Skip to content

Commit 5249a0b

Browse files
authored
Amend #204 to fix a edge case (#205)
* nit Signed-off-by: Pierre Fenoll <pierrefenoll@gmail.com> * update / cleanup deps Signed-off-by: Pierre Fenoll <pierrefenoll@gmail.com> * ensure response descriptions are not set when they shouldnt while still sat #185 Signed-off-by: Pierre Fenoll <pierrefenoll@gmail.com> * address some lint warnings on slices Signed-off-by: Pierre Fenoll <pierrefenoll@gmail.com>
1 parent 6f2d174 commit 5249a0b

15 files changed

+161
-65
lines changed

go.mod

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
module github.com/getkin/kin-openapi
22

3+
go 1.14
4+
35
require (
4-
github.com/davecgh/go-spew v1.1.1 // indirect
56
github.com/ghodss/yaml v1.0.0
6-
github.com/kr/pretty v0.1.0 // indirect
7-
github.com/stretchr/testify v1.3.0
8-
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
7+
github.com/stretchr/testify v1.5.1
98
gopkg.in/yaml.v2 v2.2.8 // indirect
109
)
11-
12-
go 1.13

go.sum

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
12
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2-
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3-
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
43
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
54
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
6-
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
7-
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
8-
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
9-
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
10-
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
115
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
126
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
137
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
14-
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
15-
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
16-
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
8+
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
9+
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
1710
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
18-
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
19-
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
11+
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
2012
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
2113
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

