221 lines
6.9 KiB
Go
221 lines
6.9 KiB
Go
package swagger
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/go-openapi/spec"
|
|
apiSpec "github.com/zeromicro/go-zero/tools/goctl/api/spec"
|
|
)
|
|
|
|
func isPostJson(ctx Context, method string, tp apiSpec.Type) (string, bool) {
|
|
// Check if this is a method that supports request body (POST, PUT, PATCH)
|
|
if !strings.EqualFold(method, http.MethodPost) &&
|
|
!strings.EqualFold(method, http.MethodPut) &&
|
|
!strings.EqualFold(method, http.MethodPatch) {
|
|
return "", false
|
|
}
|
|
structType, ok := tp.(apiSpec.DefineStruct)
|
|
if !ok {
|
|
return "", false
|
|
}
|
|
var hasJsonField bool
|
|
rangeMemberAndDo(ctx, structType, func(tag *apiSpec.Tags, required bool, member apiSpec.Member) {
|
|
jsonTag, _ := tag.Get(tagJson)
|
|
if !hasJsonField {
|
|
hasJsonField = jsonTag != nil
|
|
}
|
|
})
|
|
return structType.RawName, hasJsonField
|
|
}
|
|
|
|
func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Parameter {
|
|
if tp == nil {
|
|
return []spec.Parameter{}
|
|
}
|
|
structType, ok := tp.(apiSpec.DefineStruct)
|
|
if !ok {
|
|
return []spec.Parameter{}
|
|
}
|
|
|
|
var (
|
|
resp []spec.Parameter
|
|
properties = map[string]spec.Schema{}
|
|
requiredFields []string
|
|
)
|
|
rangeMemberAndDo(ctx, structType, func(tag *apiSpec.Tags, required bool, member apiSpec.Member) {
|
|
headerTag, _ := tag.Get(tagHeader)
|
|
hasHeader := headerTag != nil
|
|
|
|
pathParameterTag, _ := tag.Get(tagPath)
|
|
hasPathParameter := pathParameterTag != nil
|
|
|
|
formTag, _ := tag.Get(tagForm)
|
|
hasForm := formTag != nil
|
|
|
|
jsonTag, _ := tag.Get(tagJson)
|
|
hasJson := jsonTag != nil
|
|
if hasHeader {
|
|
minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(headerTag.Options)
|
|
resp = append(resp, spec.Parameter{
|
|
CommonValidations: spec.CommonValidations{
|
|
Maximum: maximum,
|
|
ExclusiveMaximum: exclusiveMaximum,
|
|
Minimum: minimum,
|
|
ExclusiveMinimum: exclusiveMinimum,
|
|
Enum: enumsValueFromOptions(headerTag.Options),
|
|
},
|
|
SimpleSchema: spec.SimpleSchema{
|
|
Type: sampleTypeFromGoType(ctx, member.Type),
|
|
Default: defValueFromOptions(ctx, headerTag.Options, member.Type),
|
|
Items: sampleItemsFromGoType(ctx, member.Type),
|
|
},
|
|
ParamProps: spec.ParamProps{
|
|
In: paramsInHeader,
|
|
Name: headerTag.Name,
|
|
Description: formatComment(member.Comment),
|
|
Required: required,
|
|
},
|
|
})
|
|
}
|
|
if hasPathParameter {
|
|
minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(pathParameterTag.Options)
|
|
resp = append(resp, spec.Parameter{
|
|
CommonValidations: spec.CommonValidations{
|
|
Maximum: maximum,
|
|
ExclusiveMaximum: exclusiveMaximum,
|
|
Minimum: minimum,
|
|
ExclusiveMinimum: exclusiveMinimum,
|
|
Enum: enumsValueFromOptions(pathParameterTag.Options),
|
|
},
|
|
SimpleSchema: spec.SimpleSchema{
|
|
Type: sampleTypeFromGoType(ctx, member.Type),
|
|
Default: defValueFromOptions(ctx, pathParameterTag.Options, member.Type),
|
|
Items: sampleItemsFromGoType(ctx, member.Type),
|
|
},
|
|
ParamProps: spec.ParamProps{
|
|
In: paramsInPath,
|
|
Name: pathParameterTag.Name,
|
|
Description: formatComment(member.Comment),
|
|
Required: required,
|
|
},
|
|
})
|
|
}
|
|
if hasForm {
|
|
minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(formTag.Options)
|
|
if strings.EqualFold(method, http.MethodGet) {
|
|
resp = append(resp, spec.Parameter{
|
|
CommonValidations: spec.CommonValidations{
|
|
Maximum: maximum,
|
|
ExclusiveMaximum: exclusiveMaximum,
|
|
Minimum: minimum,
|
|
ExclusiveMinimum: exclusiveMinimum,
|
|
Enum: enumsValueFromOptions(formTag.Options),
|
|
},
|
|
SimpleSchema: spec.SimpleSchema{
|
|
Type: sampleTypeFromGoType(ctx, member.Type),
|
|
Default: defValueFromOptions(ctx, formTag.Options, member.Type),
|
|
Items: sampleItemsFromGoType(ctx, member.Type),
|
|
},
|
|
ParamProps: spec.ParamProps{
|
|
In: paramsInQuery,
|
|
Name: formTag.Name,
|
|
Description: formatComment(member.Comment),
|
|
Required: required,
|
|
AllowEmptyValue: !required,
|
|
},
|
|
})
|
|
} else {
|
|
resp = append(resp, spec.Parameter{
|
|
CommonValidations: spec.CommonValidations{
|
|
Maximum: maximum,
|
|
ExclusiveMaximum: exclusiveMaximum,
|
|
Minimum: minimum,
|
|
ExclusiveMinimum: exclusiveMinimum,
|
|
Enum: enumsValueFromOptions(formTag.Options),
|
|
},
|
|
SimpleSchema: spec.SimpleSchema{
|
|
Type: sampleTypeFromGoType(ctx, member.Type),
|
|
Default: defValueFromOptions(ctx, formTag.Options, member.Type),
|
|
Items: sampleItemsFromGoType(ctx, member.Type),
|
|
},
|
|
ParamProps: spec.ParamProps{
|
|
In: paramsInForm,
|
|
Name: formTag.Name,
|
|
Description: formatComment(member.Comment),
|
|
Required: required,
|
|
AllowEmptyValue: !required,
|
|
},
|
|
})
|
|
}
|
|
|
|
}
|
|
if hasJson {
|
|
minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(jsonTag.Options)
|
|
if required {
|
|
requiredFields = append(requiredFields, jsonTag.Name)
|
|
}
|
|
var schema = spec.Schema{
|
|
SwaggerSchemaProps: spec.SwaggerSchemaProps{
|
|
Example: exampleValueFromOptions(ctx, jsonTag.Options, member.Type),
|
|
},
|
|
SchemaProps: spec.SchemaProps{
|
|
Description: formatComment(member.Comment),
|
|
Type: typeFromGoType(ctx, member.Type),
|
|
Default: defValueFromOptions(ctx, jsonTag.Options, member.Type),
|
|
Maximum: maximum,
|
|
ExclusiveMaximum: exclusiveMaximum,
|
|
Minimum: minimum,
|
|
ExclusiveMinimum: exclusiveMinimum,
|
|
Enum: enumsValueFromOptions(jsonTag.Options),
|
|
AdditionalProperties: mapFromGoType(ctx, member.Type),
|
|
},
|
|
}
|
|
switch sampleTypeFromGoType(ctx, member.Type) {
|
|
case swaggerTypeArray:
|
|
schema.Items = itemsFromGoType(ctx, member.Type)
|
|
case swaggerTypeObject:
|
|
p, r := propertiesFromType(ctx, member.Type)
|
|
schema.Properties = p
|
|
schema.Required = r
|
|
}
|
|
properties[jsonTag.Name] = schema
|
|
}
|
|
})
|
|
if len(properties) > 0 {
|
|
if ctx.UseDefinitions {
|
|
structName, ok := isPostJson(ctx, method, tp)
|
|
if ok {
|
|
resp = append(resp, spec.Parameter{
|
|
ParamProps: spec.ParamProps{
|
|
In: paramsInBody,
|
|
Name: paramsInBody,
|
|
Required: true,
|
|
Schema: &spec.Schema{
|
|
SchemaProps: spec.SchemaProps{
|
|
Ref: spec.MustCreateRef(getRefName(structName)),
|
|
},
|
|
},
|
|
},
|
|
})
|
|
}
|
|
} else {
|
|
resp = append(resp, spec.Parameter{
|
|
ParamProps: spec.ParamProps{
|
|
In: paramsInBody,
|
|
Name: paramsInBody,
|
|
Required: true,
|
|
Schema: &spec.Schema{
|
|
SchemaProps: spec.SchemaProps{
|
|
Type: typeFromGoType(ctx, structType),
|
|
Properties: properties,
|
|
Required: requiredFields,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
}
|
|
}
|
|
return resp
|
|
}
|