mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-14 02:10:00 +08:00
fix: support PUT, PATCH, DELETE methods for request body definitions in swagger (#5239)
This commit is contained in:
@@ -8,28 +8,37 @@ import (
|
|||||||
apiSpec "github.com/zeromicro/go-zero/tools/goctl/api/spec"
|
apiSpec "github.com/zeromicro/go-zero/tools/goctl/api/spec"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isPostJson(ctx Context, method string, tp apiSpec.Type) (string, bool) {
|
func isRequestBodyJson(ctx Context, method string, tp apiSpec.Type) (string, bool) {
|
||||||
if !strings.EqualFold(method, http.MethodPost) {
|
// Support HTTP methods that commonly use request bodies with JSON
|
||||||
|
// POST, PUT, PATCH are standard methods with bodies
|
||||||
|
// DELETE can also have a body (though less common)
|
||||||
|
method = strings.ToUpper(method)
|
||||||
|
if method != http.MethodPost && method != http.MethodPut &&
|
||||||
|
method != http.MethodPatch && method != http.MethodDelete {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
structType, ok := tp.(apiSpec.DefineStruct)
|
structType, ok := tp.(apiSpec.DefineStruct)
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
var isPostJson bool
|
|
||||||
|
var hasJsonField bool
|
||||||
rangeMemberAndDo(ctx, structType, func(tag *apiSpec.Tags, required bool, member apiSpec.Member) {
|
rangeMemberAndDo(ctx, structType, func(tag *apiSpec.Tags, required bool, member apiSpec.Member) {
|
||||||
jsonTag, _ := tag.Get(tagJson)
|
jsonTag, _ := tag.Get(tagJson)
|
||||||
if !isPostJson {
|
if !hasJsonField {
|
||||||
isPostJson = jsonTag != nil
|
hasJsonField = jsonTag != nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return structType.RawName, isPostJson
|
|
||||||
|
return structType.RawName, hasJsonField
|
||||||
}
|
}
|
||||||
|
|
||||||
func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Parameter {
|
func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Parameter {
|
||||||
if tp == nil {
|
if tp == nil {
|
||||||
return []spec.Parameter{}
|
return []spec.Parameter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
structType, ok := tp.(apiSpec.DefineStruct)
|
structType, ok := tp.(apiSpec.DefineStruct)
|
||||||
if !ok {
|
if !ok {
|
||||||
return []spec.Parameter{}
|
return []spec.Parameter{}
|
||||||
@@ -43,15 +52,13 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para
|
|||||||
rangeMemberAndDo(ctx, structType, func(tag *apiSpec.Tags, required bool, member apiSpec.Member) {
|
rangeMemberAndDo(ctx, structType, func(tag *apiSpec.Tags, required bool, member apiSpec.Member) {
|
||||||
headerTag, _ := tag.Get(tagHeader)
|
headerTag, _ := tag.Get(tagHeader)
|
||||||
hasHeader := headerTag != nil
|
hasHeader := headerTag != nil
|
||||||
|
|
||||||
pathParameterTag, _ := tag.Get(tagPath)
|
pathParameterTag, _ := tag.Get(tagPath)
|
||||||
hasPathParameter := pathParameterTag != nil
|
hasPathParameter := pathParameterTag != nil
|
||||||
|
|
||||||
formTag, _ := tag.Get(tagForm)
|
formTag, _ := tag.Get(tagForm)
|
||||||
hasForm := formTag != nil
|
hasForm := formTag != nil
|
||||||
|
|
||||||
jsonTag, _ := tag.Get(tagJson)
|
jsonTag, _ := tag.Get(tagJson)
|
||||||
hasJson := jsonTag != nil
|
hasJson := jsonTag != nil
|
||||||
|
|
||||||
if hasHeader {
|
if hasHeader {
|
||||||
minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(headerTag.Options)
|
minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(headerTag.Options)
|
||||||
resp = append(resp, spec.Parameter{
|
resp = append(resp, spec.Parameter{
|
||||||
@@ -75,6 +82,7 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasPathParameter {
|
if hasPathParameter {
|
||||||
minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(pathParameterTag.Options)
|
minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(pathParameterTag.Options)
|
||||||
resp = append(resp, spec.Parameter{
|
resp = append(resp, spec.Parameter{
|
||||||
@@ -98,6 +106,7 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasForm {
|
if hasForm {
|
||||||
minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(formTag.Options)
|
minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(formTag.Options)
|
||||||
if strings.EqualFold(method, http.MethodGet) {
|
if strings.EqualFold(method, http.MethodGet) {
|
||||||
@@ -145,8 +154,8 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasJson {
|
if hasJson {
|
||||||
minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(jsonTag.Options)
|
minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(jsonTag.Options)
|
||||||
if required {
|
if required {
|
||||||
@@ -179,9 +188,10 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para
|
|||||||
properties[jsonTag.Name] = schema
|
properties[jsonTag.Name] = schema
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(properties) > 0 {
|
if len(properties) > 0 {
|
||||||
if ctx.UseDefinitions {
|
if ctx.UseDefinitions {
|
||||||
structName, ok := isPostJson(ctx, method, tp)
|
structName, ok := isRequestBodyJson(ctx, method, tp)
|
||||||
if ok {
|
if ok {
|
||||||
resp = append(resp, spec.Parameter{
|
resp = append(resp, spec.Parameter{
|
||||||
ParamProps: spec.ParamProps{
|
ParamProps: spec.ParamProps{
|
||||||
@@ -213,5 +223,6 @@ func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Para
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
apiSpec "github.com/zeromicro/go-zero/tools/goctl/api/spec"
|
apiSpec "github.com/zeromicro/go-zero/tools/goctl/api/spec"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsPostJson(t *testing.T) {
|
func TestIsRequestBodyJson(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
method string
|
method string
|
||||||
@@ -18,13 +18,18 @@ func TestIsPostJson(t *testing.T) {
|
|||||||
{"POST with JSON", http.MethodPost, true, true},
|
{"POST with JSON", http.MethodPost, true, true},
|
||||||
{"POST without JSON", http.MethodPost, false, false},
|
{"POST without JSON", http.MethodPost, false, false},
|
||||||
{"GET with JSON", http.MethodGet, true, false},
|
{"GET with JSON", http.MethodGet, true, false},
|
||||||
{"PUT with JSON", http.MethodPut, true, false},
|
{"PUT with JSON", http.MethodPut, true, true},
|
||||||
|
{"PUT without JSON", http.MethodPut, false, false},
|
||||||
|
{"PATCH with JSON", http.MethodPatch, true, true},
|
||||||
|
{"PATCH without JSON", http.MethodPatch, false, false},
|
||||||
|
{"DELETE with JSON", http.MethodDelete, true, true},
|
||||||
|
{"DELETE without JSON", http.MethodDelete, false, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
testStruct := createTestStruct("TestStruct", tt.hasJson)
|
testStruct := createTestStruct("TestStruct", tt.hasJson)
|
||||||
_, result := isPostJson(testingContext(t), tt.method, testStruct)
|
_, result := isRequestBodyJson(testingContext(t), tt.method, testStruct)
|
||||||
assert.Equal(t, tt.expected, result)
|
assert.Equal(t, tt.expected, result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -41,6 +46,12 @@ func TestParametersFromType(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{"POST JSON with definitions", http.MethodPost, true, true, 1, true},
|
{"POST JSON with definitions", http.MethodPost, true, true, 1, true},
|
||||||
{"POST JSON without definitions", http.MethodPost, false, true, 1, true},
|
{"POST JSON without definitions", http.MethodPost, false, true, 1, true},
|
||||||
|
{"PUT JSON with definitions", http.MethodPut, true, true, 1, true},
|
||||||
|
{"PUT JSON without definitions", http.MethodPut, false, true, 1, true},
|
||||||
|
{"PATCH JSON with definitions", http.MethodPatch, true, true, 1, true},
|
||||||
|
{"PATCH JSON without definitions", http.MethodPatch, false, true, 1, true},
|
||||||
|
{"DELETE JSON with definitions", http.MethodDelete, true, true, 1, true},
|
||||||
|
{"DELETE JSON without definitions", http.MethodDelete, false, true, 1, true},
|
||||||
{"GET with form", http.MethodGet, false, false, 1, false},
|
{"GET with form", http.MethodGet, false, false, 1, false},
|
||||||
{"POST with form", http.MethodPost, false, false, 1, false},
|
{"POST with form", http.MethodPost, false, false, 1, false},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user