66 "errors"
77 "fmt"
88 "net/url"
9+ "sort"
910 "strings"
1011
1112 "github.com/getkin/kin-openapi/openapi2"
@@ -46,7 +47,7 @@ func ToV3Swagger(swagger *openapi2.Swagger) (*openapi3.Swagger, error) {
4647 result .Components .Parameters = make (map [string ]* openapi3.ParameterRef )
4748 result .Components .RequestBodies = make (map [string ]* openapi3.RequestBodyRef )
4849 for k , parameter := range parameters {
49- v3Parameter , v3RequestBody , v3SchemaMap , err := ToV3Parameter (& result .Components , parameter )
50+ v3Parameter , v3RequestBody , v3SchemaMap , err := ToV3Parameter (& result .Components , parameter , swagger . Consumes )
5051 switch {
5152 case err != nil :
5253 return nil , err
@@ -65,7 +66,7 @@ func ToV3Swagger(swagger *openapi2.Swagger) (*openapi3.Swagger, error) {
6566 if paths := swagger .Paths ; len (paths ) != 0 {
6667 resultPaths := make (map [string ]* openapi3.PathItem , len (paths ))
6768 for path , pathItem := range paths {
68- r , err := ToV3PathItem (swagger , & result .Components , pathItem )
69+ r , err := ToV3PathItem (swagger , & result .Components , pathItem , swagger . Consumes )
6970 if err != nil {
7071 return nil , err
7172 }
@@ -111,20 +112,20 @@ func ToV3Swagger(swagger *openapi2.Swagger) (*openapi3.Swagger, error) {
111112 return result , nil
112113}
113114
114- func ToV3PathItem (swagger * openapi2.Swagger , components * openapi3.Components , pathItem * openapi2.PathItem ) (* openapi3.PathItem , error ) {
115+ func ToV3PathItem (swagger * openapi2.Swagger , components * openapi3.Components , pathItem * openapi2.PathItem , consumes [] string ) (* openapi3.PathItem , error ) {
115116 stripNonCustomExtensions (pathItem .Extensions )
116117 result := & openapi3.PathItem {
117118 ExtensionProps : pathItem .ExtensionProps ,
118119 }
119120 for method , operation := range pathItem .Operations () {
120- resultOperation , err := ToV3Operation (swagger , components , pathItem , operation )
121+ resultOperation , err := ToV3Operation (swagger , components , pathItem , operation , consumes )
121122 if err != nil {
122123 return nil , err
123124 }
124125 result .SetOperation (method , resultOperation )
125126 }
126127 for _ , parameter := range pathItem .Parameters {
127- v3Parameter , v3RequestBody , v3Schema , err := ToV3Parameter (components , parameter )
128+ v3Parameter , v3RequestBody , v3Schema , err := ToV3Parameter (components , parameter , consumes )
128129 switch {
129130 case err != nil :
130131 return nil , err
@@ -139,7 +140,7 @@ func ToV3PathItem(swagger *openapi2.Swagger, components *openapi3.Components, pa
139140 return result , nil
140141}
141142
142- func ToV3Operation (swagger * openapi2.Swagger , components * openapi3.Components , pathItem * openapi2.PathItem , operation * openapi2.Operation ) (* openapi3.Operation , error ) {
143+ func ToV3Operation (swagger * openapi2.Swagger , components * openapi3.Components , pathItem * openapi2.PathItem , operation * openapi2.Operation , consumes [] string ) (* openapi3.Operation , error ) {
143144 if operation == nil {
144145 return nil , nil
145146 }
@@ -156,10 +157,14 @@ func ToV3Operation(swagger *openapi2.Swagger, components *openapi3.Components, p
156157 result .Security = & resultSecurity
157158 }
158159
160+ if len (operation .Consumes ) > 0 {
161+ consumes = operation .Consumes
162+ }
163+
159164 var reqBodies []* openapi3.RequestBodyRef
160165 formDataSchemas := make (map [string ]* openapi3.SchemaRef )
161166 for _ , parameter := range operation .Parameters {
162- v3Parameter , v3RequestBody , v3SchemaMap , err := ToV3Parameter (components , parameter )
167+ v3Parameter , v3RequestBody , v3SchemaMap , err := ToV3Parameter (components , parameter , consumes )
163168 switch {
164169 case err != nil :
165170 return nil , err
@@ -174,7 +179,7 @@ func ToV3Operation(swagger *openapi2.Swagger, components *openapi3.Components, p
174179 }
175180 }
176181 var err error
177- if result .RequestBody , err = onlyOneReqBodyParam (reqBodies , formDataSchemas , components ); err != nil {
182+ if result .RequestBody , err = onlyOneReqBodyParam (reqBodies , formDataSchemas , components , consumes ); err != nil {
178183 return nil , err
179184 }
180185
@@ -199,7 +204,7 @@ func getParameterNameFromOldRef(ref string) string {
199204 return pathSections [0 ]
200205}
201206
202- func ToV3Parameter (components * openapi3.Components , parameter * openapi2.Parameter ) (* openapi3.ParameterRef , * openapi3.RequestBodyRef , map [string ]* openapi3.SchemaRef , error ) {
207+ func ToV3Parameter (components * openapi3.Components , parameter * openapi2.Parameter , consumes [] string ) (* openapi3.ParameterRef , * openapi3.RequestBodyRef , map [string ]* openapi3.SchemaRef , error ) {
203208 if ref := parameter .Ref ; ref != "" {
204209 if strings .HasPrefix (ref , "#/parameters/" ) {
205210 name := getParameterNameFromOldRef (ref )
@@ -233,7 +238,7 @@ func ToV3Parameter(components *openapi3.Components, parameter *openapi2.Paramete
233238
234239 if schemaRef := parameter .Schema ; schemaRef != nil {
235240 // Assuming JSON
236- result .WithJSONSchemaRef (ToV3SchemaRef (schemaRef ))
241+ result .WithSchemaRef (ToV3SchemaRef (schemaRef ), consumes )
237242 }
238243 return nil , & openapi3.RequestBodyRef {Value : result }, nil , nil
239244
@@ -314,7 +319,7 @@ func ToV3Parameter(components *openapi3.Components, parameter *openapi2.Paramete
314319 }
315320}
316321
317- func formDataBody (bodies map [string ]* openapi3.SchemaRef , reqs map [string ]bool ) * openapi3.RequestBodyRef {
322+ func formDataBody (bodies map [string ]* openapi3.SchemaRef , reqs map [string ]bool , consumes [] string ) * openapi3.RequestBodyRef {
318323 if len (bodies ) != len (reqs ) {
319324 panic (`request bodies and them being required must match` )
320325 }
@@ -333,7 +338,7 @@ func formDataBody(bodies map[string]*openapi3.SchemaRef, reqs map[string]bool) *
333338 Required : requireds ,
334339 }
335340 return & openapi3.RequestBodyRef {
336- Value : openapi3 .NewRequestBody ().WithFormDataSchema (schema ),
341+ Value : openapi3 .NewRequestBody ().WithSchema (schema , consumes ),
337342 }
338343}
339344
@@ -344,7 +349,7 @@ func getParameterNameFromNewRef(ref string) string {
344349 return pathSections [0 ]
345350}
346351
347- func onlyOneReqBodyParam (bodies []* openapi3.RequestBodyRef , formDataSchemas map [string ]* openapi3.SchemaRef , components * openapi3.Components ) (* openapi3.RequestBodyRef , error ) {
352+ func onlyOneReqBodyParam (bodies []* openapi3.RequestBodyRef , formDataSchemas map [string ]* openapi3.SchemaRef , components * openapi3.Components , consumes [] string ) (* openapi3.RequestBodyRef , error ) {
348353 if len (bodies ) > 1 {
349354 return nil , errors .New ("multiple body parameters cannot exist for the same operation" )
350355 }
@@ -386,7 +391,7 @@ func onlyOneReqBodyParam(bodies []*openapi3.RequestBodyRef, formDataSchemas map[
386391 }
387392 }
388393
389- return formDataBody (formDataParams , formDataReqs ), nil
394+ return formDataBody (formDataParams , formDataReqs , consumes ), nil
390395 }
391396
392397 return nil , nil
@@ -601,25 +606,23 @@ func FromV3Swagger(swagger *openapi3.Swagger) (*openapi2.Swagger, error) {
601606 }
602607 }
603608
604- for name , requestBody := range swagger .Components .RequestBodies {
605- parameters := FromV3RequestBodyFormData ( requestBody )
606- for _ , param := range parameters {
607- result . Parameters [ param . Name ] = param
609+ for name , requestBodyRef := range swagger .Components .RequestBodies {
610+ bodyOrRefParameters , formDataParameters , consumes , err := FromV3RequestBodies ( name , requestBodyRef , & swagger . Components )
611+ if err != nil {
612+ return nil , err
608613 }
609-
610- if len (parameters ) == 0 {
611- paramName := name
612- if requestBody .Value != nil {
613- if originalName , ok := requestBody .Value .Extensions ["x-originalParamName" ]; ok {
614- json .Unmarshal (originalName .(json.RawMessage ), & paramName )
615- }
614+ if len (* formDataParameters ) != 0 {
615+ for _ , param := range * formDataParameters {
616+ result .Parameters [param .Name ] = param
616617 }
617-
618- r , err := FromV3RequestBody (swagger , paramName , requestBody )
619- if err != nil {
620- return nil , err
618+ } else if len (* bodyOrRefParameters ) != 0 {
619+ for _ , param := range * bodyOrRefParameters {
620+ result .Parameters [name ] = param
621621 }
622- result .Parameters [name ] = r
622+ }
623+
624+ if len (consumes ) != 0 {
625+ result .Consumes = consumesToArray (consumes )
623626 }
624627 }
625628
@@ -638,6 +641,49 @@ func FromV3Swagger(swagger *openapi3.Swagger) (*openapi2.Swagger, error) {
638641 return result , nil
639642}
640643
644+ func consumesToArray (consumes map [string ]bool ) []string {
645+ var consumesArr []string
646+ for key , _ := range consumes {
647+ consumesArr = append (consumesArr , key )
648+ }
649+ sort .Strings (consumesArr )
650+ return consumesArr
651+ }
652+
653+ func FromV3RequestBodies (name string , requestBodyRef * openapi3.RequestBodyRef , components * openapi3.Components ) (* openapi2.Parameters , * openapi2.Parameters , map [string ]bool , error ) {
654+ formParameters := openapi2.Parameters {}
655+ bodyOrRefParameters := openapi2.Parameters {}
656+ if ref := requestBodyRef .Ref ; ref != "" {
657+ bodyOrRefParameters = append (bodyOrRefParameters , & openapi2.Parameter {Ref : FromV3Ref (ref )})
658+ return & bodyOrRefParameters , & formParameters , nil , nil
659+ }
660+
661+ //Only select one formData or request body for an individual requesstBody as swagger 2 does not support multiples
662+ consumes := make (map [string ]bool )
663+ if requestBodyRef .Value != nil {
664+ for contentType , mediaType := range requestBodyRef .Value .Content {
665+ //add each type to the consumes array
666+ consumes [contentType ] = true
667+ formParams := FromV3RequestBodyFormData (mediaType )
668+ if len (formParams ) != 0 {
669+ formParameters = formParams
670+ } else {
671+ paramName := name
672+ if originalName , ok := requestBodyRef .Value .Extensions ["x-originalParamName" ]; ok {
673+ json .Unmarshal (originalName .(json.RawMessage ), & paramName )
674+ }
675+
676+ r , err := FromV3RequestBody (paramName , requestBodyRef , mediaType , components )
677+ if err != nil {
678+ return & bodyOrRefParameters , & formParameters , consumes , err
679+ }
680+ bodyOrRefParameters = append (bodyOrRefParameters , r )
681+ }
682+ }
683+ }
684+ return & bodyOrRefParameters , & formParameters , consumes , nil
685+ }
686+
641687func FromV3Schemas (schemas map [string ]* openapi3.SchemaRef , components * openapi3.Components ) (map [string ]* openapi3.SchemaRef , map [string ]* openapi2.Parameter ) {
642688 v2Defs := make (map [string ]* openapi3.SchemaRef )
643689 v2Params := make (map [string ]* openapi2.Parameter )
@@ -770,11 +816,7 @@ nameSearch:
770816 return ""
771817}
772818
773- func FromV3RequestBodyFormData (requestBodyRef * openapi3.RequestBodyRef ) openapi2.Parameters {
774- mediaType := requestBodyRef .Value .GetMediaType ("multipart/form-data" )
775- if mediaType == nil {
776- return nil
777- }
819+ func FromV3RequestBodyFormData (mediaType * openapi3.MediaType ) openapi2.Parameters {
778820 parameters := openapi2.Parameters {}
779821 for propName , schemaRef := range mediaType .Schema .Value .Properties {
780822 if ref := schemaRef .Ref ; ref != "" {
@@ -848,27 +890,30 @@ func FromV3Operation(swagger *openapi3.Swagger, operation *openapi3.Operation) (
848890 result .Parameters = append (result .Parameters , r )
849891 }
850892 if v := operation .RequestBody ; v != nil {
851- parameters := FromV3RequestBodyFormData (operation .RequestBody )
852- if len (parameters ) > 0 {
853- result .Parameters = append (result .Parameters , parameters ... )
854- } else {
855- // Find parameter name that we can use for the body
856- name := findNameForRequestBody (operation )
857- if name == "" {
858- return nil , errors .New ("could not find a name for request body" )
859- }
860- r , err := FromV3RequestBody (swagger , name , v )
861- if err != nil {
862- return nil , err
893+ // Find parameter name that we can use for the body
894+ name := findNameForRequestBody (operation )
895+ if name == "" {
896+ return nil , errors .New ("could not find a name for request body" )
897+ }
898+
899+ bodyOrRefParameters , formDataParameters , consumes , err := FromV3RequestBodies (name , v , & swagger .Components )
900+ if err != nil {
901+ return nil , err
902+ }
903+ if len (* formDataParameters ) != 0 {
904+ result .Parameters = append (result .Parameters , * formDataParameters ... )
905+ } else if len (* bodyOrRefParameters ) != 0 {
906+ //add a single request body
907+ for i , param := range * bodyOrRefParameters {
908+ if i == 0 {
909+ result .Parameters = append (result .Parameters , param )
910+ }
863911 }
864- result . Parameters = append ( result . Parameters , r )
912+
865913 }
866- }
867914
868- for _ , param := range result .Parameters {
869- if param .Type == "file" {
870- result .Consumes = append (result .Consumes , "multipart/form-data" )
871- break
915+ if len (consumes ) != 0 {
916+ result .Consumes = consumesToArray (consumes )
872917 }
873918 }
874919
@@ -882,10 +927,7 @@ func FromV3Operation(swagger *openapi3.Swagger, operation *openapi3.Operation) (
882927 return result , nil
883928}
884929
885- func FromV3RequestBody (swagger * openapi3.Swagger , name string , requestBodyRef * openapi3.RequestBodyRef ) (* openapi2.Parameter , error ) {
886- if ref := requestBodyRef .Ref ; ref != "" {
887- return & openapi2.Parameter {Ref : FromV3Ref (ref )}, nil
888- }
930+ func FromV3RequestBody (name string , requestBodyRef * openapi3.RequestBodyRef , mediaType * openapi3.MediaType , components * openapi3.Components ) (* openapi2.Parameter , error ) {
889931 requestBody := requestBodyRef .Value
890932
891933 stripNonCustomExtensions (requestBody .Extensions )
@@ -897,10 +939,8 @@ func FromV3RequestBody(swagger *openapi3.Swagger, name string, requestBodyRef *o
897939 ExtensionProps : requestBody .ExtensionProps ,
898940 }
899941
900- // Assuming JSON
901- mediaType := requestBody .GetMediaType ("application/json" )
902942 if mediaType != nil {
903- result .Schema , _ = FromV3SchemaRef (mediaType .Schema , & swagger . Components )
943+ result .Schema , _ = FromV3SchemaRef (mediaType .Schema , components )
904944 }
905945 return result , nil
906946}
0 commit comments