func (g *jsonschema) collectPathParameters(pattern string) []map[string]interface{} { vars, err := router.ExtractVariables(pattern) if err != nil { g.gen.Error(err) return nil } params := make([]map[string]interface{}, 0, len(vars)) for _, v := range vars { param := map[string]interface{}{ "name": strings.Replace(v.Name, ".", "_", -1), "in": "path", "type": "string", //"format": } if v.Pattern != "" { param["pattern"] = v.Pattern } if v.MinCount > 0 { param["required"] = true param["minItems"] = v.MinCount } if v.MaxCount > 0 { param["maxItems"] = v.MaxCount } params = append(params, param) } return params }
// generateService generates all the code for the named service. func (g *svchttp) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) { apis := filterAPIs(service, service.Method, index) if len(apis) == 0 { return } origServName := service.GetName() fullServName := file.GetPackage() + "." + origServName servName := generator.CamelCase(origServName) gatewayVarName := "_" + servName + "_gatewayDesc" g.gen.AddInitf("%s.RegisterGatewayDesc(&%s)", g.runtimePkg.Use(), gatewayVarName) g.P(`var `, gatewayVarName, ` = `, g.runtimePkg.Use(), `.GatewayDesc{`) g.P(`ServiceName: `, strconv.Quote(fullServName), `,`) g.P(`HandlerType: ((*`, servName, `Server)(nil)),`) g.P(`Routes: []`, g.runtimePkg.Use(), `.RouteDesc{`) for _, api := range apis { _, method := api.desc, api.method httpMethod, pattern, ok := api.GetMethodAndPattern() if !ok { g.gen.Fail("xyz.featherhead.http requires a method: pattern") } if idx := strings.IndexRune(pattern, '?'); idx >= 0 { pattern = pattern[:idx] } g.P(`{`) g.P(`Method: `, strconv.Quote(httpMethod), `,`) g.P(`Pattern: `, strconv.Quote(pattern), `,`) g.P(`Handler: `, g.generateServerCallName(servName, method), `,`) g.P("},") } g.P("},") g.P("}") g.P() // Server handler implementations. for _, api := range apis { info, method := api.desc, api.method inputTypeName := method.GetInputType() inputType, _ := g.gen.ObjectNamed(inputTypeName).(*generator.Descriptor) httpMethod, pattern, ok := api.GetMethodAndPattern() queryParams := map[string]string{} if !ok { g.gen.Fail("xyz.featherhead.http requires a method: pattern") } if idx := strings.IndexRune(pattern, '?'); idx >= 0 { queryString := pattern[idx+1:] pattern = pattern[:idx] for _, pair := range strings.SplitN(queryString, "&", -1) { idx := strings.Index(pair, "={") if pair[len(pair)-1] != '}' || idx < 0 { g.gen.Fail("invalid query paramter") } queryParams[pair[:idx]] = pair[idx+2 : len(pair)-1] } } vars, err := router.ExtractVariables(pattern) if err != nil { g.gen.Error(err) return } var ( httpResponseWriter = g.httpPkg.Use() + ".ResponseWriter" httpRequest = g.httpPkg.Use() + ".Request" contextContext = g.contextPkg.Use() + ".Context" ) handlerMethod := g.generateServerCallName(servName, method) jujuErrors := g.jujuErrorsPkg.Use() g.P("func ", handlerMethod, "(srvDesc *", g.grpcPkg.Use(), ".ServiceDesc, srv interface{}, ctx ", contextContext, ", rw ", httpResponseWriter, ", req *", httpRequest, ") error {") g.P("if req.Method != ", strconv.Quote(httpMethod), "{") g.P(` return `, jujuErrors, `.MethodNotAllowedf("expected `, httpMethod, ` request")`) g.P("}") g.P() if len(vars) > 0 { routerP := g.routerPkg.Use() + ".P" g.P(`params := `, routerP, `(ctx)`) } g.P(`stream, err := `, g.runtimePkg.Use(), `.NewServerStream(ctx, rw, req, `, method.GetServerStreaming(), `, `, method.GetClientStreaming(), `, `, int(info.PageSize), `, func(x interface{}) error {`) g.P(`input := x.(*`, g.typeName(inputTypeName), `)`) g.P(`_ = input`) g.P() for param, value := range queryParams { g.P("// populate ?", param, "=", value) g.generateHttpMapping(inputType, value, "req.URL.Query().Get("+strconv.Quote(param)+")") } for _, v := range vars { g.P("// populate {", v.Name, "}") g.generateHttpMapping(inputType, v.Name, "params.Get("+strconv.Quote(v.Name)+")") } g.P(`return nil`) g.P(`})`) g.P() if !api.stream { g.P(`desc := &srvDesc.Methods[`, api.index, `]`) g.P(`output, err := desc.Handler(srv, stream.Context(), stream.RecvMsg, nil)`) g.P(`if err == nil && output == nil {`) g.P(`err = `, g.grpcPkg.Use(), `.Errorf(`, g.grpcCodesPkg.Use(), `.Internal, "internal server error")`) g.P(`}`) g.P(`if err == nil {`) g.P(`err = stream.SendMsg(output)`) g.P(`}`) } else { g.P(`desc := &srvDesc.Streams[`, api.index, `]`) g.P(`err = desc.Handler(srv, stream)`) } g.P(`if err != nil {`) g.P(`stream.SetError(err)`) g.P(`}`) g.P() g.P(`return stream.CloseSend()`) g.P("}") g.P() } }