jsoninfo/type_info.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ func GetTypeInfo(t reflect.Type) *TypeInfo {
6060
// FieldNames returns all field names
6161
func (typeInfo *TypeInfo) FieldNames() []string {
6262
fields := typeInfo.Fields
63-
names := make([]string, len(fields))
64-
for i, field := range fields {
65-
names[i] = field.JSONName
63+
names := make([]string, 0, len(fields))
64+
for _, field := range fields {
65+
names = append(names, field.JSONName)
6666
}
6767
return names
6868
}

openapi2conv/openapi2_conv.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func ToV3Response(response *openapi2.Response) (*openapi3.ResponseRef, error) {
209209
}, nil
210210
}
211211
result := &openapi3.Response{
212-
Description: response.Description,
212+
Description: &response.Description,
213213
}
214214
if schemaRef := response.Schema; schemaRef != nil {
215215
result.WithJSONSchemaRef(ToV3SchemaRef(schemaRef))
@@ -594,8 +594,12 @@ func FromV3Response(ref *openapi3.ResponseRef) (*openapi2.Response, error) {
594594
if response == nil {
595595
return nil, nil
596596
}
597+
description := ""
598+
if desc := response.Description; desc != nil {
599+
description = *desc
600+
}
597601
result := &openapi2.Response{
598-
Description: response.Description,
602+
Description: description,
599603
}
600604
if content := response.Content; content != nil {
601605
if ct := content["application/json"]; ct != nil {

openapi3/link.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package openapi3
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67

78
"github.com/getkin/kin-openapi/jsoninfo"
@@ -28,7 +29,7 @@ func (value *Link) UnmarshalJSON(data []byte) error {
2829

2930
func (value *Link) Validate(c context.Context) error {
3031
if value.OperationID == "" && value.OperationRef == "" {
31-
return fmt.Errorf("missing operationId or operationRef on link")
32+
return errors.New("missing operationId or operationRef on link")
3233
}
3334
if value.OperationID != "" && value.OperationRef != "" {
3435
return fmt.Errorf("operationId '%s' and operationRef '%s' are mutually exclusive", value.OperationID, value.OperationRef)

openapi3/operation_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func operationWithoutResponses() *Operation {
4040

4141
func operationWithResponses() *Operation {
4242
initOperation()
43-
operation.AddResponse(200, NewResponse())
43+
operation.AddResponse(200, NewResponse().WithDescription("some response"))
4444
return operation
4545
}
4646

openapi3/response.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package openapi3
22

33
import (
44
"context"
5+
"errors"
56
"strconv"
67

78
"github.com/getkin/kin-openapi/jsoninfo"
@@ -34,7 +35,7 @@ func (responses Responses) Validate(c context.Context) error {
3435
// Response is specified by OpenAPI/Swagger 3.0 standard.
3536
type Response struct {
3637
ExtensionProps
37-
Description string `json:"description" yaml:"description"`
38+
Description *string `json:"description,omitempty" yaml:"description,omitempty"`
3839
Headers map[string]*HeaderRef `json:"headers,omitempty" yaml:"headers,omitempty"`
3940
Content Content `json:"content,omitempty" yaml:"content,omitempty"`
4041
Links map[string]*LinkRef `json:"links,omitempty" yaml:"links,omitempty"`
@@ -45,7 +46,7 @@ func NewResponse() *Response {
4546
}
4647

4748
func (response *Response) WithDescription(value string) *Response {
48-
response.Description = value
49+
response.Description = &value
4950
return response
5051
}
5152

@@ -73,6 +74,10 @@ func (response *Response) UnmarshalJSON(data []byte) error {
7374
}
7475

7576
func (response *Response) Validate(c context.Context) error {
77+
if response.Description == nil {
78+
return errors.New("A short description of the response is required")
79+
}
80+
7681
if content := response.Content; content != nil {
7782
if err := content.Validate(c); err != nil {
7883
return err

openapi3/schema.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -122,29 +122,29 @@ func (schema *Schema) NewRef() *SchemaRef {
122122
}
123123

124124
func NewOneOfSchema(schemas ...*Schema) *Schema {
125-
refs := make([]*SchemaRef, len(schemas))
126-
for i, schema := range schemas {
127-
refs[i] = &SchemaRef{Value: schema}
125+
refs := make([]*SchemaRef, 0, len(schemas))
126+
for _, schema := range schemas {
127+
refs = append(refs, &SchemaRef{Value: schema})
128128
}
129129
return &Schema{
130130
OneOf: refs,
131131
}
132132
}
133133

134134
func NewAnyOfSchema(schemas ...*Schema) *Schema {
135-
refs := make([]*SchemaRef, len(schemas))
136-
for i, schema := range schemas {
137-
refs[i] = &SchemaRef{Value: schema}
135+
refs := make([]*SchemaRef, 0, len(schemas))
136+
for _, schema := range schemas {
137+
refs = append(refs, &SchemaRef{Value: schema})
138138
}
139139
return &Schema{
140140
AnyOf: refs,
141141
}
142142
}
143143

144144
func NewAllOfSchema(schemas ...*Schema) *Schema {
145-
refs := make([]*SchemaRef, len(schemas))
146-
for i, schema := range schemas {
147-
refs[i] = &SchemaRef{Value: schema}
145+
refs := make([]*SchemaRef, 0, len(schemas))
146+
for _, schema := range schemas {
147+
refs = append(refs, &SchemaRef{Value: schema})
148148
}
149149
return &Schema{
150150
AllOf: refs,
@@ -439,7 +439,7 @@ func (schema *Schema) IsEmpty() bool {
439439
}
440440

441441
func (schema *Schema) Validate(c context.Context) error {
442-
return schema.validate(c, make([]*Schema, 2))
442+
return schema.validate(c, []*Schema{})
443443
}
444444

445445
func (schema *Schema) validate(c context.Context, stack []*Schema) (err error) {
@@ -1158,9 +1158,9 @@ func markSchemaErrorIndex(err error, index int) error {
11581158

11591159
func (err *SchemaError) JSONPointer() []string {
11601160
reversePath := err.reversePath
1161-
path := make([]string, len(reversePath))
1162-
for i := range path {
1163-
path[i] = reversePath[len(path)-1-i]
1161+
path := append([]string(nil), reversePath...)
1162+
for left, right := 0, len(path)-1; left < right; left, right = left+1, right-1 {
1163+
path[left], path[right] = path[right], path[left]
11641164
}
11651165
return path
11661166
}

openapi3/schema_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,16 +319,16 @@ var schemaExamples = []schemaExample{
319319
AllValid: []interface{}{
320320
"",
321321
base64.StdEncoding.EncodeToString(func() []byte {
322-
data := make([]byte, 1024)
323-
for i := range data {
324-
data[i] = byte(i)
322+
data := make([]byte, 0, 1024)
323+
for i := 0; i < cap(data); i++ {
324+
data = append(data, byte(i))
325325
}
326326
return data
327327
}()),
328328
base64.URLEncoding.EncodeToString(func() []byte {
329-
data := make([]byte, 1024)
330-
for i := range data {
331-
data[i] = byte(i)
329+
data := make([]byte, 0, 1024)
330+
for i := 0; i < cap(data); i++ {
331+
data = append(data, byte(i))
332332
}
333333
return data
334334
}()),
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package openapi3_test
2+
3+
import (
4+
"encoding/json"
5+
"strings"
6+
"testing"
7+
8+
"github.com/getkin/kin-openapi/openapi3"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func TestJSONSpecResponseDescriptionEmptiness(t *testing.T) {
13+
const spec = `
14+
{
15+
"info": {
16+
"description": "A sample API to illustrate OpenAPI concepts",
17+
"title": "Sample API",
18+
"version": "1.0.0"
19+
},
20+
"openapi": "3.0.0",
21+
"paths": {
22+
"/path1": {
23+
"get": {
24+
"responses": {
25+
"200": {
26+
"description": ""
27+
}
28+
}
29+
}
30+
}
31+
}
32+
}
33+
`
34+
35+
{
36+
spec := []byte(spec)
37+
loader := openapi3.NewSwaggerLoader()
38+
doc, err := loader.LoadSwaggerFromData(spec)
39+
require.NoError(t, err)
40+
got := doc.Paths["/path1"].Get.Responses["200"].Value.Description
41+
expected := ""
42+
require.Equal(t, &expected, got)
43+
t.Log("Empty description provided: valid spec")
44+
err = doc.Validate(loader.Context)
45+
require.NoError(t, err)
46+
}
47+
48+
{
49+
spec := []byte(strings.Replace(spec, `"description": ""`, `"description": "My response"`, 1))
50+
loader := openapi3.NewSwaggerLoader()
51+
doc, err := loader.LoadSwaggerFromData(spec)
52+
require.NoError(t, err)
53+
got := doc.Paths["/path1"].Get.Responses["200"].Value.Description
54+
expected := "My response"
55+
require.Equal(t, &expected, got)
56+
t.Log("Non-empty description provided: valid spec")
57+
err = doc.Validate(loader.Context)
58+
require.NoError(t, err)
59+
}
60+
61+
noDescriptionIsInvalid := func(data []byte) *openapi3.Swagger {
62+
loader := openapi3.NewSwaggerLoader()
63+
doc, err := loader.LoadSwaggerFromData(data)
64+
require.NoError(t, err)
65+
got := doc.Paths["/path1"].Get.Responses["200"].Value.Description
66+
require.Nil(t, got)
67+
t.Log("No description provided: invalid spec")
68+
err = doc.Validate(loader.Context)
69+
require.Error(t, err)
70+
return doc
71+
}
72+
73+
var docWithNoResponseDescription *openapi3.Swagger
74+
{
75+
spec := []byte(strings.Replace(spec, `"description": ""`, ``, 1))
76+
docWithNoResponseDescription = noDescriptionIsInvalid(spec)
77+
}
78+
79+
str, err := json.Marshal(docWithNoResponseDescription)
80+
require.NoError(t, err)
81+
require.NotEmpty(t, str)
82+
t.Log("Reserialization does not set description")
83+
_ = noDescriptionIsInvalid(str)
84+
}

0 commit comments

Comments
 (0)