Bump github.com/emicklei/go-restful-openapi to v2.9.2-0.20230507070325-d6acc08e570c (#5669)
This commit is contained in:
2
vendor/github.com/emicklei/go-restful-openapi/v2/.gitignore
generated
vendored
Normal file
2
vendor/github.com/emicklei/go-restful-openapi/v2/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
examples/examples
|
||||
.vscode
|
||||
103
vendor/github.com/emicklei/go-restful-openapi/v2/.golangci.yml
generated
vendored
Normal file
103
vendor/github.com/emicklei/go-restful-openapi/v2/.golangci.yml
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
# This file contains all available configuration options
|
||||
# with their default values.
|
||||
|
||||
# options for analysis running
|
||||
run:
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
deadline: 5m
|
||||
|
||||
# exit code when at least one issue was found, default is 1
|
||||
issues-exit-code: 1
|
||||
|
||||
# include test files or not, default is true
|
||||
tests: true
|
||||
|
||||
# which dirs to skip: they won't be analyzed;
|
||||
# can use regexp here: generated.*, regexp is applied on full path;
|
||||
# default value is empty list, but next dirs are always skipped independently
|
||||
# from this option's value:
|
||||
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
|
||||
skip-dirs:
|
||||
|
||||
# which files to skip: they will be analyzed, but issues from them
|
||||
# won't be reported. Default value is empty list, but there is
|
||||
# no need to include all autogenerated files, we confidently recognize
|
||||
# autogenerated files. If it's not please let us know.
|
||||
skip-files:
|
||||
|
||||
# whether to hide "congrats" message if no issues were found,
|
||||
# default is false (show "congrats" message by default).
|
||||
# set this option to true to print nothing if no issues were found.
|
||||
silent: true
|
||||
|
||||
# build-tags:
|
||||
# - mandrill
|
||||
# - test
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
# colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number"
|
||||
format: line-number
|
||||
|
||||
# print lines of code with issue, default is true
|
||||
print-issued-lines: true
|
||||
|
||||
# print linter name in the end of issue text, default is true
|
||||
print-linter-name: true
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- lll
|
||||
- dupl
|
||||
- wsl
|
||||
- funlen
|
||||
- gocognit
|
||||
- testpackage
|
||||
- gomnd
|
||||
- goerr113
|
||||
- nestif
|
||||
- interfacer
|
||||
- godot
|
||||
- unparam
|
||||
- nlreturn
|
||||
- wrapcheck
|
||||
- exhaustivestruct
|
||||
- errorlint
|
||||
# todo enable as much as possible linters below
|
||||
- paralleltest
|
||||
- unused
|
||||
- govet
|
||||
- gosimple
|
||||
- exhaustive
|
||||
- whitespace
|
||||
- structcheck
|
||||
- misspell
|
||||
- golint
|
||||
- goheader
|
||||
- stylecheck
|
||||
- gofumpt
|
||||
- gofmt
|
||||
- godox
|
||||
- gocyclo
|
||||
- gocritic
|
||||
- goconst
|
||||
- goimports
|
||||
- gci
|
||||
- errcheck
|
||||
- deadcode
|
||||
fast: false
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: true
|
||||
golint:
|
||||
report-comments: true
|
||||
|
||||
issues:
|
||||
max-same-issues: 20
|
||||
exclude:
|
||||
- ^G104
|
||||
- ^G501
|
||||
13
vendor/github.com/emicklei/go-restful-openapi/v2/.travis.yml
generated
vendored
Normal file
13
vendor/github.com/emicklei/go-restful-openapi/v2/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.13
|
||||
|
||||
before_install:
|
||||
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.33.0
|
||||
|
||||
script:
|
||||
- go mod vendor
|
||||
- go mod download
|
||||
# - make lint-ci
|
||||
- make test
|
||||
90
vendor/github.com/emicklei/go-restful-openapi/v2/CHANGES.md
generated
vendored
Normal file
90
vendor/github.com/emicklei/go-restful-openapi/v2/CHANGES.md
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
# changes to the go-restful-openapi package
|
||||
|
||||
# v2+ versions are using the Go module of go-restful v3+
|
||||
|
||||
|
||||
## v2.9.1
|
||||
|
||||
- fix set array data format (#96)
|
||||
|
||||
## v2.9.0
|
||||
|
||||
- Add property x-go-name support (#90)
|
||||
- Add support to set swagger Schemes field (#91)
|
||||
|
||||
## v2.8.0
|
||||
|
||||
[2022-01-04]
|
||||
|
||||
- refine and fix GoLowerCamelCasedNameHandler bug (#88)
|
||||
- Add missing fields of response header object (#89)
|
||||
- support generate field name with config (#86)
|
||||
|
||||
Thanks again to slow-zhang and Sergey Vilgelm
|
||||
|
||||
## v2.7.0
|
||||
|
||||
[2021-12-08]
|
||||
|
||||
- fix some typos (#85)
|
||||
- use PossibleValues in favor of AllowedValues (#84)
|
||||
- PostBuildSwaggerSchema handler for each model (#83)
|
||||
- Use int64 format for time.Duration type (#82)
|
||||
|
||||
Special thanks to contributions of Sergey Vilgelm <sergey@vilgelm.com>
|
||||
|
||||
## [2021-09-20] v2.6.0
|
||||
|
||||
- feat(parameter): adds additional openapi mappings (#74, robbie@robnrob.com)
|
||||
|
||||
## [2021-09-20] v2.5.0
|
||||
|
||||
- add support for format tag (#72, askingcat)
|
||||
|
||||
## [2021-09-18] v2.4.0
|
||||
|
||||
- add support for vendor extensions (#)
|
||||
|
||||
## [2020-02-10] v2.3.0
|
||||
- Support for custom attribute "x-nullable" (#70)
|
||||
|
||||
## v1.4.0 + v2.2.0
|
||||
- Allow maps as top level types and support maps to slices (#63)
|
||||
|
||||
## v1.3.0 + v2.1.0
|
||||
- add json.Number handling (PR #61)
|
||||
- add type alias support for primitives (PR #61)
|
||||
|
||||
## v1.2.0
|
||||
|
||||
- handle map[string][]byte (#59)
|
||||
|
||||
## v1.1.0 (v0.14.1)
|
||||
|
||||
- Add Host field to Config which is copied into Swagger object
|
||||
- Enable CORS by default as per the documentation (#58)
|
||||
- add go module
|
||||
- update dependencies
|
||||
|
||||
## v0.13.0
|
||||
|
||||
- Do not use 200 as default response, instead use the one explicitly defined.
|
||||
- support time.Duration
|
||||
- Fix Parameter 'AllowableValues' to populate swagger definition
|
||||
|
||||
## v0.12.0
|
||||
|
||||
- add support for time.Duration
|
||||
- Populate the swagger definition with the parameter's 'AllowableValues' as an enum (#53)
|
||||
- Fix for #19 MapModelTypeNameFunc has incomplete behavior
|
||||
- Merge paths with existing paths from other webServices (#48)
|
||||
- prevent array param.Type be overwritten in the else case below (#47)
|
||||
|
||||
## v0.11.0
|
||||
|
||||
- Register pointer to array/slice of primitives as such rather than as reference to the primitive type definition. (#46)
|
||||
- Add support for map types using "additional properties" (#44)
|
||||
|
||||
## <= v0.10.0
|
||||
|
||||
See `git log`.
|
||||
22
vendor/github.com/emicklei/go-restful-openapi/v2/LICENSE
generated
vendored
Normal file
22
vendor/github.com/emicklei/go-restful-openapi/v2/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2017 Ernest Micklei
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
20
vendor/github.com/emicklei/go-restful-openapi/v2/Makefile
generated
vendored
Normal file
20
vendor/github.com/emicklei/go-restful-openapi/v2/Makefile
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
clean:
|
||||
rm coverage.out
|
||||
|
||||
test:
|
||||
go test -cover -race -count=1 ./...
|
||||
|
||||
coverage:
|
||||
go test -coverprofile=coverage.out ./...
|
||||
go tool cover -html=coverage.out
|
||||
|
||||
# for local testing
|
||||
lint:
|
||||
docker run --rm -v $(PWD):$(PWD) -w $(PWD) golangci/golangci-lint:v1.33.0 golangci-lint run -v
|
||||
|
||||
# for testing on CI/CD. we specify required linter version in the .travis.yml file
|
||||
lint-ci:
|
||||
golangci-lint run
|
||||
|
||||
outdated:
|
||||
go list -u -m -json all | docker run -i psampaz/go-mod-outdated -update -direct -ci
|
||||
38
vendor/github.com/emicklei/go-restful-openapi/v2/README.md
generated
vendored
Normal file
38
vendor/github.com/emicklei/go-restful-openapi/v2/README.md
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# go-restful-openapi
|
||||
|
||||
[](https://travis-ci.org/emicklei/go-restful-openapi)
|
||||
[](https://godoc.org/github.com/emicklei/go-restful-openapi)
|
||||
|
||||
[openapi](https://www.openapis.org) extension to the go-restful package, targeting [version 2.0](https://github.com/OAI/OpenAPI-Specification)
|
||||
|
||||
## The following Go field tags are translated to OpenAPI equivalents
|
||||
- description
|
||||
- minimum
|
||||
- maximum
|
||||
- optional ( if set to "true" then it is not listed in `required`)
|
||||
- unique
|
||||
- modelDescription
|
||||
- type (overrides the Go type String())
|
||||
- enum
|
||||
- readOnly
|
||||
|
||||
See TestThatExtraTagsAreReadIntoModel for examples.
|
||||
|
||||
## dependencies
|
||||
|
||||
- [go-restful](https://github.com/emicklei/go-restful)
|
||||
- [go-openapi](https://github.com/go-openapi/spec)
|
||||
|
||||
|
||||
## Go modules
|
||||
|
||||
Versions `v1` of this package require Go module version `v2` of the go-restful package.
|
||||
To use version `v3` of the go-restful package, you need to import `v2` of this package, such as:
|
||||
|
||||
import (
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
)
|
||||
|
||||
|
||||
© 2017-2020, ernestmicklei.com. MIT License. Contributions welcome.
|
||||
32
vendor/github.com/emicklei/go-restful-openapi/v2/build_definitions.go
generated
vendored
Normal file
32
vendor/github.com/emicklei/go-restful-openapi/v2/build_definitions.go
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
package restfulspec
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
func buildDefinitions(ws *restful.WebService, cfg Config) (definitions spec.Definitions) {
|
||||
definitions = spec.Definitions{}
|
||||
for _, each := range ws.Routes() {
|
||||
addDefinitionsFromRouteTo(each, cfg, definitions)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func addDefinitionsFromRouteTo(r restful.Route, cfg Config, d spec.Definitions) {
|
||||
builder := definitionBuilder{Definitions: d, Config: cfg}
|
||||
if r.ReadSample != nil {
|
||||
builder.addModel(reflect.TypeOf(r.ReadSample), "")
|
||||
}
|
||||
if r.WriteSample != nil {
|
||||
builder.addModel(reflect.TypeOf(r.WriteSample), "")
|
||||
}
|
||||
for _, v := range r.ResponseErrors {
|
||||
if v.Model == nil {
|
||||
continue
|
||||
}
|
||||
builder.addModel(reflect.TypeOf(v.Model), "")
|
||||
}
|
||||
}
|
||||
380
vendor/github.com/emicklei/go-restful-openapi/v2/build_path.go
generated
vendored
Normal file
380
vendor/github.com/emicklei/go-restful-openapi/v2/build_path.go
generated
vendored
Normal file
@@ -0,0 +1,380 @@
|
||||
package restfulspec
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
// KeyOpenAPITags is a Metadata key for a restful Route
|
||||
KeyOpenAPITags = "openapi.tags"
|
||||
|
||||
// ExtensionPrefix is the only prefix accepted for VendorExtensible extension keys
|
||||
ExtensionPrefix = "x-"
|
||||
|
||||
arrayType = "array"
|
||||
definitionRoot = "#/definitions/"
|
||||
)
|
||||
|
||||
func buildPaths(ws *restful.WebService, cfg Config) spec.Paths {
|
||||
p := spec.Paths{Paths: map[string]spec.PathItem{}}
|
||||
for _, each := range ws.Routes() {
|
||||
path, patterns := sanitizePath(each.Path)
|
||||
existingPathItem, ok := p.Paths[path]
|
||||
if !ok {
|
||||
existingPathItem = spec.PathItem{}
|
||||
}
|
||||
p.Paths[path] = buildPathItem(ws, each, existingPathItem, patterns, cfg)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// sanitizePath removes regex expressions from named path params,
|
||||
// since openapi only supports setting the pattern as a property named "pattern".
|
||||
// Expressions like "/api/v1/{name:[a-z]}/" are converted to "/api/v1/{name}/".
|
||||
// The second return value is a map which contains the mapping from the path parameter
|
||||
// name to the extracted pattern
|
||||
func sanitizePath(restfulPath string) (string, map[string]string) {
|
||||
openapiPath := ""
|
||||
patterns := map[string]string{}
|
||||
for _, fragment := range strings.Split(restfulPath, "/") {
|
||||
if fragment == "" {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(fragment, "{") && strings.Contains(fragment, ":") {
|
||||
split := strings.Split(fragment, ":")
|
||||
// skip google custom method like `resource/{resource-id}:customVerb`
|
||||
if !strings.Contains(split[0], "}") {
|
||||
fragment = split[0][1:]
|
||||
pattern := split[1][:len(split[1])-1]
|
||||
if pattern == "*" { // special case
|
||||
pattern = ".*"
|
||||
}
|
||||
patterns[fragment] = pattern
|
||||
fragment = "{" + fragment + "}"
|
||||
}
|
||||
}
|
||||
openapiPath += "/" + fragment
|
||||
}
|
||||
return openapiPath, patterns
|
||||
}
|
||||
|
||||
func buildPathItem(ws *restful.WebService, r restful.Route, existingPathItem spec.PathItem, patterns map[string]string, cfg Config) spec.PathItem {
|
||||
op := buildOperation(ws, r, patterns, cfg)
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
existingPathItem.Get = op
|
||||
case http.MethodPost:
|
||||
existingPathItem.Post = op
|
||||
case http.MethodPut:
|
||||
existingPathItem.Put = op
|
||||
case http.MethodDelete:
|
||||
existingPathItem.Delete = op
|
||||
case http.MethodPatch:
|
||||
existingPathItem.Patch = op
|
||||
case http.MethodOptions:
|
||||
existingPathItem.Options = op
|
||||
case http.MethodHead:
|
||||
existingPathItem.Head = op
|
||||
}
|
||||
return existingPathItem
|
||||
}
|
||||
|
||||
func buildOperation(ws *restful.WebService, r restful.Route, patterns map[string]string, cfg Config) *spec.Operation {
|
||||
o := spec.NewOperation(r.Operation)
|
||||
o.Description = r.Notes
|
||||
o.Summary = stripTags(r.Doc)
|
||||
o.Consumes = r.Consumes
|
||||
o.Produces = r.Produces
|
||||
o.Deprecated = r.Deprecated
|
||||
if r.Metadata != nil {
|
||||
if tags, ok := r.Metadata[KeyOpenAPITags]; ok {
|
||||
if tagList, ok := tags.([]string); ok {
|
||||
o.Tags = tagList
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extractVendorExtensions(&o.VendorExtensible, r.ExtensionProperties)
|
||||
|
||||
// collect any path parameters
|
||||
for _, param := range ws.PathParameters() {
|
||||
p := buildParameter(r, param, patterns[param.Data().Name], cfg)
|
||||
o.Parameters = append(o.Parameters, p)
|
||||
}
|
||||
// route specific params
|
||||
for _, param := range r.ParameterDocs {
|
||||
p := buildParameter(r, param, patterns[param.Data().Name], cfg)
|
||||
o.Parameters = append(o.Parameters, p)
|
||||
}
|
||||
o.Responses = new(spec.Responses)
|
||||
props := &o.Responses.ResponsesProps
|
||||
props.StatusCodeResponses = make(map[int]spec.Response, len(r.ResponseErrors))
|
||||
for k, v := range r.ResponseErrors {
|
||||
r := buildResponse(v, cfg)
|
||||
props.StatusCodeResponses[k] = r
|
||||
}
|
||||
if r.DefaultResponse != nil {
|
||||
rsp := buildResponse(*r.DefaultResponse, cfg)
|
||||
o.Responses.Default = &rsp
|
||||
}
|
||||
if len(o.Responses.StatusCodeResponses) == 0 {
|
||||
o.Responses.StatusCodeResponses[200] = spec.Response{ResponseProps: spec.ResponseProps{Description: http.StatusText(http.StatusOK)}}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
// stringAutoType automatically picks the correct type from an ambiguously typed
|
||||
// string. Ex. numbers become int, true/false become bool, etc.
|
||||
func stringAutoType(ambiguous string) interface{} {
|
||||
if ambiguous == "" {
|
||||
return nil
|
||||
}
|
||||
if parsedInt, err := strconv.ParseInt(ambiguous, 10, 64); err == nil {
|
||||
return parsedInt
|
||||
}
|
||||
if parsedBool, err := strconv.ParseBool(ambiguous); err == nil {
|
||||
return parsedBool
|
||||
}
|
||||
return ambiguous
|
||||
}
|
||||
|
||||
func extractVendorExtensions(extensible *spec.VendorExtensible, extensions restful.ExtensionProperties) {
|
||||
if len(extensions.Extensions) > 0 {
|
||||
for key := range extensions.Extensions {
|
||||
if strings.HasPrefix(key, ExtensionPrefix) {
|
||||
extensible.AddExtension(key, extensions.Extensions[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func buildParameter(r restful.Route, restfulParam *restful.Parameter, pattern string, cfg Config) spec.Parameter {
|
||||
p := spec.Parameter{}
|
||||
param := restfulParam.Data()
|
||||
p.In = asParamType(param.Kind)
|
||||
|
||||
if param.AllowMultiple {
|
||||
// If the param is an array apply the validations to the items in it
|
||||
p.Type = arrayType
|
||||
p.Items = spec.NewItems()
|
||||
p.Items.Type = param.DataType
|
||||
p.Items.Pattern = param.Pattern
|
||||
p.Items.MinLength = param.MinLength
|
||||
p.Items.MaxLength = param.MaxLength
|
||||
p.CollectionFormat = param.CollectionFormat
|
||||
p.MinItems = param.MinItems
|
||||
p.MaxItems = param.MaxItems
|
||||
p.UniqueItems = param.UniqueItems
|
||||
} else {
|
||||
// Otherwise, for non-arrays, apply the validations directly to the param
|
||||
p.Type = param.DataType
|
||||
p.MinLength = param.MinLength
|
||||
p.MaxLength = param.MaxLength
|
||||
p.Minimum = param.Minimum
|
||||
p.Maximum = param.Maximum
|
||||
}
|
||||
|
||||
// Prefer PossibleValues over deprecated AllowableValues
|
||||
if numPossible := len(param.PossibleValues); numPossible > 0 {
|
||||
// init Enum to our known size and populate it
|
||||
p.Enum = make([]interface{}, 0, numPossible)
|
||||
for _, value := range param.PossibleValues {
|
||||
p.Enum = append(p.Enum, value)
|
||||
}
|
||||
} else {
|
||||
if numAllowable := len(param.AllowableValues); numAllowable > 0 {
|
||||
// If allowable values are defined, set the enum array to the sorted values
|
||||
allowableSortedKeys := make([]string, 0, numAllowable)
|
||||
for k := range param.AllowableValues {
|
||||
allowableSortedKeys = append(allowableSortedKeys, k)
|
||||
}
|
||||
|
||||
// sort away
|
||||
sort.Strings(allowableSortedKeys)
|
||||
|
||||
// init Enum to our known size and populate it
|
||||
p.Enum = make([]interface{}, 0, numAllowable)
|
||||
for _, key := range allowableSortedKeys {
|
||||
p.Enum = append(p.Enum, param.AllowableValues[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.Description = param.Description
|
||||
p.Name = param.Name
|
||||
p.Required = param.Required
|
||||
p.AllowEmptyValue = param.AllowEmptyValue
|
||||
|
||||
if param.Kind == restful.PathParameterKind {
|
||||
p.Pattern = pattern
|
||||
} else if !param.AllowMultiple {
|
||||
p.Pattern = param.Pattern
|
||||
}
|
||||
st := reflect.TypeOf(r.ReadSample)
|
||||
if param.Kind == restful.BodyParameterKind && r.ReadSample != nil && param.DataType == st.String() {
|
||||
p.Schema = new(spec.Schema)
|
||||
p.SimpleSchema = spec.SimpleSchema{}
|
||||
if st.Kind() == reflect.Array || st.Kind() == reflect.Slice {
|
||||
dataTypeName := keyFrom(st.Elem(), cfg)
|
||||
p.Schema.Type = []string{arrayType}
|
||||
p.Schema.Items = &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{},
|
||||
}
|
||||
isPrimitive := isPrimitiveType(dataTypeName)
|
||||
if isPrimitive {
|
||||
mapped := jsonSchemaType(dataTypeName)
|
||||
p.Schema.Items.Schema.Type = []string{mapped}
|
||||
} else {
|
||||
p.Schema.Items.Schema.Ref = spec.MustCreateRef(definitionRoot + dataTypeName)
|
||||
}
|
||||
} else {
|
||||
dataTypeName := keyFrom(st, cfg)
|
||||
p.Schema.Ref = spec.MustCreateRef(definitionRoot + dataTypeName)
|
||||
}
|
||||
|
||||
} else {
|
||||
if param.AllowMultiple {
|
||||
p.Type = arrayType
|
||||
p.Items = spec.NewItems()
|
||||
p.Items.Type = param.DataType
|
||||
p.CollectionFormat = param.CollectionFormat
|
||||
} else {
|
||||
p.Type = param.DataType
|
||||
}
|
||||
p.Default = stringAutoType(param.DefaultValue)
|
||||
p.Format = param.DataFormat
|
||||
}
|
||||
|
||||
extractVendorExtensions(&p.VendorExtensible, param.ExtensionProperties)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func buildResponse(e restful.ResponseError, cfg Config) (r spec.Response) {
|
||||
r.Description = e.Message
|
||||
if e.Model != nil {
|
||||
st := reflect.TypeOf(e.Model)
|
||||
if st.Kind() == reflect.Ptr {
|
||||
// For pointer type, use element type as the key; otherwise we'll
|
||||
// endup with '#/definitions/*Type' which violates openapi spec.
|
||||
st = st.Elem()
|
||||
}
|
||||
r.Schema = new(spec.Schema)
|
||||
if st.Kind() == reflect.Array || st.Kind() == reflect.Slice {
|
||||
modelName := keyFrom(st.Elem(), cfg)
|
||||
r.Schema.Type = []string{arrayType}
|
||||
r.Schema.Items = &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{},
|
||||
}
|
||||
isPrimitive := isPrimitiveType(modelName)
|
||||
if isPrimitive {
|
||||
mapped := jsonSchemaType(modelName)
|
||||
r.Schema.Items.Schema.Type = []string{mapped}
|
||||
} else {
|
||||
r.Schema.Items.Schema.Ref = spec.MustCreateRef(definitionRoot + modelName)
|
||||
}
|
||||
} else {
|
||||
modelName := keyFrom(st, cfg)
|
||||
if isPrimitiveType(modelName) {
|
||||
// If the response is a primitive type, then don't reference any definitions.
|
||||
// Instead, set the schema's "type" to the model name.
|
||||
r.Schema.AddType(modelName, "")
|
||||
} else {
|
||||
modelName := keyFrom(st, cfg)
|
||||
r.Schema.Ref = spec.MustCreateRef(definitionRoot + modelName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(e.Headers) > 0 {
|
||||
r.Headers = make(map[string]spec.Header, len(e.Headers))
|
||||
for k, v := range e.Headers {
|
||||
r.Headers[k] = buildHeader(v)
|
||||
}
|
||||
}
|
||||
|
||||
extractVendorExtensions(&r.VendorExtensible, e.ExtensionProperties)
|
||||
return r
|
||||
}
|
||||
|
||||
// buildHeader builds a specification header structure from restful.Header
|
||||
func buildHeader(header restful.Header) spec.Header {
|
||||
responseHeader := spec.Header{}
|
||||
responseHeader.Type = header.Type
|
||||
responseHeader.Description = header.Description
|
||||
responseHeader.Format = header.Format
|
||||
responseHeader.Default = header.Default
|
||||
|
||||
// If type is "array" items field is required
|
||||
if header.Type == arrayType {
|
||||
responseHeader.CollectionFormat = header.CollectionFormat
|
||||
responseHeader.Items = buildHeadersItems(header.Items)
|
||||
}
|
||||
|
||||
return responseHeader
|
||||
}
|
||||
|
||||
// buildHeadersItems builds
|
||||
func buildHeadersItems(items *restful.Items) *spec.Items {
|
||||
responseItems := spec.NewItems()
|
||||
responseItems.Format = items.Format
|
||||
responseItems.Type = items.Type
|
||||
responseItems.Default = items.Default
|
||||
responseItems.CollectionFormat = items.CollectionFormat
|
||||
if items.Items != nil {
|
||||
responseItems.Items = buildHeadersItems(items.Items)
|
||||
}
|
||||
|
||||
return responseItems
|
||||
}
|
||||
|
||||
// stripTags takes a snippet of HTML and returns only the text content.
|
||||
// For example, `<b><Hi!></b> <br>` -> `<Hi!> `.
|
||||
func stripTags(html string) string {
|
||||
re := regexp.MustCompile("<[^>]*>")
|
||||
return re.ReplaceAllString(html, "")
|
||||
}
|
||||
|
||||
func isPrimitiveType(modelName string) bool {
|
||||
if len(modelName) == 0 {
|
||||
return false
|
||||
}
|
||||
return strings.Contains("uint uint8 uint16 uint32 uint64 int int8 int16 int32 int64 float32 float64 bool string byte rune time.Time time.Duration", modelName)
|
||||
}
|
||||
|
||||
func jsonSchemaType(modelName string) string {
|
||||
schemaMap := map[string]string{
|
||||
"uint": "integer",
|
||||
"uint8": "integer",
|
||||
"uint16": "integer",
|
||||
"uint32": "integer",
|
||||
"uint64": "integer",
|
||||
|
||||
"int": "integer",
|
||||
"int8": "integer",
|
||||
"int16": "integer",
|
||||
"int32": "integer",
|
||||
"int64": "integer",
|
||||
|
||||
"byte": "integer",
|
||||
"float64": "number",
|
||||
"float32": "number",
|
||||
"bool": "boolean",
|
||||
"time.Time": "string",
|
||||
"time.Duration": "integer",
|
||||
}
|
||||
mapped, ok := schemaMap[modelName]
|
||||
if !ok {
|
||||
return modelName // use as is (custom or struct)
|
||||
}
|
||||
return mapped
|
||||
}
|
||||
62
vendor/github.com/emicklei/go-restful-openapi/v2/config.go
generated
vendored
Normal file
62
vendor/github.com/emicklei/go-restful-openapi/v2/config.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package restfulspec
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// MapSchemaFormatFunc can be used to modify typeName at definition time.
|
||||
// To use it set the SchemaFormatHandler in the config.
|
||||
type MapSchemaFormatFunc func(typeName string) string
|
||||
|
||||
// MapModelTypeNameFunc can be used to return the desired typeName for a given
|
||||
// type. It will return false if the default name should be used.
|
||||
// To use it set the ModelTypeNameHandler in the config.
|
||||
type MapModelTypeNameFunc func(t reflect.Type) (string, bool)
|
||||
|
||||
// PostBuildSwaggerObjectFunc can be used to change the creates Swagger Object
|
||||
// before serving it. To use it set the PostBuildSwaggerObjectHandler in the config.
|
||||
type PostBuildSwaggerObjectFunc func(s *spec.Swagger)
|
||||
|
||||
// DefinitionNameHandlerFunc generate name by this handler for definition without json tag.
|
||||
// example: (for more, see file definition_name_test.go)
|
||||
// field definition_name
|
||||
// Name `json:"name"` -> name
|
||||
// Name -> Name
|
||||
//
|
||||
// there are some example provided for use
|
||||
// DefaultNameHandler GoRestfulDefinition -> GoRestfulDefinition (not changed)
|
||||
// LowerSnakeCasedNameHandler GoRestfulDefinition -> go_restful_definition
|
||||
// LowerCamelCasedNameHandler GoRestfulDefinition -> goRestfulDefinition
|
||||
// GoLowerCamelCasedNameHandler HTTPRestfulDefinition -> httpRestfulDefinition
|
||||
//
|
||||
type DefinitionNameHandlerFunc func(string) string
|
||||
|
||||
// Config holds service api metadata.
|
||||
type Config struct {
|
||||
// [optional] If set then set this field with the generated Swagger Object
|
||||
Host string
|
||||
// [optional] If set then set this field with the generated Swagger Object
|
||||
Schemes []string
|
||||
// WebServicesURL is a DEPRECATED field; it never had any effect in this package.
|
||||
WebServicesURL string
|
||||
// APIPath is the path where the JSON api is available, e.g. /apidocs.json
|
||||
APIPath string
|
||||
// api listing is constructed from this list of restful WebServices.
|
||||
WebServices []*restful.WebService
|
||||
// [optional] on default CORS (Cross-Origin-Resource-Sharing) is enabled.
|
||||
DisableCORS bool
|
||||
// Top-level API version. Is reflected in the resource listing.
|
||||
APIVersion string
|
||||
// [optional] If set, model builder should call this handler to get addition typename-to-swagger-format-field conversion.
|
||||
SchemaFormatHandler MapSchemaFormatFunc
|
||||
// [optional] If set, model builder should call this handler to retrieve the name for a given type.
|
||||
ModelTypeNameHandler MapModelTypeNameFunc
|
||||
// [optional] If set then call this function with the generated Swagger Object
|
||||
PostBuildSwaggerObjectHandler PostBuildSwaggerObjectFunc
|
||||
// [optional] If set then call handler's function for to generate name by this handler for definition without json tag,
|
||||
// you can use you DefinitionNameHandler, also, there are four DefinitionNameHandler provided, see definition_name.go
|
||||
DefinitionNameHandler DefinitionNameHandlerFunc
|
||||
}
|
||||
595
vendor/github.com/emicklei/go-restful-openapi/v2/definition_builder.go
generated
vendored
Normal file
595
vendor/github.com/emicklei/go-restful-openapi/v2/definition_builder.go
generated
vendored
Normal file
@@ -0,0 +1,595 @@
|
||||
package restfulspec
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
type definitionBuilder struct {
|
||||
Definitions spec.Definitions
|
||||
Config Config
|
||||
}
|
||||
|
||||
// Documented is
|
||||
type Documented interface {
|
||||
SwaggerDoc() map[string]string
|
||||
}
|
||||
|
||||
type PostBuildSwaggerSchema interface {
|
||||
PostBuildSwaggerSchemaHandler(sm *spec.Schema)
|
||||
}
|
||||
|
||||
// Check if this structure has a method with signature func (<theModel>) SwaggerDoc() map[string]string
|
||||
// If it exists, retrieve the documentation and overwrite all struct tag descriptions
|
||||
func getDocFromMethodSwaggerDoc2(model reflect.Type) map[string]string {
|
||||
if docable, ok := reflect.New(model).Elem().Interface().(Documented); ok {
|
||||
return docable.SwaggerDoc()
|
||||
}
|
||||
return make(map[string]string)
|
||||
}
|
||||
|
||||
// addModelFrom creates and adds a Schema to the builder and detects and calls
|
||||
// the post build hook for customizations
|
||||
func (b definitionBuilder) addModelFrom(sample interface{}) {
|
||||
b.addModel(reflect.TypeOf(sample), "")
|
||||
}
|
||||
|
||||
func (b definitionBuilder) addModel(st reflect.Type, nameOverride string) *spec.Schema {
|
||||
// Turn pointers into simpler types so further checks are
|
||||
// correct.
|
||||
isArray := false
|
||||
if st.Kind() == reflect.Ptr {
|
||||
st = st.Elem()
|
||||
}
|
||||
if b.isSliceOrArrayType(st.Kind()) {
|
||||
isArray = true
|
||||
st = st.Elem()
|
||||
}
|
||||
|
||||
modelName := keyFrom(st, b.Config)
|
||||
if nameOverride != "" {
|
||||
modelName = nameOverride
|
||||
}
|
||||
// no models needed for primitive types unless it has alias
|
||||
if b.isPrimitiveType(modelName, st.Kind()) {
|
||||
if nameOverride == "" {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// golang encoding/json packages says array and slice values encode as
|
||||
// JSON arrays, except that []byte encodes as a base64-encoded string.
|
||||
// If we see a []byte here, treat it at as a primitive type (string)
|
||||
// and deal with it in buildArrayTypeProperty.
|
||||
if b.isByteArrayType(st) {
|
||||
return nil
|
||||
}
|
||||
// see if we already have visited this model
|
||||
if _, ok := b.Definitions[modelName]; ok {
|
||||
return nil
|
||||
}
|
||||
sm := spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Required: []string{},
|
||||
Properties: map[string]spec.Schema{},
|
||||
},
|
||||
}
|
||||
|
||||
// fixes issue 77 but feels like a workaround.
|
||||
if b.isPrimitiveType(modelName, st.Kind()) {
|
||||
if isArray {
|
||||
sm.Type = []string{"array"}
|
||||
sm.Items = &spec.SchemaOrArray{Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{Type: []string{jsonSchemaType(st.Kind().String())}}}}
|
||||
}
|
||||
}
|
||||
|
||||
// reference the model before further initializing (enables recursive structs)
|
||||
b.Definitions[modelName] = sm
|
||||
|
||||
if st.Kind() == reflect.Map {
|
||||
_, sm = b.buildMapType(st, "value", modelName)
|
||||
b.Definitions[modelName] = sm
|
||||
return &sm
|
||||
}
|
||||
// check for structure or primitive type
|
||||
if st.Kind() != reflect.Struct {
|
||||
return &sm
|
||||
}
|
||||
|
||||
fullDoc := getDocFromMethodSwaggerDoc2(st)
|
||||
modelDescriptions := []string{}
|
||||
|
||||
for i := 0; i < st.NumField(); i++ {
|
||||
field := st.Field(i)
|
||||
jsonName, modelDescription, prop := b.buildProperty(field, &sm, modelName)
|
||||
if len(modelDescription) > 0 {
|
||||
modelDescriptions = append(modelDescriptions, modelDescription)
|
||||
}
|
||||
|
||||
// add if not omitted
|
||||
if len(jsonName) != 0 {
|
||||
// update description
|
||||
if fieldDoc, ok := fullDoc[jsonName]; ok {
|
||||
prop.Description = fieldDoc
|
||||
}
|
||||
// update Required
|
||||
if b.isPropertyRequired(field) {
|
||||
sm.Required = append(sm.Required, jsonName)
|
||||
}
|
||||
sm.Properties[jsonName] = prop
|
||||
}
|
||||
}
|
||||
|
||||
// We always overwrite documentation if SwaggerDoc method exists
|
||||
// "" is special for documenting the struct itself
|
||||
if modelDoc, ok := fullDoc[""]; ok {
|
||||
sm.Description = modelDoc
|
||||
} else if len(modelDescriptions) != 0 {
|
||||
sm.Description = strings.Join(modelDescriptions, "\n")
|
||||
}
|
||||
// Needed to pass openapi validation. This field exists for json-schema compatibility,
|
||||
// but it conflicts with the openapi specification.
|
||||
// See https://github.com/go-openapi/spec/issues/23 for more context
|
||||
sm.ID = ""
|
||||
|
||||
// Call handler to update sch
|
||||
if handler, ok := reflect.New(st).Elem().Interface().(PostBuildSwaggerSchema); ok {
|
||||
handler.PostBuildSwaggerSchemaHandler(&sm)
|
||||
}
|
||||
|
||||
// update model builder with completed model
|
||||
b.Definitions[modelName] = sm
|
||||
|
||||
return &sm
|
||||
}
|
||||
|
||||
func (b definitionBuilder) isPropertyRequired(field reflect.StructField) bool {
|
||||
required := true
|
||||
if optionalTag := field.Tag.Get("optional"); optionalTag == "true" {
|
||||
return false
|
||||
}
|
||||
if jsonTag := field.Tag.Get("json"); jsonTag != "" {
|
||||
s := strings.Split(jsonTag, ",")
|
||||
if len(s) > 1 && s[1] == "omitempty" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return required
|
||||
}
|
||||
|
||||
func (b definitionBuilder) buildProperty(field reflect.StructField, model *spec.Schema, modelName string) (jsonName, modelDescription string, prop spec.Schema) {
|
||||
jsonName = b.jsonNameOfField(field)
|
||||
if len(jsonName) == 0 {
|
||||
// empty name signals skip property
|
||||
return "", "", prop
|
||||
}
|
||||
|
||||
if field.Name == "XMLName" && field.Type.String() == "xml.Name" {
|
||||
// property is metadata for the xml.Name attribute, can be skipped
|
||||
return "", "", prop
|
||||
}
|
||||
|
||||
if tag := field.Tag.Get("modelDescription"); tag != "" {
|
||||
modelDescription = tag
|
||||
}
|
||||
|
||||
setPropertyMetadata(&prop, field)
|
||||
if prop.Type != nil {
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
fieldType := field.Type
|
||||
|
||||
// check if type is doing its own marshalling
|
||||
marshalerType := reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
if fieldType.Implements(marshalerType) {
|
||||
var pType = "string"
|
||||
if prop.Type == nil {
|
||||
prop.Type = []string{pType}
|
||||
}
|
||||
if prop.Format == "" {
|
||||
prop.Format = b.jsonSchemaFormat(keyFrom(fieldType, b.Config), fieldType.Kind())
|
||||
}
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
// check if annotation says it is a string
|
||||
if jsonTag := field.Tag.Get("json"); jsonTag != "" {
|
||||
s := strings.Split(jsonTag, ",")
|
||||
if len(s) > 1 && s[1] == "string" {
|
||||
stringt := "string"
|
||||
prop.Type = []string{stringt}
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
}
|
||||
|
||||
fieldKind := fieldType.Kind()
|
||||
switch {
|
||||
case fieldKind == reflect.Struct:
|
||||
jsonName, prop := b.buildStructTypeProperty(field, jsonName, model)
|
||||
return jsonName, modelDescription, prop
|
||||
case b.isSliceOrArrayType(fieldKind):
|
||||
jsonName, prop := b.buildArrayTypeProperty(field, jsonName, modelName)
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.Ptr:
|
||||
jsonName, prop := b.buildPointerTypeProperty(field, jsonName, modelName)
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.Map:
|
||||
jsonName, prop := b.buildMapTypeProperty(field, jsonName, modelName)
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
fieldTypeName := keyFrom(fieldType, b.Config)
|
||||
if b.isPrimitiveType(fieldTypeName, fieldKind) {
|
||||
mapped := b.jsonSchemaType(fieldTypeName, fieldKind)
|
||||
prop.Type = []string{mapped}
|
||||
prop.Format = b.jsonSchemaFormat(fieldTypeName, fieldKind)
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
modelType := keyFrom(fieldType, b.Config)
|
||||
prop.Ref = spec.MustCreateRef("#/definitions/" + modelType)
|
||||
|
||||
if fieldType.Name() == "" { // override type of anonymous structs
|
||||
// FIXME: Still need a way to handle anonymous struct model naming.
|
||||
nestedTypeName := modelName + "." + jsonName
|
||||
prop.Ref = spec.MustCreateRef("#/definitions/" + nestedTypeName)
|
||||
b.addModel(fieldType, nestedTypeName)
|
||||
}
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
func hasNamedJSONTag(field reflect.StructField) bool {
|
||||
parts := strings.Split(field.Tag.Get("json"), ",")
|
||||
if len(parts) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, s := range parts[1:] {
|
||||
if s == "inline" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return len(parts[0]) > 0
|
||||
}
|
||||
|
||||
func (b definitionBuilder) buildStructTypeProperty(field reflect.StructField, jsonName string, model *spec.Schema) (nameJson string, prop spec.Schema) {
|
||||
setPropertyMetadata(&prop, field)
|
||||
fieldType := field.Type
|
||||
// check for anonymous
|
||||
if len(fieldType.Name()) == 0 {
|
||||
// anonymous
|
||||
// FIXME: Still need a way to handle anonymous struct model naming.
|
||||
anonType := model.ID + "." + jsonName
|
||||
b.addModel(fieldType, anonType)
|
||||
prop.Ref = spec.MustCreateRef("#/definitions/" + anonType)
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
if field.Name == fieldType.Name() && field.Anonymous && !hasNamedJSONTag(field) {
|
||||
// embedded struct
|
||||
sub := definitionBuilder{b.Definitions, b.Config}
|
||||
sub.addModel(fieldType, "")
|
||||
subKey := keyFrom(fieldType, b.Config)
|
||||
// merge properties from sub
|
||||
subModel, _ := sub.Definitions[subKey]
|
||||
for k, v := range subModel.Properties {
|
||||
model.Properties[k] = v
|
||||
// if subModel says this property is required then include it
|
||||
required := false
|
||||
for _, each := range subModel.Required {
|
||||
if k == each {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if required {
|
||||
model.Required = append(model.Required, k)
|
||||
}
|
||||
}
|
||||
// add all new referenced models
|
||||
for key, sub := range sub.Definitions {
|
||||
if key != subKey {
|
||||
if _, ok := b.Definitions[key]; !ok {
|
||||
b.Definitions[key] = sub
|
||||
}
|
||||
}
|
||||
}
|
||||
// empty name signals skip property
|
||||
return "", prop
|
||||
}
|
||||
// simple struct
|
||||
b.addModel(fieldType, "")
|
||||
var pType = keyFrom(fieldType, b.Config)
|
||||
prop.Ref = spec.MustCreateRef("#/definitions/" + pType)
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
func (b definitionBuilder) buildArrayTypeProperty(field reflect.StructField, jsonName, modelName string) (nameJson string, prop spec.Schema) {
|
||||
setPropertyMetadata(&prop, field)
|
||||
fieldType := field.Type
|
||||
if fieldType.Elem().Kind() == reflect.Uint8 {
|
||||
stringt := "string"
|
||||
prop.Type = []string{stringt}
|
||||
return jsonName, prop
|
||||
}
|
||||
var pType = "array"
|
||||
prop.Type = []string{pType}
|
||||
isPrimitive := b.isPrimitiveType(fieldType.Elem().Name(), fieldType.Elem().Kind())
|
||||
elemTypeName := b.getElementTypeName(modelName, jsonName, fieldType.Elem())
|
||||
prop.Items = &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{},
|
||||
}
|
||||
if isPrimitive {
|
||||
mapped := b.jsonSchemaType(elemTypeName, fieldType.Elem().Kind())
|
||||
prop.Items.Schema.Type = []string{mapped}
|
||||
prop.Items.Schema.Format = b.jsonSchemaFormat(elemTypeName, fieldType.Elem().Kind())
|
||||
} else {
|
||||
prop.Items.Schema.Ref = spec.MustCreateRef("#/definitions/" + elemTypeName)
|
||||
}
|
||||
// add|overwrite model for element type
|
||||
if fieldType.Elem().Kind() == reflect.Ptr {
|
||||
fieldType = fieldType.Elem()
|
||||
}
|
||||
if !isPrimitive {
|
||||
b.addModel(fieldType.Elem(), elemTypeName)
|
||||
}
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
func (b definitionBuilder) buildMapTypeProperty(field reflect.StructField, jsonName, modelName string) (nameJson string, prop spec.Schema) {
|
||||
nameJson, prop = b.buildMapType(field.Type, jsonName, modelName)
|
||||
setPropertyMetadata(&prop, field)
|
||||
return nameJson, prop
|
||||
}
|
||||
|
||||
func (b definitionBuilder) buildMapType(mapType reflect.Type, jsonName, modelName string) (nameJson string, prop spec.Schema) {
|
||||
var pType = "object"
|
||||
prop.Type = []string{pType}
|
||||
|
||||
// As long as the element isn't an interface, we should be able to figure out what the
|
||||
// intended type is and represent it in `AdditionalProperties`.
|
||||
// See: https://swagger.io/docs/specification/data-models/dictionaries/
|
||||
if mapType.Elem().Kind().String() != "interface" {
|
||||
isSlice := b.isSliceOrArrayType(mapType.Elem().Kind())
|
||||
if isSlice && !b.isByteArrayType(mapType.Elem()) {
|
||||
mapType = mapType.Elem()
|
||||
}
|
||||
isPrimitive := b.isPrimitiveType(mapType.Elem().Name(), mapType.Elem().Kind())
|
||||
elemTypeName := b.getElementTypeName(modelName, jsonName, mapType.Elem())
|
||||
prop.AdditionalProperties = &spec.SchemaOrBool{
|
||||
Schema: &spec.Schema{},
|
||||
}
|
||||
// golang encoding/json packages says array and slice values encode as
|
||||
// JSON arrays, except that []byte encodes as a base64-encoded string.
|
||||
// If we see a []byte here, treat it at as a string
|
||||
if b.isByteArrayType(mapType.Elem()) {
|
||||
prop.AdditionalProperties.Schema.Type = []string{"string"}
|
||||
} else {
|
||||
if isSlice {
|
||||
var item *spec.Schema
|
||||
if isPrimitive {
|
||||
mapped := b.jsonSchemaType(elemTypeName, mapType.Kind())
|
||||
item = &spec.Schema{}
|
||||
item.Type = []string{mapped}
|
||||
item.Format = b.jsonSchemaFormat(elemTypeName, mapType.Kind())
|
||||
} else {
|
||||
item = spec.RefProperty("#/definitions/" + elemTypeName)
|
||||
}
|
||||
prop.AdditionalProperties.Schema = spec.ArrayProperty(item)
|
||||
} else if isPrimitive {
|
||||
mapped := b.jsonSchemaType(elemTypeName, mapType.Elem().Kind())
|
||||
prop.AdditionalProperties.Schema.Type = []string{mapped}
|
||||
} else {
|
||||
prop.AdditionalProperties.Schema.Ref = spec.MustCreateRef("#/definitions/" + elemTypeName)
|
||||
}
|
||||
// add|overwrite model for element type
|
||||
if mapType.Elem().Kind() == reflect.Ptr {
|
||||
mapType = mapType.Elem()
|
||||
}
|
||||
if !isPrimitive {
|
||||
b.addModel(mapType.Elem(), elemTypeName)
|
||||
}
|
||||
}
|
||||
}
|
||||
return jsonName, prop
|
||||
}
|
||||
func (b definitionBuilder) buildPointerTypeProperty(field reflect.StructField, jsonName, modelName string) (nameJson string, prop spec.Schema) {
|
||||
setPropertyMetadata(&prop, field)
|
||||
fieldType := field.Type
|
||||
|
||||
// override type of pointer to list-likes
|
||||
if fieldType.Elem().Kind() == reflect.Slice || fieldType.Elem().Kind() == reflect.Array {
|
||||
var pType = "array"
|
||||
prop.Type = []string{pType}
|
||||
isPrimitive := b.isPrimitiveType(fieldType.Elem().Elem().Name(), fieldType.Elem().Elem().Kind())
|
||||
elemName := b.getElementTypeName(modelName, jsonName, fieldType.Elem().Elem())
|
||||
prop.Items = &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{},
|
||||
}
|
||||
if isPrimitive {
|
||||
primName := b.jsonSchemaType(elemName, fieldType.Elem().Elem().Kind())
|
||||
prop.Items.Schema.Type = []string{primName}
|
||||
} else {
|
||||
prop.Items.Schema.Ref = spec.MustCreateRef("#/definitions/" + elemName)
|
||||
}
|
||||
if !isPrimitive {
|
||||
// add|overwrite model for element type
|
||||
b.addModel(fieldType.Elem().Elem(), elemName)
|
||||
}
|
||||
} else {
|
||||
// non-array, pointer type
|
||||
fieldTypeName := keyFrom(fieldType.Elem(), b.Config)
|
||||
isPrimitive := b.isPrimitiveType(fieldTypeName, fieldType.Elem().Kind())
|
||||
var pType = b.jsonSchemaType(fieldTypeName, fieldType.Elem().Kind()) // no star, include pkg path
|
||||
if isPrimitive {
|
||||
prop.Type = []string{pType}
|
||||
prop.Format = b.jsonSchemaFormat(fieldTypeName, fieldType.Elem().Kind())
|
||||
return jsonName, prop
|
||||
}
|
||||
prop.Ref = spec.MustCreateRef("#/definitions/" + pType)
|
||||
elemName := ""
|
||||
if fieldType.Elem().Name() == "" {
|
||||
elemName = modelName + "." + jsonName
|
||||
prop.Ref = spec.MustCreateRef("#/definitions/" + elemName)
|
||||
}
|
||||
if !isPrimitive {
|
||||
b.addModel(fieldType.Elem(), elemName)
|
||||
}
|
||||
}
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
func (b definitionBuilder) getElementTypeName(modelName, jsonName string, t reflect.Type) string {
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
if t.Name() == "" {
|
||||
return modelName + "." + jsonName
|
||||
}
|
||||
return keyFrom(t, b.Config)
|
||||
}
|
||||
|
||||
func keyFrom(st reflect.Type, cfg Config) string {
|
||||
key := st.String()
|
||||
if cfg.ModelTypeNameHandler != nil {
|
||||
if name, ok := cfg.ModelTypeNameHandler(st); ok {
|
||||
key = name
|
||||
}
|
||||
}
|
||||
if len(st.Name()) == 0 { // unnamed type
|
||||
// If it is an array, remove the leading []
|
||||
key = strings.TrimPrefix(key, "[]")
|
||||
// Swagger UI has special meaning for [
|
||||
key = strings.Replace(key, "[]", "||", -1)
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
func (b definitionBuilder) isSliceOrArrayType(t reflect.Kind) bool {
|
||||
return t == reflect.Slice || t == reflect.Array
|
||||
}
|
||||
|
||||
// Does the type represent a []byte?
|
||||
func (b definitionBuilder) isByteArrayType(t reflect.Type) bool {
|
||||
return (t.Kind() == reflect.Slice || t.Kind() == reflect.Array) &&
|
||||
t.Elem().Kind() == reflect.Uint8
|
||||
}
|
||||
|
||||
// see also https://golang.org/ref/spec#Numeric_types
|
||||
func (b definitionBuilder) isPrimitiveType(modelName string, modelKind reflect.Kind) bool {
|
||||
switch modelKind {
|
||||
case reflect.Bool:
|
||||
return true
|
||||
case reflect.Float32, reflect.Float64,
|
||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return true
|
||||
case reflect.String:
|
||||
return true
|
||||
}
|
||||
|
||||
if len(modelName) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return strings.Contains("time.Time time.Duration json.Number", modelName)
|
||||
}
|
||||
|
||||
// jsonNameOfField returns the name of the field as it should appear in JSON format
|
||||
// An empty string indicates that this field is not part of the JSON representation
|
||||
func (b definitionBuilder) jsonNameOfField(field reflect.StructField) string {
|
||||
if jsonTag := field.Tag.Get("json"); jsonTag != "" {
|
||||
s := strings.Split(jsonTag, ",")
|
||||
if s[0] == "-" {
|
||||
// empty name signals skip property
|
||||
return ""
|
||||
} else if s[0] != "" {
|
||||
return s[0]
|
||||
}
|
||||
}
|
||||
|
||||
if b.Config.DefinitionNameHandler == nil {
|
||||
b.Config.DefinitionNameHandler = DefaultNameHandler
|
||||
}
|
||||
return b.Config.DefinitionNameHandler(field.Name)
|
||||
}
|
||||
|
||||
// see also http://json-schema.org/latest/json-schema-core.html#anchor8
|
||||
func (b definitionBuilder) jsonSchemaType(modelName string, modelKind reflect.Kind) string {
|
||||
schemaMap := map[string]string{
|
||||
"time.Time": "string",
|
||||
"time.Duration": "integer",
|
||||
"json.Number": "number",
|
||||
}
|
||||
|
||||
if mapped, ok := schemaMap[modelName]; ok {
|
||||
return mapped
|
||||
}
|
||||
|
||||
// check if original type is primitive
|
||||
switch modelKind {
|
||||
case reflect.Bool:
|
||||
return "boolean"
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return "number"
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return "integer"
|
||||
case reflect.String:
|
||||
return "string"
|
||||
}
|
||||
|
||||
return modelName // use as is (custom or struct)
|
||||
}
|
||||
|
||||
func (b definitionBuilder) jsonSchemaFormat(modelName string, modelKind reflect.Kind) string {
|
||||
if b.Config.SchemaFormatHandler != nil {
|
||||
if mapped := b.Config.SchemaFormatHandler(modelName); mapped != "" {
|
||||
return mapped
|
||||
}
|
||||
}
|
||||
|
||||
schemaMap := map[string]string{
|
||||
"time.Time": "date-time",
|
||||
"*time.Time": "date-time",
|
||||
"time.Duration": "int64",
|
||||
"*time.Duration": "int64",
|
||||
"json.Number": "double",
|
||||
"*json.Number": "double",
|
||||
}
|
||||
|
||||
if mapped, ok := schemaMap[modelName]; ok {
|
||||
return mapped
|
||||
}
|
||||
|
||||
// check if original type is primitive
|
||||
switch modelKind {
|
||||
case reflect.Float32:
|
||||
return "float"
|
||||
case reflect.Float64:
|
||||
return "double"
|
||||
case reflect.Int:
|
||||
return "int32"
|
||||
case reflect.Int8:
|
||||
return "byte"
|
||||
case reflect.Int16:
|
||||
return "integer"
|
||||
case reflect.Int32:
|
||||
return "int32"
|
||||
case reflect.Int64:
|
||||
return "int64"
|
||||
case reflect.Uint:
|
||||
return "integer"
|
||||
case reflect.Uint8:
|
||||
return "byte"
|
||||
case reflect.Uint16:
|
||||
return "integer"
|
||||
case reflect.Uint32:
|
||||
return "integer"
|
||||
case reflect.Uint64:
|
||||
return "integer"
|
||||
}
|
||||
|
||||
return "" // no format
|
||||
}
|
||||
105
vendor/github.com/emicklei/go-restful-openapi/v2/definition_name.go
generated
vendored
Normal file
105
vendor/github.com/emicklei/go-restful-openapi/v2/definition_name.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
package restfulspec
|
||||
|
||||
import "strings"
|
||||
|
||||
// DefaultNameHandler GoRestfulDefinition -> GoRestfulDefinition (not changed)
|
||||
func DefaultNameHandler(name string) string {
|
||||
return name
|
||||
}
|
||||
|
||||
// LowerSnakeCasedNameHandler GoRestfulDefinition -> go_restful_definition
|
||||
func LowerSnakeCasedNameHandler(name string) string {
|
||||
definitionName := make([]byte, 0, len(name)+1)
|
||||
for i := 0; i < len(name); i++ {
|
||||
c := name[i]
|
||||
if isUpper(c) {
|
||||
if i > 0 {
|
||||
definitionName = append(definitionName, '_')
|
||||
}
|
||||
c += 'a' - 'A'
|
||||
}
|
||||
definitionName = append(definitionName, c)
|
||||
}
|
||||
|
||||
return string(definitionName)
|
||||
}
|
||||
|
||||
// LowerCamelCasedNameHandler GoRestfulDefinition -> goRestfulDefinition
|
||||
func LowerCamelCasedNameHandler(name string) string {
|
||||
definitionName := make([]byte, 0, len(name)+1)
|
||||
for i := 0; i < len(name); i++ {
|
||||
c := name[i]
|
||||
if isUpper(c) && i == 0 {
|
||||
c += 'a' - 'A'
|
||||
}
|
||||
definitionName = append(definitionName, c)
|
||||
}
|
||||
|
||||
return string(definitionName)
|
||||
}
|
||||
|
||||
// GoLowerCamelCasedNameHandler HTTPRestfulDefinition -> httpRestfulDefinition
|
||||
func GoLowerCamelCasedNameHandler(name string) string {
|
||||
var i = 0
|
||||
// for continuous Upper letters, check whether is it a common Initialisms
|
||||
for ; i < len(name) && isUpper(name[i]); i++ {
|
||||
}
|
||||
if len(name) != i && i > 1 {
|
||||
i-- // for continuous Upper letters, the last Upper is should not be check, eg: S for HTTPStatus
|
||||
}
|
||||
for ; i > 1; i-- {
|
||||
if _, ok := commonInitialisms[name[:i]]; ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return strings.ToLower(name[:i]) + name[i:]
|
||||
}
|
||||
|
||||
// commonInitialisms is a set of common initialisms. (from https://github.com/golang/lint/blob/master/lint.go)
|
||||
// Only add entries that are highly unlikely to be non-initialisms.
|
||||
// For instance, "ID" is fine (Freudian code is rare), but "AND" is not.
|
||||
var commonInitialisms = map[string]bool{
|
||||
"ACL": true,
|
||||
"API": true,
|
||||
"ASCII": true,
|
||||
"CPU": true,
|
||||
"CSS": true,
|
||||
"DNS": true,
|
||||
"EOF": true,
|
||||
"GUID": true,
|
||||
"HTML": true,
|
||||
"HTTP": true,
|
||||
"HTTPS": true,
|
||||
"ID": true,
|
||||
"IP": true,
|
||||
"JSON": true,
|
||||
"LHS": true,
|
||||
"QPS": true,
|
||||
"RAM": true,
|
||||
"RHS": true,
|
||||
"RPC": true,
|
||||
"SLA": true,
|
||||
"SMTP": true,
|
||||
"SQL": true,
|
||||
"SSH": true,
|
||||
"TCP": true,
|
||||
"TLS": true,
|
||||
"TTL": true,
|
||||
"UDP": true,
|
||||
"UI": true,
|
||||
"UID": true,
|
||||
"UUID": true,
|
||||
"URI": true,
|
||||
"URL": true,
|
||||
"UTF8": true,
|
||||
"VM": true,
|
||||
"XML": true,
|
||||
"XMPP": true,
|
||||
"XSRF": true,
|
||||
"XSS": true,
|
||||
}
|
||||
|
||||
func isUpper(r uint8) bool {
|
||||
return 'A' <= r && r <= 'Z'
|
||||
}
|
||||
19
vendor/github.com/emicklei/go-restful-openapi/v2/lookup.go
generated
vendored
Normal file
19
vendor/github.com/emicklei/go-restful-openapi/v2/lookup.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
package restfulspec
|
||||
|
||||
import restful "github.com/emicklei/go-restful/v3"
|
||||
|
||||
func asParamType(kind int) string {
|
||||
switch {
|
||||
case kind == restful.PathParameterKind:
|
||||
return "path"
|
||||
case kind == restful.QueryParameterKind:
|
||||
return "query"
|
||||
case kind == restful.BodyParameterKind:
|
||||
return "body"
|
||||
case kind == restful.HeaderParameterKind:
|
||||
return "header"
|
||||
case kind == restful.FormParameterKind:
|
||||
return "formData"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
138
vendor/github.com/emicklei/go-restful-openapi/v2/property_ext.go
generated
vendored
Normal file
138
vendor/github.com/emicklei/go-restful-openapi/v2/property_ext.go
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
package restfulspec
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
func initPropExtensions(ext *spec.Extensions) {
|
||||
if *ext == nil {
|
||||
*ext = make(spec.Extensions, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func setDescription(prop *spec.Schema, field reflect.StructField) {
|
||||
if tag := field.Tag.Get("description"); tag != "" {
|
||||
prop.Description = tag
|
||||
}
|
||||
}
|
||||
|
||||
func setDefaultValue(prop *spec.Schema, field reflect.StructField) {
|
||||
if tag := field.Tag.Get("default"); tag != "" {
|
||||
prop.Default = stringAutoType(tag)
|
||||
}
|
||||
}
|
||||
|
||||
func setIsNullableValue(prop *spec.Schema, field reflect.StructField) {
|
||||
if tag := field.Tag.Get("x-nullable"); tag != "" {
|
||||
initPropExtensions(&prop.Extensions)
|
||||
|
||||
value, err := strconv.ParseBool(tag)
|
||||
|
||||
prop.Extensions["x-nullable"] = value && err == nil
|
||||
}
|
||||
}
|
||||
|
||||
func setGoNameValue(prop *spec.Schema, field reflect.StructField) {
|
||||
const tagName = "x-go-name"
|
||||
if tag := field.Tag.Get(tagName); tag != "" {
|
||||
initPropExtensions(&prop.Extensions)
|
||||
prop.Extensions[tagName] = tag
|
||||
}
|
||||
}
|
||||
|
||||
func setEnumValues(prop *spec.Schema, field reflect.StructField) {
|
||||
// We use | to separate the enum values. This value is chosen
|
||||
// since it's unlikely to be useful in actual enumeration values.
|
||||
if tag := field.Tag.Get("enum"); tag != "" {
|
||||
enums := []interface{}{}
|
||||
for _, s := range strings.Split(tag, "|") {
|
||||
enums = append(enums, s)
|
||||
}
|
||||
prop.Enum = enums
|
||||
}
|
||||
}
|
||||
|
||||
func setFormat(prop *spec.Schema, field reflect.StructField) {
|
||||
if tag := field.Tag.Get("format"); tag != "" {
|
||||
prop.Format = tag
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func setMaximum(prop *spec.Schema, field reflect.StructField) {
|
||||
if tag := field.Tag.Get("maximum"); tag != "" {
|
||||
value, err := strconv.ParseFloat(tag, 64)
|
||||
if err == nil {
|
||||
prop.Maximum = &value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setMinimum(prop *spec.Schema, field reflect.StructField) {
|
||||
if tag := field.Tag.Get("minimum"); tag != "" {
|
||||
value, err := strconv.ParseFloat(tag, 64)
|
||||
if err == nil {
|
||||
prop.Minimum = &value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setType(prop *spec.Schema, field reflect.StructField) {
|
||||
if tag := field.Tag.Get("type"); tag != "" {
|
||||
// Check if the first two characters of the type tag are
|
||||
// intended to emulate slice/array behaviour.
|
||||
//
|
||||
// If type is intended to be a slice/array then add the
|
||||
// overridden type to the array item instead of the main property
|
||||
if len(tag) > 2 && tag[0:2] == "[]" {
|
||||
pType := "array"
|
||||
prop.Type = []string{pType}
|
||||
prop.Items = &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{},
|
||||
}
|
||||
iType := tag[2:]
|
||||
prop.Items.Schema.Type = []string{iType}
|
||||
return
|
||||
}
|
||||
|
||||
prop.Type = []string{tag}
|
||||
}
|
||||
}
|
||||
|
||||
func setUniqueItems(prop *spec.Schema, field reflect.StructField) {
|
||||
tag := field.Tag.Get("unique")
|
||||
switch tag {
|
||||
case "true":
|
||||
prop.UniqueItems = true
|
||||
case "false":
|
||||
prop.UniqueItems = false
|
||||
}
|
||||
}
|
||||
|
||||
func setReadOnly(prop *spec.Schema, field reflect.StructField) {
|
||||
tag := field.Tag.Get("readOnly")
|
||||
switch tag {
|
||||
case "true":
|
||||
prop.ReadOnly = true
|
||||
case "false":
|
||||
prop.ReadOnly = false
|
||||
}
|
||||
}
|
||||
|
||||
func setPropertyMetadata(prop *spec.Schema, field reflect.StructField) {
|
||||
setDescription(prop, field)
|
||||
setDefaultValue(prop, field)
|
||||
setEnumValues(prop, field)
|
||||
setFormat(prop, field)
|
||||
setMinimum(prop, field)
|
||||
setMaximum(prop, field)
|
||||
setUniqueItems(prop, field)
|
||||
setType(prop, field)
|
||||
setReadOnly(prop, field)
|
||||
setIsNullableValue(prop, field)
|
||||
setGoNameValue(prop, field)
|
||||
}
|
||||
78
vendor/github.com/emicklei/go-restful-openapi/v2/spec_resource.go
generated
vendored
Normal file
78
vendor/github.com/emicklei/go-restful-openapi/v2/spec_resource.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
package restfulspec
|
||||
|
||||
import (
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// NewOpenAPIService returns a new WebService that provides the API documentation of all services
|
||||
// conform the OpenAPI documentation specifcation.
|
||||
func NewOpenAPIService(config Config) *restful.WebService {
|
||||
|
||||
ws := new(restful.WebService)
|
||||
ws.Path(config.APIPath)
|
||||
ws.Produces(restful.MIME_JSON)
|
||||
if !config.DisableCORS {
|
||||
ws.Filter(enableCORS)
|
||||
}
|
||||
|
||||
swagger := BuildSwagger(config)
|
||||
resource := specResource{swagger: swagger}
|
||||
ws.Route(ws.GET("/").To(resource.getSwagger))
|
||||
return ws
|
||||
}
|
||||
|
||||
// BuildSwagger returns a Swagger object for all services' API endpoints.
|
||||
func BuildSwagger(config Config) *spec.Swagger {
|
||||
// collect paths and model definitions to build Swagger object.
|
||||
paths := &spec.Paths{Paths: map[string]spec.PathItem{}}
|
||||
definitions := spec.Definitions{}
|
||||
|
||||
for _, each := range config.WebServices {
|
||||
for path, item := range buildPaths(each, config).Paths {
|
||||
existingPathItem, ok := paths.Paths[path]
|
||||
if ok {
|
||||
for _, r := range each.Routes() {
|
||||
_, patterns := sanitizePath(r.Path)
|
||||
item = buildPathItem(each, r, existingPathItem, patterns, config)
|
||||
}
|
||||
}
|
||||
paths.Paths[path] = item
|
||||
}
|
||||
for name, def := range buildDefinitions(each, config) {
|
||||
definitions[name] = def
|
||||
}
|
||||
}
|
||||
swagger := &spec.Swagger{
|
||||
SwaggerProps: spec.SwaggerProps{
|
||||
Host: config.Host,
|
||||
Schemes: config.Schemes,
|
||||
Swagger: "2.0",
|
||||
Paths: paths,
|
||||
Definitions: definitions,
|
||||
},
|
||||
}
|
||||
if config.PostBuildSwaggerObjectHandler != nil {
|
||||
config.PostBuildSwaggerObjectHandler(swagger)
|
||||
}
|
||||
return swagger
|
||||
}
|
||||
|
||||
func enableCORS(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
|
||||
if origin := req.HeaderParameter(restful.HEADER_Origin); origin != "" {
|
||||
// prevent duplicate header
|
||||
if len(resp.Header().Get(restful.HEADER_AccessControlAllowOrigin)) == 0 {
|
||||
resp.AddHeader(restful.HEADER_AccessControlAllowOrigin, origin)
|
||||
}
|
||||
}
|
||||
chain.ProcessFilter(req, resp)
|
||||
}
|
||||
|
||||
// specResource is a REST resource to serve the Open-API spec.
|
||||
type specResource struct {
|
||||
swagger *spec.Swagger
|
||||
}
|
||||
|
||||
func (s specResource) getSwagger(req *restful.Request, resp *restful.Response) {
|
||||
resp.WriteAsJson(s.swagger)
|
||||
}
|
||||
Reference in New Issue
Block a user