From 0846d700650012c02a16668ebd2bf1e77e9a1669 Mon Sep 17 00:00:00 2001 From: Sergey Vilgelm Date: Thu, 3 Feb 2022 11:26:53 -0800 Subject: [PATCH] openapi2conv: Convert response headers (#483) --- openapi2/openapi2.go | 5 +--- openapi2conv/openapi2_conv.go | 42 ++++++++++++++++++++++++++++++ openapi2conv/openapi2_conv_test.go | 21 +++++++++++++-- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/openapi2/openapi2.go b/openapi2/openapi2.go index 0d8c07228..de9247f67 100644 --- a/openapi2/openapi2.go +++ b/openapi2/openapi2.go @@ -232,10 +232,7 @@ func (response *Response) UnmarshalJSON(data []byte) error { } type Header struct { - openapi3.ExtensionProps - Ref string `json:"$ref,omitempty" yaml:"$ref,omitempty"` - Description string `json:"description,omitempty" yaml:"description,omitempty"` - Type string `json:"type,omitempty" yaml:"type,omitempty"` + Parameter } func (header *Header) MarshalJSON() ([]byte, error) { diff --git a/openapi2conv/openapi2_conv.go b/openapi2conv/openapi2_conv.go index 04cb18d2e..4177f1f55 100644 --- a/openapi2conv/openapi2_conv.go +++ b/openapi2conv/openapi2_conv.go @@ -424,9 +424,29 @@ func ToV3Response(response *openapi2.Response) (*openapi3.ResponseRef, error) { if schemaRef := response.Schema; schemaRef != nil { result.WithJSONSchemaRef(ToV3SchemaRef(schemaRef)) } + if headers := response.Headers; len(headers) > 0 { + result.Headers = ToV3Headers(headers) + } return &openapi3.ResponseRef{Value: result}, nil } +func ToV3Headers(defs map[string]*openapi2.Header) openapi3.Headers { + headers := make(openapi3.Headers, len(defs)) + for name, header := range defs { + header.In = "" + header.Name = "" + if ref := header.Ref; ref != "" { + headers[name] = &openapi3.HeaderRef{Ref: ToV3Ref(ref)} + } else { + parameter, _, _, _ := ToV3Parameter(nil, &header.Parameter, nil) + headers[name] = &openapi3.HeaderRef{Value: &openapi3.Header{ + Parameter: *parameter.Value, + }} + } + } + return headers +} + func ToV3Schemas(defs map[string]*openapi3.SchemaRef) map[string]*openapi3.SchemaRef { schemas := make(map[string]*openapi3.SchemaRef, len(defs)) for name, schema := range defs { @@ -654,6 +674,7 @@ func FromV3(doc3 *openapi3.T) (*openapi2.T, error) { doc2.SecurityDefinitions = doc2SecuritySchemes } doc2.Security = FromV3SecurityRequirements(doc3.Security) + return doc2, nil } @@ -1048,9 +1069,30 @@ func FromV3Response(ref *openapi3.ResponseRef, components *openapi3.Components) result.Schema, _ = FromV3SchemaRef(ct.Schema, components) } } + if headers := response.Headers; len(headers) > 0 { + var err error + if result.Headers, err = FromV3Headers(headers, components); err != nil { + return nil, err + } + } return result, nil } +func FromV3Headers(defs openapi3.Headers, components *openapi3.Components) (map[string]*openapi2.Header, error) { + headers := make(map[string]*openapi2.Header, len(defs)) + for name, header := range defs { + ref := openapi3.ParameterRef{Ref: header.Ref, Value: &header.Value.Parameter} + parameter, err := FromV3Parameter(&ref, components) + if err != nil { + return nil, err + } + parameter.In = "" + parameter.Name = "" + headers[name] = &openapi2.Header{Parameter: *parameter} + } + return headers, nil +} + func FromV3SecurityScheme(doc3 *openapi3.T, ref *openapi3.SecuritySchemeRef) (*openapi2.SecurityScheme, error) { securityScheme := ref.Value if securityScheme == nil { diff --git a/openapi2conv/openapi2_conv_test.go b/openapi2conv/openapi2_conv_test.go index f8f287836..24ead5610 100644 --- a/openapi2conv/openapi2_conv_test.go +++ b/openapi2conv/openapi2_conv_test.go @@ -5,9 +5,10 @@ import ( "encoding/json" "testing" + "github.com/stretchr/testify/require" + "github.com/getkin/kin-openapi/openapi2" "github.com/getkin/kin-openapi/openapi3" - "github.com/stretchr/testify/require" ) func TestConvOpenAPIV3ToV2(t *testing.T) { @@ -179,6 +180,13 @@ const exampleV2 = ` "$ref": "#/definitions/Item" }, "type": "array" + }, + "headers": { + "ETag": { + "description": "The ETag (or entity tag) HTTP response header is an identifier for a specific version of a resource.", + "type": "string", + "maxLength": 64 + } } }, "404": { @@ -543,7 +551,16 @@ const exampleV3 = ` } } }, - "description": "ok" + "description": "ok", + "headers": { + "ETag": { + "description": "The ETag (or entity tag) HTTP response header is an identifier for a specific version of a resource.", + "schema": { + "type": "string", + "maxLength": 64 + } + } + } }, "404": { "description": "404 response"