Skip to content

Commit

Permalink
Merge 54675d1 into a3046bf
Browse files Browse the repository at this point in the history
  • Loading branch information
Nerzal authored Apr 14, 2023
2 parents a3046bf + 54675d1 commit bddf978
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 14 deletions.
91 changes: 80 additions & 11 deletions operationv3.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ type OperationV3 struct {
parser *Parser
codeExampleFilesDir string
spec.Operation
RouterProperties []RouteProperties
RouterProperties []RouteProperties
responseMimeTypes []string
}

// NewOperationV3 returns a new instance of OperationV3.
Expand Down Expand Up @@ -177,6 +178,7 @@ func (o *OperationV3) ParseAcceptComment(commentLine string) error {
"application/octet-stream",
"application/pdf",
"application/msexcel",
"application/zip",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.openxmlformats-officedocument.presentationml.presentation":
Expand All @@ -196,19 +198,84 @@ func (o *OperationV3) ParseAcceptComment(commentLine string) error {
// ParseProduceComment parses comment for given `produce` comment string.
func (o *OperationV3) ParseProduceComment(commentLine string) error {
const errMessage = "could not parse produce comment"
// return parseMimeTypeList(commentLine, &o.Responses, "%v produce type can't be accepted")

// result, err := parseMimeTypeListV3(commentLine, "%v accept type can't be accepted")
// if err != nil {
// return errors.Wrap(err, errMessage)
// }
validTypes, err := parseMimeTypeListV3(commentLine, "%v produce type can't be accepted")
if err != nil {
return errors.Wrap(err, errMessage)
}

o.responseMimeTypes = validTypes

return nil
}

// ProcessProduceComment processes the previously parsed produce comment.
func (o *OperationV3) ProcessProduceComment() error {
const errMessage = "could not process produce comment"

if o.Responses == nil {
return nil
}

for _, value := range o.responseMimeTypes {
if o.Responses.Spec.Response == nil {
o.Responses.Spec.Response = make(map[string]*spec.RefOrSpec[spec.Extendable[spec.Response]], len(o.responseMimeTypes))
}

for key, response := range o.Responses.Spec.Response {
code, err := strconv.Atoi(key)
if err != nil {
return errors.Wrap(err, errMessage)
}

// Status 204 is no content. So we do not need to add content.
if code == 204 {
continue
}

// As this is a workaround, we need to check if the code is in range.
// The Produce comment is being deprecated soon.
if code < 200 || code > 299 {
continue
}

// skip correctly setup types like application/json
if response.Spec.Spec.Content[value] != nil {
continue
}

// for _, value := range result {
// o.Responses.Spec.Response
// }
mediaType := spec.NewMediaType()
schema := spec.NewSchemaSpec()

switch value {
case "application/json", "multipart/form-data", "text/xml":
schema.Spec.Type = spec.NewSingleOrArray(OBJECT)
case "image/png",
"image/jpeg",
"image/gif",
"application/octet-stream",
"application/pdf",
"application/msexcel",
"application/zip",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.openxmlformats-officedocument.presentationml.presentation":
schema.Spec.Type = spec.NewSingleOrArray(STRING)
schema.Spec.Format = "binary"
default:
schema.Spec.Type = spec.NewSingleOrArray(STRING)
}

// TODO the format of the comment needs to be changed in order to work
// The produce can be different per response code, so the produce mimetype needs to be included in the response comment
mediaType.Spec.Schema = schema

if response.Spec.Spec.Content == nil {
response.Spec.Spec.Content = make(map[string]*spec.Extendable[spec.MediaType])
}

response.Spec.Spec.Content[value] = mediaType

}
}

return nil
}
Expand All @@ -219,6 +286,8 @@ func (o *OperationV3) ParseProduceComment(commentLine string) error {
func parseMimeTypeListV3(mimeTypeList string, format string) ([]string, error) {
var result []string
for _, typeName := range strings.Split(mimeTypeList, ",") {
typeName = strings.TrimSpace(typeName)

if mimeTypePattern.MatchString(typeName) {
result = append(result, typeName)

Expand Down
71 changes: 69 additions & 2 deletions operationv3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1861,7 +1861,7 @@ func TestParseCodeSamplesV3(t *testing.T) {
func TestParseAcceptCommentV3(t *testing.T) {
t.Parallel()

comment := `/@Accept json,xml,plain,html,mpfd,x-www-form-urlencoded,json-api,json-stream,octet-stream,png,jpeg,gif,application/xhtml+xml,application/health+json`
comment := `//@Accept json,xml,plain,html,mpfd,x-www-form-urlencoded,json-api,json-stream,octet-stream,png,jpeg,gif,application/xhtml+xml,application/health+json`
operation := NewOperationV3(New())
err := operation.ParseComment(comment, nil)
assert.NoError(t, err)
Expand Down Expand Up @@ -1896,8 +1896,75 @@ func TestParseAcceptCommentV3(t *testing.T) {
func TestParseAcceptCommentErrV3(t *testing.T) {
t.Parallel()

comment := `/@Accept unknown`
comment := `//@Accept unknown`
operation := NewOperationV3(New())
err := operation.ParseComment(comment, nil)
assert.Error(t, err)
}

func TestParseProduceCommandV3(t *testing.T) {
t.Parallel()

t.Run("Produce success", func(t *testing.T) {
t.Parallel()

const comment = "//@Produce application/json,text/csv,application/zip"

operation := NewOperationV3(New())
err := operation.ParseComment(comment, nil)
assert.NoError(t, err)

assert.Equal(t, 3, len(operation.responseMimeTypes))
})

t.Run("Produce Invalid Mime Type", func(t *testing.T) {
t.Parallel()

const comment = "//@Produce text,stuff,gophers"

operation := NewOperationV3(New())
err := operation.ParseComment(comment, nil)
assert.Error(t, err)
})
}

func TestProcessProduceComment(t *testing.T) {
t.Parallel()

const comment = "//@Produce application/json,text/csv,application/zip"

operation := NewOperationV3(New())
err := operation.ParseComment(comment, nil)
require.NoError(t, err)

operation.Responses.Spec.Response = make(map[string]*spec.RefOrSpec[spec.Extendable[spec.Response]])
operation.Responses.Spec.Response["200"] = spec.NewResponseSpec()
operation.Responses.Spec.Response["201"] = spec.NewResponseSpec()
operation.Responses.Spec.Response["204"] = spec.NewResponseSpec()
operation.Responses.Spec.Response["400"] = spec.NewResponseSpec()
operation.Responses.Spec.Response["500"] = spec.NewResponseSpec()

err = operation.ProcessProduceComment()
require.NoError(t, err)

content := operation.Responses.Spec.Response["200"].Spec.Spec.Content
assert.Equal(t, 3, len(content))
assert.NotNil(t, content["application/json"].Spec.Schema)
assert.NotNil(t, content["text/csv"].Spec.Schema)
assert.NotNil(t, content["application/zip"].Spec.Schema)

content = operation.Responses.Spec.Response["201"].Spec.Spec.Content
assert.Equal(t, 3, len(content))
assert.NotNil(t, content["application/json"].Spec.Schema)
assert.NotNil(t, content["text/csv"].Spec.Schema)
assert.NotNil(t, content["application/zip"].Spec.Schema)

content = operation.Responses.Spec.Response["204"].Spec.Spec.Content
assert.Nil(t, content)

content = operation.Responses.Spec.Response["400"].Spec.Spec.Content
assert.Nil(t, content)

content = operation.Responses.Spec.Response["500"].Spec.Spec.Content
assert.Nil(t, content)
}
10 changes: 9 additions & 1 deletion parserv3.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,15 @@ func (p *Parser) ParseRouterAPIInfoV3(fileInfo *AstFileInfo) error {
return fmt.Errorf("ParseComment error in file %s :%+v", fileInfo.Path, err)
}
}
err := processRouterOperationV3(p, operation)

// workaround until we replace the produce comment with a new @Success syntax
// We first need to setup all responses before we can set the mimetypes
err := operation.ProcessProduceComment()
if err != nil {
return err
}

err = processRouterOperationV3(p, operation)
if err != nil {
return err
}
Expand Down

0 comments on commit bddf978

Please sign in to comment.