diff --git a/openapiv3.go b/openapiv3.go index 499edeb..f0dffb4 100644 --- a/openapiv3.go +++ b/openapiv3.go @@ -24,7 +24,7 @@ import ( "strings" "go.unistack.org/micro-proto/v3/api" - v2 "go.unistack.org/micro-proto/v3/openapiv2" + // v2 "go.unistack.org/micro-proto/v3/openapiv2" v3 "go.unistack.org/micro-proto/v3/openapiv3" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/proto" @@ -245,12 +245,14 @@ func (g *openapiv3Generator) addPathsToDocumentV3(d *v3.Document, file *protogen outputMessage := method.Output operationID := service.GoName + "_" + method.GoName - e2opt := proto.GetExtension(method.Desc.Options(), v2.E_Openapiv2Operation) - if e2opt != nil && e2opt != v2.E_Openapiv2Operation.InterfaceOf(v2.E_Openapiv2Operation.Zero()) { - if opt, ok := e2opt.(*v2.Operation); ok && opt.OperationId != "" { - operationID = opt.OperationId + /* + e2opt := proto.GetExtension(method.Desc.Options(), v2.E_Openapiv2Operation) + if e2opt != nil && e2opt != v2.E_Openapiv2Operation.InterfaceOf(v2.E_Openapiv2Operation.Zero()) { + if opt, ok := e2opt.(*v2.Operation); ok && opt.OperationId != "" { + operationID = opt.OperationId + } } - } + */ e3opt := proto.GetExtension(method.Desc.Options(), v3.E_Openapiv3Operation) if e3opt != nil && e3opt != v3.E_Openapiv3Operation.InterfaceOf(v3.E_Openapiv3Operation.Zero()) { if opt, ok := e3opt.(*v3.Operation); ok && opt.OperationId != "" { @@ -520,6 +522,21 @@ func (g *openapiv3Generator) buildOperationV3( sparameters[parameter.Name] = struct{}{} } + if u, err := url.Parse(path); err == nil { + mp := u.Query() + path = u.Path + if mp != nil { + for _, field := range inputMessage.Fields { + fieldName := string(field.Desc.Name()) + if _, ok := mp[fieldName]; ok && fieldName != bodyField { + fieldParams := g.buildQueryParamsV3(field) + parameters = append(parameters, fieldParams...) + coveredParameters = append(coveredParameters, fieldName) + } + } + } + } + // Find simple path parameters like {id} if allMatches := g.pathPattern.FindAllStringSubmatch(path, -1); allMatches != nil { for _, matches := range allMatches { @@ -692,6 +709,8 @@ func (g *openapiv3Generator) buildOperationV3( } } + ctype := getMediaType(eopt) + op.RequestBody = &v3.RequestBodyOrReference{ Oneof: &v3.RequestBodyOrReference_RequestBody{ RequestBody: &v3.RequestBody{ @@ -699,7 +718,7 @@ func (g *openapiv3Generator) buildOperationV3( Content: &v3.MediaTypes{ AdditionalProperties: []*v3.NamedMediaType{ { - Name: "application/json", + Name: ctype, Value: &v3.MediaType{ Schema: requestSchema, }, diff --git a/openapiv3_util.go b/openapiv3_util.go new file mode 100644 index 0000000..86e8689 --- /dev/null +++ b/openapiv3_util.go @@ -0,0 +1,39 @@ +package main + +import v3 "go.unistack.org/micro-proto/v3/openapiv3" + +func getMediaType(eopt interface{}) string { + ctype := "application/json" + + if eopt == nil { + return ctype + } + + if eopt == v3.E_Openapiv3Operation.InterfaceOf(v3.E_Openapiv3Operation.Zero()) { + return ctype + } + + opt, ok := eopt.(*v3.Operation) + if !ok || opt.RequestBody == nil { + return ctype + } + + if opt.GetRequestBody() == nil { + return ctype + } + + if opt.GetRequestBody().GetRequestBody() == nil { + return ctype + } + + c := opt.GetRequestBody().GetRequestBody().GetContent() + if c == nil { + return ctype + } + + for _, prop := range c.GetAdditionalProperties() { + ctype = prop.Name + } + + return ctype +} diff --git a/util.go b/util.go index 5c771b7..3dc1e63 100644 --- a/util.go +++ b/util.go @@ -55,6 +55,9 @@ func generateServiceClientMethods(gfile *protogen.GeneratedFile, service *protog opts := proto.GetExtension(method.Desc.Options(), v2.E_Openapiv2Operation) if opts != nil { r := opts.(*v2.Operation) + if r.Responses == nil { + goto labelMethod + } gfile.P("errmap := make(map[string]interface{}, ", len(r.Responses.ResponseCode), ")") for _, rsp := range r.Responses.ResponseCode { if schema := rsp.Value.GetJsonReference(); schema != nil { @@ -84,8 +87,15 @@ func generateServiceClientMethods(gfile *protogen.GeneratedFile, service *protog opts := proto.GetExtension(method.Desc.Options(), v3.E_Openapiv3Operation) if opts != nil { r := opts.(*v3.Operation) - gfile.P("errmap := make(map[string]interface{}, ", len(r.Responses.ResponseOrReference), ")") - for _, rsp := range r.Responses.ResponseOrReference { + if r.Responses == nil { + goto labelMethod + } + resps := r.Responses.ResponseOrReference + if r.Responses.GetDefault() != nil { + resps = append(resps, &v3.NamedResponseOrReference{Name: "default", Value: r.Responses.GetDefault()}) + } + gfile.P("errmap := make(map[string]interface{}, ", len(resps), ")") + for _, rsp := range resps { if schema := rsp.Value.GetReference(); schema != nil { ref := schema.XRef if strings.HasPrefix(ref, "."+string(service.Desc.ParentFile().Package())+".") { @@ -110,6 +120,7 @@ func generateServiceClientMethods(gfile *protogen.GeneratedFile, service *protog gfile.P(")") } + labelMethod: if proto.HasExtension(method.Desc.Options(), api_options.E_Http) { gfile.P("opts = append(opts,") endpoints, _ := generateEndpoints(method)