go: vendor the oapi-codegen cmd
See the comment in tools.go, I cannot fully explain what's happening here. Somehow, Go 1.14 wants to use the vendored version of oapi-codegen but without this file, oapi-codegen isn't vendored so the generation fails. Signed-off-by: Ondřej Budai <ondrej@budai.cz>
This commit is contained in:
parent
1a3cbb282a
commit
2241a8d9ed
75 changed files with 11211 additions and 0 deletions
2
go.sum
2
go.sum
|
|
@ -72,6 +72,7 @@ github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAU
|
|||
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219 h1:utua3L2IbQJmauC5IXdEA547bcoU5dozgQAfc8Onsg4=
|
||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
|
|
@ -160,6 +161,7 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
|||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191203134012-c197fd4bf371 h1:Cjq6sG3gnKDchzWy7ouGQklhxMtWvh4AhSNJ0qGIeo4=
|
||||
golang.org/x/tools v0.0.0-20191203134012-c197fd4bf371/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
|
|||
15
internal/tools.go
Normal file
15
internal/tools.go
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// +build tools
|
||||
|
||||
// This file is here to just explicitly tell `go mod vendor` that we depend
|
||||
// on oapi-codegen. Without this file, `go generate ./...` in Go >= 1.14 gets
|
||||
// confused because oapi-codegen is not being vendored.
|
||||
//
|
||||
// This is apparently the conventional way, see:
|
||||
// https://stackoverflow.com/questions/52428230/how-do-go-modules-work-with-installable-commands
|
||||
// https://github.com/golang/go/issues/29516
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/deepmap/oapi-codegen/cmd/oapi-codegen"
|
||||
)
|
||||
173
vendor/github.com/deepmap/oapi-codegen/cmd/oapi-codegen/oapi-codegen.go
generated
vendored
Normal file
173
vendor/github.com/deepmap/oapi-codegen/cmd/oapi-codegen/oapi-codegen.go
generated
vendored
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/deepmap/oapi-codegen/pkg/codegen"
|
||||
"github.com/deepmap/oapi-codegen/pkg/util"
|
||||
)
|
||||
|
||||
func errExit(format string, args ...interface{}) {
|
||||
_, _ = fmt.Fprintf(os.Stderr, format, args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
packageName string
|
||||
generate string
|
||||
outputFile string
|
||||
includeTags string
|
||||
excludeTags string
|
||||
templatesDir string
|
||||
importMapping string
|
||||
excludeSchemas string
|
||||
)
|
||||
flag.StringVar(&packageName, "package", "", "The package name for generated code")
|
||||
flag.StringVar(&generate, "generate", "types,client,server,spec",
|
||||
`Comma-separated list of code to generate; valid options: "types", "client", "chi-server", "server", "spec", "skip-fmt", "skip-prune"`)
|
||||
flag.StringVar(&outputFile, "o", "", "Where to output generated code, stdout is default")
|
||||
flag.StringVar(&includeTags, "include-tags", "", "Only include operations with the given tags. Comma-separated list of tags.")
|
||||
flag.StringVar(&excludeTags, "exclude-tags", "", "Exclude operations that are tagged with the given tags. Comma-separated list of tags.")
|
||||
flag.StringVar(&templatesDir, "templates", "", "Path to directory containing user templates")
|
||||
flag.StringVar(&importMapping, "import-mapping", "", "A dict from the external reference to golang package path")
|
||||
flag.StringVar(&excludeSchemas, "exclude-schemas", "", "A comma separated list of schemas which must be excluded from generation")
|
||||
flag.Parse()
|
||||
|
||||
if flag.NArg() < 1 {
|
||||
fmt.Println("Please specify a path to a OpenAPI 3.0 spec file")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// If the package name has not been specified, we will use the name of the
|
||||
// swagger file.
|
||||
if packageName == "" {
|
||||
path := flag.Arg(0)
|
||||
baseName := filepath.Base(path)
|
||||
// Split the base name on '.' to get the first part of the file.
|
||||
nameParts := strings.Split(baseName, ".")
|
||||
packageName = codegen.ToCamelCase(nameParts[0])
|
||||
}
|
||||
|
||||
opts := codegen.Options{}
|
||||
for _, g := range splitCSVArg(generate) {
|
||||
switch g {
|
||||
case "client":
|
||||
opts.GenerateClient = true
|
||||
case "chi-server":
|
||||
opts.GenerateChiServer = true
|
||||
case "server":
|
||||
opts.GenerateEchoServer = true
|
||||
case "types":
|
||||
opts.GenerateTypes = true
|
||||
case "spec":
|
||||
opts.EmbedSpec = true
|
||||
case "skip-fmt":
|
||||
opts.SkipFmt = true
|
||||
case "skip-prune":
|
||||
opts.SkipPrune = true
|
||||
default:
|
||||
fmt.Printf("unknown generate option %s\n", g)
|
||||
flag.PrintDefaults()
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
opts.IncludeTags = splitCSVArg(includeTags)
|
||||
opts.ExcludeTags = splitCSVArg(excludeTags)
|
||||
opts.ExcludeSchemas = splitCSVArg(excludeSchemas)
|
||||
|
||||
if opts.GenerateEchoServer && opts.GenerateChiServer {
|
||||
errExit("can not specify both server and chi-server targets simultaneously")
|
||||
}
|
||||
|
||||
swagger, err := util.LoadSwagger(flag.Arg(0))
|
||||
if err != nil {
|
||||
errExit("error loading swagger spec\n: %s", err)
|
||||
}
|
||||
|
||||
templates, err := loadTemplateOverrides(templatesDir)
|
||||
if err != nil {
|
||||
errExit("error loading template overrides: %s\n", err)
|
||||
}
|
||||
opts.UserTemplates = templates
|
||||
|
||||
if len(importMapping) > 0 {
|
||||
opts.ImportMapping, err = util.ParseCommandlineMap(importMapping)
|
||||
if err != nil {
|
||||
errExit("error parsing import-mapping: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
code, err := codegen.Generate(swagger, packageName, opts)
|
||||
if err != nil {
|
||||
errExit("error generating code: %s\n", err)
|
||||
}
|
||||
|
||||
if outputFile != "" {
|
||||
err = ioutil.WriteFile(outputFile, []byte(code), 0644)
|
||||
if err != nil {
|
||||
errExit("error writing generated code to file: %s", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Println(code)
|
||||
}
|
||||
}
|
||||
|
||||
func splitCSVArg(input string) []string {
|
||||
input = strings.TrimSpace(input)
|
||||
if len(input) == 0 {
|
||||
return nil
|
||||
}
|
||||
splitInput := strings.Split(input, ",")
|
||||
args := make([]string, 0, len(splitInput))
|
||||
for _, s := range splitInput {
|
||||
s = strings.TrimSpace(s)
|
||||
if len(s) > 0 {
|
||||
args = append(args, s)
|
||||
}
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func loadTemplateOverrides(templatesDir string) (map[string]string, error) {
|
||||
var templates = make(map[string]string)
|
||||
|
||||
if templatesDir == "" {
|
||||
return templates, nil
|
||||
}
|
||||
|
||||
files, err := ioutil.ReadDir(templatesDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
data, err := ioutil.ReadFile(path.Join(templatesDir, f.Name()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
templates[f.Name()] = string(data)
|
||||
}
|
||||
|
||||
return templates, nil
|
||||
}
|
||||
572
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/codegen.go
generated
vendored
Normal file
572
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/codegen.go
generated
vendored
Normal file
|
|
@ -0,0 +1,572 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/deepmap/oapi-codegen/pkg/codegen/templates"
|
||||
)
|
||||
|
||||
// Options defines the optional code to generate.
|
||||
type Options struct {
|
||||
GenerateChiServer bool // GenerateChiServer specifies whether to generate chi server boilerplate
|
||||
GenerateEchoServer bool // GenerateEchoServer specifies whether to generate echo server boilerplate
|
||||
GenerateClient bool // GenerateClient specifies whether to generate client boilerplate
|
||||
GenerateTypes bool // GenerateTypes specifies whether to generate type definitions
|
||||
EmbedSpec bool // Whether to embed the swagger spec in the generated code
|
||||
SkipFmt bool // Whether to skip go fmt on the generated code
|
||||
SkipPrune bool // Whether to skip pruning unused components on the generated code
|
||||
IncludeTags []string // Only include operations that have one of these tags. Ignored when empty.
|
||||
ExcludeTags []string // Exclude operations that have one of these tags. Ignored when empty.
|
||||
UserTemplates map[string]string // Override built-in templates from user-provided files
|
||||
ImportMapping map[string]string // ImportMapping specifies the golang package path for each external reference
|
||||
ExcludeSchemas []string // Exclude from generation schemas with given names. Ignored when empty.
|
||||
}
|
||||
|
||||
type goImport struct {
|
||||
lookFor string
|
||||
alias string
|
||||
packageName string
|
||||
}
|
||||
|
||||
func (i goImport) String() string {
|
||||
if i.alias != "" {
|
||||
return fmt.Sprintf("%s %q", i.alias, i.packageName)
|
||||
}
|
||||
return fmt.Sprintf("%q", i.packageName)
|
||||
}
|
||||
|
||||
type goImports []goImport
|
||||
|
||||
var (
|
||||
allGoImports = goImports{
|
||||
{lookFor: "base64\\.", packageName: "encoding/base64"},
|
||||
{lookFor: "bytes\\.", packageName: "bytes"},
|
||||
{lookFor: "chi\\.", packageName: "github.com/go-chi/chi"},
|
||||
{lookFor: "context\\.", packageName: "context"},
|
||||
{lookFor: "echo\\.", packageName: "github.com/labstack/echo/v4"},
|
||||
{lookFor: "errors\\.", packageName: "github.com/pkg/errors"},
|
||||
{lookFor: "fmt\\.", packageName: "fmt"},
|
||||
{lookFor: "gzip\\.", packageName: "compress/gzip"},
|
||||
{lookFor: "http\\.", packageName: "net/http"},
|
||||
{lookFor: "io\\.", packageName: "io"},
|
||||
{lookFor: "ioutil\\.", packageName: "io/ioutil"},
|
||||
{lookFor: "json\\.", packageName: "encoding/json"},
|
||||
{lookFor: "openapi3\\.", packageName: "github.com/getkin/kin-openapi/openapi3"},
|
||||
{lookFor: "openapi_types\\.", alias: "openapi_types", packageName: "github.com/deepmap/oapi-codegen/pkg/types"},
|
||||
{lookFor: "path\\.", packageName: "path"},
|
||||
{lookFor: "runtime\\.", packageName: "github.com/deepmap/oapi-codegen/pkg/runtime"},
|
||||
{lookFor: "strings\\.", packageName: "strings"},
|
||||
{lookFor: "time\\.Duration", packageName: "time"},
|
||||
{lookFor: "time\\.Time", packageName: "time"},
|
||||
{lookFor: "url\\.", packageName: "net/url"},
|
||||
{lookFor: "xml\\.", packageName: "encoding/xml"},
|
||||
{lookFor: "yaml\\.", packageName: "gopkg.in/yaml.v2"},
|
||||
}
|
||||
|
||||
importMapping = map[string]goImport{}
|
||||
)
|
||||
|
||||
func constructImportMapping(input map[string]string) map[string]goImport {
|
||||
var (
|
||||
nameToAlias = map[string]string{}
|
||||
result = map[string]goImport{}
|
||||
)
|
||||
|
||||
{
|
||||
var packagePaths []string
|
||||
for _, packageName := range input {
|
||||
packagePaths = append(packagePaths, packageName)
|
||||
}
|
||||
sort.Strings(packagePaths)
|
||||
|
||||
for _, packageName := range packagePaths {
|
||||
if _, ok := nameToAlias[packageName]; !ok {
|
||||
nameToAlias[packageName] = fmt.Sprintf("externalRef%d", len(nameToAlias))
|
||||
}
|
||||
}
|
||||
}
|
||||
for urlOrPath, packageName := range input {
|
||||
result[urlOrPath] = goImport{alias: nameToAlias[packageName], packageName: packageName}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Uses the Go templating engine to generate all of our server wrappers from
|
||||
// the descriptions we've built up above from the schema objects.
|
||||
// opts defines
|
||||
func Generate(swagger *openapi3.Swagger, packageName string, opts Options) (string, error) {
|
||||
importMapping = constructImportMapping(opts.ImportMapping)
|
||||
|
||||
filterOperationsByTag(swagger, opts)
|
||||
if !opts.SkipPrune {
|
||||
pruneUnusedComponents(swagger)
|
||||
}
|
||||
|
||||
// This creates the golang templates text package
|
||||
t := template.New("oapi-codegen").Funcs(TemplateFunctions)
|
||||
// This parses all of our own template files into the template object
|
||||
// above
|
||||
t, err := templates.Parse(t)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error parsing oapi-codegen templates")
|
||||
}
|
||||
|
||||
// Override built-in templates with user-provided versions
|
||||
for _, tpl := range t.Templates() {
|
||||
if _, ok := opts.UserTemplates[tpl.Name()]; ok {
|
||||
utpl := t.New(tpl.Name())
|
||||
if _, err := utpl.Parse(opts.UserTemplates[tpl.Name()]); err != nil {
|
||||
return "", errors.Wrapf(err, "error parsing user-provided template %q", tpl.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ops, err := OperationDefinitions(swagger)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error creating operation definitions")
|
||||
}
|
||||
|
||||
var typeDefinitions string
|
||||
if opts.GenerateTypes {
|
||||
typeDefinitions, err = GenerateTypeDefinitions(t, swagger, ops, opts.ExcludeSchemas)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating type definitions")
|
||||
}
|
||||
}
|
||||
|
||||
var echoServerOut string
|
||||
if opts.GenerateEchoServer {
|
||||
echoServerOut, err = GenerateEchoServer(t, ops)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating Go handlers for Paths")
|
||||
}
|
||||
}
|
||||
|
||||
var chiServerOut string
|
||||
if opts.GenerateChiServer {
|
||||
chiServerOut, err = GenerateChiServer(t, ops)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating Go handlers for Paths")
|
||||
}
|
||||
}
|
||||
|
||||
var clientOut string
|
||||
if opts.GenerateClient {
|
||||
clientOut, err = GenerateClient(t, ops)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating client")
|
||||
}
|
||||
}
|
||||
|
||||
var clientWithResponsesOut string
|
||||
if opts.GenerateClient {
|
||||
clientWithResponsesOut, err = GenerateClientWithResponses(t, ops)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating client with responses")
|
||||
}
|
||||
}
|
||||
|
||||
var inlinedSpec string
|
||||
if opts.EmbedSpec {
|
||||
inlinedSpec, err = GenerateInlinedSpec(t, swagger)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating Go handlers for Paths")
|
||||
}
|
||||
}
|
||||
|
||||
// Imports needed for the generated code to compile
|
||||
var imports []string
|
||||
for _, importGo := range importMapping {
|
||||
imports = append(imports, importGo.String())
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
// Based on module prefixes, figure out which optional imports are required.
|
||||
pkgs := make(map[string]int)
|
||||
for _, str := range []string{typeDefinitions, chiServerOut, echoServerOut, clientOut, clientWithResponsesOut, inlinedSpec} {
|
||||
for _, line := range strings.Split(strings.TrimSpace(str), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
|
||||
if line == "" || strings.HasPrefix(line, "//") {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, goImport := range allGoImports {
|
||||
match, err := regexp.MatchString(fmt.Sprintf("[^a-zA-Z0-9_]%s", goImport.lookFor), line)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error figuring out imports")
|
||||
}
|
||||
|
||||
if match {
|
||||
pkgs[goImport.String()]++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k := range pkgs {
|
||||
imports = append(imports, k)
|
||||
}
|
||||
|
||||
importsOut, err := GenerateImports(t, imports, packageName)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating imports")
|
||||
}
|
||||
|
||||
_, err = w.WriteString(importsOut)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error writing imports")
|
||||
}
|
||||
|
||||
_, err = w.WriteString(typeDefinitions)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error writing type definitions")
|
||||
|
||||
}
|
||||
|
||||
if opts.GenerateClient {
|
||||
_, err = w.WriteString(clientOut)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error writing client")
|
||||
}
|
||||
_, err = w.WriteString(clientWithResponsesOut)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error writing client")
|
||||
}
|
||||
}
|
||||
|
||||
if opts.GenerateEchoServer {
|
||||
_, err = w.WriteString(echoServerOut)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error writing server path handlers")
|
||||
}
|
||||
}
|
||||
|
||||
if opts.GenerateChiServer {
|
||||
_, err = w.WriteString(chiServerOut)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error writing server path handlers")
|
||||
}
|
||||
}
|
||||
|
||||
if opts.EmbedSpec {
|
||||
_, err = w.WriteString(inlinedSpec)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error writing inlined spec")
|
||||
}
|
||||
}
|
||||
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error flushing output buffer")
|
||||
}
|
||||
|
||||
// remove any byte-order-marks which break Go-Code
|
||||
goCode := SanitizeCode(buf.String())
|
||||
|
||||
// The generation code produces unindented horrors. Use the Go formatter
|
||||
// to make it all pretty.
|
||||
if opts.SkipFmt {
|
||||
return goCode, nil
|
||||
}
|
||||
outBytes, err := format.Source([]byte(goCode))
|
||||
if err != nil {
|
||||
fmt.Println(goCode)
|
||||
return "", errors.Wrap(err, "error formatting Go code")
|
||||
}
|
||||
return string(outBytes), nil
|
||||
}
|
||||
|
||||
func GenerateTypeDefinitions(t *template.Template, swagger *openapi3.Swagger, ops []OperationDefinition, excludeSchemas []string) (string, error) {
|
||||
schemaTypes, err := GenerateTypesForSchemas(t, swagger.Components.Schemas, excludeSchemas)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating Go types for component schemas")
|
||||
}
|
||||
|
||||
paramTypes, err := GenerateTypesForParameters(t, swagger.Components.Parameters)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating Go types for component parameters")
|
||||
}
|
||||
allTypes := append(schemaTypes, paramTypes...)
|
||||
|
||||
responseTypes, err := GenerateTypesForResponses(t, swagger.Components.Responses)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating Go types for component responses")
|
||||
}
|
||||
allTypes = append(allTypes, responseTypes...)
|
||||
|
||||
bodyTypes, err := GenerateTypesForRequestBodies(t, swagger.Components.RequestBodies)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating Go types for component request bodies")
|
||||
}
|
||||
allTypes = append(allTypes, bodyTypes...)
|
||||
|
||||
paramTypesOut, err := GenerateTypesForOperations(t, ops)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating Go types for operation parameters")
|
||||
}
|
||||
|
||||
typesOut, err := GenerateTypes(t, allTypes)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating code for type definitions")
|
||||
}
|
||||
|
||||
allOfBoilerplate, err := GenerateAdditionalPropertyBoilerplate(t, allTypes)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating allOf boilerplate")
|
||||
}
|
||||
|
||||
typeDefinitions := strings.Join([]string{typesOut, paramTypesOut, allOfBoilerplate}, "")
|
||||
return typeDefinitions, nil
|
||||
}
|
||||
|
||||
// Generates type definitions for any custom types defined in the
|
||||
// components/schemas section of the Swagger spec.
|
||||
func GenerateTypesForSchemas(t *template.Template, schemas map[string]*openapi3.SchemaRef, excludeSchemas []string) ([]TypeDefinition, error) {
|
||||
var excludeSchemasMap = make(map[string]bool)
|
||||
for _, schema := range excludeSchemas {
|
||||
excludeSchemasMap[schema] = true
|
||||
}
|
||||
types := make([]TypeDefinition, 0)
|
||||
// We're going to define Go types for every object under components/schemas
|
||||
for _, schemaName := range SortedSchemaKeys(schemas) {
|
||||
if _, ok := excludeSchemasMap[schemaName]; ok {
|
||||
continue
|
||||
}
|
||||
schemaRef := schemas[schemaName]
|
||||
|
||||
goSchema, err := GenerateGoSchema(schemaRef, []string{schemaName})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("error converting Schema %s to Go type", schemaName))
|
||||
}
|
||||
|
||||
types = append(types, TypeDefinition{
|
||||
JsonName: schemaName,
|
||||
TypeName: SchemaNameToTypeName(schemaName),
|
||||
Schema: goSchema,
|
||||
})
|
||||
|
||||
types = append(types, goSchema.GetAdditionalTypeDefs()...)
|
||||
}
|
||||
return types, nil
|
||||
}
|
||||
|
||||
// Generates type definitions for any custom types defined in the
|
||||
// components/parameters section of the Swagger spec.
|
||||
func GenerateTypesForParameters(t *template.Template, params map[string]*openapi3.ParameterRef) ([]TypeDefinition, error) {
|
||||
var types []TypeDefinition
|
||||
for _, paramName := range SortedParameterKeys(params) {
|
||||
paramOrRef := params[paramName]
|
||||
|
||||
goType, err := paramToGoType(paramOrRef.Value, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("error generating Go type for schema in parameter %s", paramName))
|
||||
}
|
||||
|
||||
typeDef := TypeDefinition{
|
||||
JsonName: paramName,
|
||||
Schema: goType,
|
||||
TypeName: SchemaNameToTypeName(paramName),
|
||||
}
|
||||
|
||||
if paramOrRef.Ref != "" {
|
||||
// Generate a reference type for referenced parameters
|
||||
refType, err := RefPathToGoType(paramOrRef.Ref)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("error generating Go type for (%s) in parameter %s", paramOrRef.Ref, paramName))
|
||||
}
|
||||
typeDef.TypeName = SchemaNameToTypeName(refType)
|
||||
}
|
||||
|
||||
types = append(types, typeDef)
|
||||
}
|
||||
return types, nil
|
||||
}
|
||||
|
||||
// Generates type definitions for any custom types defined in the
|
||||
// components/responses section of the Swagger spec.
|
||||
func GenerateTypesForResponses(t *template.Template, responses openapi3.Responses) ([]TypeDefinition, error) {
|
||||
var types []TypeDefinition
|
||||
|
||||
for _, responseName := range SortedResponsesKeys(responses) {
|
||||
responseOrRef := responses[responseName]
|
||||
|
||||
// We have to generate the response object. We're only going to
|
||||
// handle application/json media types here. Other responses should
|
||||
// simply be specified as strings or byte arrays.
|
||||
response := responseOrRef.Value
|
||||
jsonResponse, found := response.Content["application/json"]
|
||||
if found {
|
||||
goType, err := GenerateGoSchema(jsonResponse.Schema, []string{responseName})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("error generating Go type for schema in response %s", responseName))
|
||||
}
|
||||
|
||||
typeDef := TypeDefinition{
|
||||
JsonName: responseName,
|
||||
Schema: goType,
|
||||
TypeName: SchemaNameToTypeName(responseName),
|
||||
}
|
||||
|
||||
if responseOrRef.Ref != "" {
|
||||
// Generate a reference type for referenced parameters
|
||||
refType, err := RefPathToGoType(responseOrRef.Ref)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("error generating Go type for (%s) in parameter %s", responseOrRef.Ref, responseName))
|
||||
}
|
||||
typeDef.TypeName = SchemaNameToTypeName(refType)
|
||||
}
|
||||
types = append(types, typeDef)
|
||||
}
|
||||
}
|
||||
return types, nil
|
||||
}
|
||||
|
||||
// Generates type definitions for any custom types defined in the
|
||||
// components/requestBodies section of the Swagger spec.
|
||||
func GenerateTypesForRequestBodies(t *template.Template, bodies map[string]*openapi3.RequestBodyRef) ([]TypeDefinition, error) {
|
||||
var types []TypeDefinition
|
||||
|
||||
for _, bodyName := range SortedRequestBodyKeys(bodies) {
|
||||
bodyOrRef := bodies[bodyName]
|
||||
|
||||
// As for responses, we will only generate Go code for JSON bodies,
|
||||
// the other body formats are up to the user.
|
||||
response := bodyOrRef.Value
|
||||
jsonBody, found := response.Content["application/json"]
|
||||
if found {
|
||||
goType, err := GenerateGoSchema(jsonBody.Schema, []string{bodyName})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("error generating Go type for schema in body %s", bodyName))
|
||||
}
|
||||
|
||||
typeDef := TypeDefinition{
|
||||
JsonName: bodyName,
|
||||
Schema: goType,
|
||||
TypeName: SchemaNameToTypeName(bodyName),
|
||||
}
|
||||
|
||||
if bodyOrRef.Ref != "" {
|
||||
// Generate a reference type for referenced bodies
|
||||
refType, err := RefPathToGoType(bodyOrRef.Ref)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("error generating Go type for (%s) in body %s", bodyOrRef.Ref, bodyName))
|
||||
}
|
||||
typeDef.TypeName = SchemaNameToTypeName(refType)
|
||||
}
|
||||
types = append(types, typeDef)
|
||||
}
|
||||
}
|
||||
return types, nil
|
||||
}
|
||||
|
||||
// Helper function to pass a bunch of types to the template engine, and buffer
|
||||
// its output into a string.
|
||||
func GenerateTypes(t *template.Template, types []TypeDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
context := struct {
|
||||
Types []TypeDefinition
|
||||
}{
|
||||
Types: types,
|
||||
}
|
||||
|
||||
err := t.ExecuteTemplate(w, "typedef.tmpl", context)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating types")
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error flushing output buffer for types")
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// Generate our import statements and package definition.
|
||||
func GenerateImports(t *template.Template, imports []string, packageName string) (string, error) {
|
||||
sort.Strings(imports)
|
||||
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
context := struct {
|
||||
Imports []string
|
||||
PackageName string
|
||||
}{
|
||||
Imports: imports,
|
||||
PackageName: packageName,
|
||||
}
|
||||
err := t.ExecuteTemplate(w, "imports.tmpl", context)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating imports")
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error flushing output buffer for imports")
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// Generate all the glue code which provides the API for interacting with
|
||||
// additional properties and JSON-ification
|
||||
func GenerateAdditionalPropertyBoilerplate(t *template.Template, typeDefs []TypeDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
var filteredTypes []TypeDefinition
|
||||
for _, t := range typeDefs {
|
||||
if t.Schema.HasAdditionalProperties {
|
||||
filteredTypes = append(filteredTypes, t)
|
||||
}
|
||||
}
|
||||
|
||||
context := struct {
|
||||
Types []TypeDefinition
|
||||
}{
|
||||
Types: filteredTypes,
|
||||
}
|
||||
|
||||
err := t.ExecuteTemplate(w, "additional-properties.tmpl", context)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating additional properties code")
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error flushing output buffer for additional properties")
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// SanitizeCode runs sanitizers across the generated Go code to ensure the
|
||||
// generated code will be able to compile.
|
||||
func SanitizeCode(goCode string) string {
|
||||
// remove any byte-order-marks which break Go-Code
|
||||
// See: https://groups.google.com/forum/#!topic/golang-nuts/OToNIPdfkks
|
||||
return strings.Replace(goCode, "\uFEFF", "", -1)
|
||||
}
|
||||
25
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/extension.go
generated
vendored
Normal file
25
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/extension.go
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
extPropGoType = "x-go-type"
|
||||
)
|
||||
|
||||
func extTypeName(extPropValue interface{}) (string, error) {
|
||||
raw, ok := extPropValue.(json.RawMessage)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("failed to convert type: %T", extPropValue)
|
||||
}
|
||||
var name string
|
||||
if err := json.Unmarshal(raw, &name); err != nil {
|
||||
return "", errors.Wrap(err, "failed to unmarshal json")
|
||||
}
|
||||
|
||||
return name, nil
|
||||
}
|
||||
46
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/filter.go
generated
vendored
Normal file
46
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/filter.go
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package codegen
|
||||
|
||||
import "github.com/getkin/kin-openapi/openapi3"
|
||||
|
||||
func filterOperationsByTag(swagger *openapi3.Swagger, opts Options) {
|
||||
if len(opts.ExcludeTags) > 0 {
|
||||
excludeOperationsWithTags(swagger.Paths, opts.ExcludeTags)
|
||||
}
|
||||
if len(opts.IncludeTags) > 0 {
|
||||
includeOperationsWithTags(swagger.Paths, opts.IncludeTags, false)
|
||||
}
|
||||
}
|
||||
|
||||
func excludeOperationsWithTags(paths openapi3.Paths, tags []string) {
|
||||
includeOperationsWithTags(paths, tags, true)
|
||||
}
|
||||
|
||||
func includeOperationsWithTags(paths openapi3.Paths, tags []string, exclude bool) {
|
||||
for _, pathItem := range paths {
|
||||
ops := pathItem.Operations()
|
||||
names := make([]string, 0, len(ops))
|
||||
for name, op := range ops {
|
||||
if operationHasTag(op, tags) == exclude {
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
for _, name := range names {
|
||||
pathItem.SetOperation(name, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//operationHasTag returns true if the operation is tagged with any of tags
|
||||
func operationHasTag(op *openapi3.Operation, tags []string) bool {
|
||||
if op == nil {
|
||||
return false
|
||||
}
|
||||
for _, hasTag := range op.Tags {
|
||||
for _, wantTag := range tags {
|
||||
if hasTag == wantTag {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
77
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/inline.go
generated
vendored
Normal file
77
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/inline.go
generated
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"text/template"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
)
|
||||
|
||||
// This generates a gzipped, base64 encoded JSON representation of the
|
||||
// swagger definition, which we embed inside the generated code.
|
||||
func GenerateInlinedSpec(t *template.Template, swagger *openapi3.Swagger) (string, error) {
|
||||
// Marshal to json
|
||||
encoded, err := swagger.MarshalJSON()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error marshaling swagger: %s", err)
|
||||
}
|
||||
|
||||
// gzip
|
||||
var buf bytes.Buffer
|
||||
zw, err := gzip.NewWriterLevel(&buf, gzip.BestCompression)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error creating gzip compressor: %s", err)
|
||||
}
|
||||
_, err = zw.Write(encoded)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error gzipping swagger file: %s", err)
|
||||
}
|
||||
err = zw.Close()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error gzipping swagger file: %s", err)
|
||||
}
|
||||
str := base64.StdEncoding.EncodeToString(buf.Bytes())
|
||||
|
||||
var parts []string
|
||||
const width = 80
|
||||
|
||||
// Chop up the string into an array of strings.
|
||||
for len(str) > width {
|
||||
part := str[0:width]
|
||||
parts = append(parts, part)
|
||||
str = str[width:]
|
||||
}
|
||||
if len(str) > 0 {
|
||||
parts = append(parts, str)
|
||||
}
|
||||
|
||||
// Generate inline code.
|
||||
buf.Reset()
|
||||
w := bufio.NewWriter(&buf)
|
||||
err = t.ExecuteTemplate(w, "inline.tmpl", parts)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error generating inlined spec: %s", err)
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error flushing output buffer for inlined spec: %s", err)
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
790
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/operations.go
generated
vendored
Normal file
790
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/operations.go
generated
vendored
Normal file
|
|
@ -0,0 +1,790 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type ParameterDefinition struct {
|
||||
ParamName string // The original json parameter name, eg param_name
|
||||
In string // Where the parameter is defined - path, header, cookie, query
|
||||
Required bool // Is this a required parameter?
|
||||
Spec *openapi3.Parameter
|
||||
Schema Schema
|
||||
}
|
||||
|
||||
// This function is here as an adapter after a large refactoring so that I don't
|
||||
// have to update all the templates. It returns the type definition for a parameter,
|
||||
// without the leading '*' for optional ones.
|
||||
func (pd ParameterDefinition) TypeDef() string {
|
||||
typeDecl := pd.Schema.TypeDecl()
|
||||
return typeDecl
|
||||
}
|
||||
|
||||
// Generate the JSON annotation to map GoType to json type name. If Parameter
|
||||
// Foo is marshaled to json as "foo", this will create the annotation
|
||||
// 'json:"foo"'
|
||||
func (pd *ParameterDefinition) JsonTag() string {
|
||||
if pd.Required {
|
||||
return fmt.Sprintf("`json:\"%s\"`", pd.ParamName)
|
||||
} else {
|
||||
return fmt.Sprintf("`json:\"%s,omitempty\"`", pd.ParamName)
|
||||
}
|
||||
}
|
||||
|
||||
func (pd *ParameterDefinition) IsJson() bool {
|
||||
p := pd.Spec
|
||||
if len(p.Content) == 1 {
|
||||
_, found := p.Content["application/json"]
|
||||
return found
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (pd *ParameterDefinition) IsPassThrough() bool {
|
||||
p := pd.Spec
|
||||
if len(p.Content) > 1 {
|
||||
return true
|
||||
}
|
||||
if len(p.Content) == 1 {
|
||||
return !pd.IsJson()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (pd *ParameterDefinition) IsStyled() bool {
|
||||
p := pd.Spec
|
||||
return p.Schema != nil
|
||||
}
|
||||
|
||||
func (pd *ParameterDefinition) Style() string {
|
||||
style := pd.Spec.Style
|
||||
if style == "" {
|
||||
in := pd.Spec.In
|
||||
switch in {
|
||||
case "path", "header":
|
||||
return "simple"
|
||||
case "query", "cookie":
|
||||
return "form"
|
||||
default:
|
||||
panic("unknown parameter format")
|
||||
}
|
||||
}
|
||||
return style
|
||||
}
|
||||
|
||||
func (pd *ParameterDefinition) Explode() bool {
|
||||
if pd.Spec.Explode == nil {
|
||||
in := pd.Spec.In
|
||||
switch in {
|
||||
case "path", "header":
|
||||
return false
|
||||
case "query", "cookie":
|
||||
return true
|
||||
default:
|
||||
panic("unknown parameter format")
|
||||
}
|
||||
}
|
||||
return *pd.Spec.Explode
|
||||
}
|
||||
|
||||
func (pd ParameterDefinition) GoVariableName() string {
|
||||
name := LowercaseFirstCharacter(pd.GoName())
|
||||
if IsGoKeyword(name) {
|
||||
name = "p" + UppercaseFirstCharacter(name)
|
||||
}
|
||||
if unicode.IsNumber([]rune(name)[0]) {
|
||||
name = "n" + name
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func (pd ParameterDefinition) GoName() string {
|
||||
return ToCamelCase(pd.ParamName)
|
||||
}
|
||||
|
||||
func (pd ParameterDefinition) IndirectOptional() bool {
|
||||
return !pd.Required && !pd.Schema.SkipOptionalPointer
|
||||
}
|
||||
|
||||
type ParameterDefinitions []ParameterDefinition
|
||||
|
||||
func (p ParameterDefinitions) FindByName(name string) *ParameterDefinition {
|
||||
for _, param := range p {
|
||||
if param.ParamName == name {
|
||||
return ¶m
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// This function walks the given parameters dictionary, and generates the above
|
||||
// descriptors into a flat list. This makes it a lot easier to traverse the
|
||||
// data in the template engine.
|
||||
func DescribeParameters(params openapi3.Parameters, path []string) ([]ParameterDefinition, error) {
|
||||
outParams := make([]ParameterDefinition, 0)
|
||||
for _, paramOrRef := range params {
|
||||
param := paramOrRef.Value
|
||||
|
||||
goType, err := paramToGoType(param, append(path, param.Name))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error generating type for param (%s): %s",
|
||||
param.Name, err)
|
||||
}
|
||||
|
||||
pd := ParameterDefinition{
|
||||
ParamName: param.Name,
|
||||
In: param.In,
|
||||
Required: param.Required,
|
||||
Spec: param,
|
||||
Schema: goType,
|
||||
}
|
||||
|
||||
// If this is a reference to a predefined type, simply use the reference
|
||||
// name as the type. $ref: "#/components/schemas/custom_type" becomes
|
||||
// "CustomType".
|
||||
if paramOrRef.Ref != "" {
|
||||
goType, err := RefPathToGoType(paramOrRef.Ref)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error dereferencing (%s) for param (%s): %s",
|
||||
paramOrRef.Ref, param.Name, err)
|
||||
}
|
||||
pd.Schema.GoType = goType
|
||||
}
|
||||
outParams = append(outParams, pd)
|
||||
}
|
||||
return outParams, nil
|
||||
}
|
||||
|
||||
type SecurityDefinition struct {
|
||||
ProviderName string
|
||||
Scopes []string
|
||||
}
|
||||
|
||||
func DescribeSecurityDefinition(securityRequirements openapi3.SecurityRequirements) []SecurityDefinition {
|
||||
outDefs := make([]SecurityDefinition, 0)
|
||||
|
||||
for _, sr := range securityRequirements {
|
||||
for k, v := range sr {
|
||||
outDefs = append(outDefs, SecurityDefinition{ProviderName: k, Scopes: v})
|
||||
}
|
||||
}
|
||||
|
||||
return outDefs
|
||||
}
|
||||
|
||||
// This structure describes an Operation
|
||||
type OperationDefinition struct {
|
||||
OperationId string // The operation_id description from Swagger, used to generate function names
|
||||
|
||||
PathParams []ParameterDefinition // Parameters in the path, eg, /path/:param
|
||||
HeaderParams []ParameterDefinition // Parameters in HTTP headers
|
||||
QueryParams []ParameterDefinition // Parameters in the query, /path?param
|
||||
CookieParams []ParameterDefinition // Parameters in cookies
|
||||
TypeDefinitions []TypeDefinition // These are all the types we need to define for this operation
|
||||
SecurityDefinitions []SecurityDefinition // These are the security providers
|
||||
BodyRequired bool
|
||||
Bodies []RequestBodyDefinition // The list of bodies for which to generate handlers.
|
||||
Summary string // Summary string from Swagger, used to generate a comment
|
||||
Method string // GET, POST, DELETE, etc.
|
||||
Path string // The Swagger path for the operation, like /resource/{id}
|
||||
Spec *openapi3.Operation
|
||||
}
|
||||
|
||||
// Returns the list of all parameters except Path parameters. Path parameters
|
||||
// are handled differently from the rest, since they're mandatory.
|
||||
func (o *OperationDefinition) Params() []ParameterDefinition {
|
||||
result := append(o.QueryParams, o.HeaderParams...)
|
||||
result = append(result, o.CookieParams...)
|
||||
return result
|
||||
}
|
||||
|
||||
// Returns all parameters
|
||||
func (o *OperationDefinition) AllParams() []ParameterDefinition {
|
||||
result := append(o.QueryParams, o.HeaderParams...)
|
||||
result = append(result, o.CookieParams...)
|
||||
result = append(result, o.PathParams...)
|
||||
return result
|
||||
}
|
||||
|
||||
// If we have parameters other than path parameters, they're bundled into an
|
||||
// object. Returns true if we have any of those. This is used from the template
|
||||
// engine.
|
||||
func (o *OperationDefinition) RequiresParamObject() bool {
|
||||
return len(o.Params()) > 0
|
||||
}
|
||||
|
||||
// This is called by the template engine to determine whether to generate body
|
||||
// marshaling code on the client. This is true for all body types, whether or
|
||||
// not we generate types for them.
|
||||
func (o *OperationDefinition) HasBody() bool {
|
||||
return o.Spec.RequestBody != nil
|
||||
}
|
||||
|
||||
// This returns the Operations summary as a multi line comment
|
||||
func (o *OperationDefinition) SummaryAsComment() string {
|
||||
if o.Summary == "" {
|
||||
return ""
|
||||
}
|
||||
trimmed := strings.TrimSuffix(o.Summary, "\n")
|
||||
parts := strings.Split(trimmed, "\n")
|
||||
for i, p := range parts {
|
||||
parts[i] = "// " + p
|
||||
}
|
||||
return strings.Join(parts, "\n")
|
||||
}
|
||||
|
||||
// Produces a list of type definitions for a given Operation for the response
|
||||
// types which we know how to parse. These will be turned into fields on a
|
||||
// response object for automatic deserialization of responses in the generated
|
||||
// Client code. See "client-with-responses.tmpl".
|
||||
func (o *OperationDefinition) GetResponseTypeDefinitions() ([]TypeDefinition, error) {
|
||||
var tds []TypeDefinition
|
||||
|
||||
responses := o.Spec.Responses
|
||||
sortedResponsesKeys := SortedResponsesKeys(responses)
|
||||
for _, responseName := range sortedResponsesKeys {
|
||||
responseRef := responses[responseName]
|
||||
|
||||
// We can only generate a type if we have a value:
|
||||
if responseRef.Value != nil {
|
||||
sortedContentKeys := SortedContentKeys(responseRef.Value.Content)
|
||||
for _, contentTypeName := range sortedContentKeys {
|
||||
contentType := responseRef.Value.Content[contentTypeName]
|
||||
// We can only generate a type if we have a schema:
|
||||
if contentType.Schema != nil {
|
||||
responseSchema, err := GenerateGoSchema(contentType.Schema, []string{responseName})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("Unable to determine Go type for %s.%s", o.OperationId, contentTypeName))
|
||||
}
|
||||
|
||||
var typeName string
|
||||
switch {
|
||||
case StringInArray(contentTypeName, contentTypesJSON):
|
||||
typeName = fmt.Sprintf("JSON%s", ToCamelCase(responseName))
|
||||
// YAML:
|
||||
case StringInArray(contentTypeName, contentTypesYAML):
|
||||
typeName = fmt.Sprintf("YAML%s", ToCamelCase(responseName))
|
||||
// XML:
|
||||
case StringInArray(contentTypeName, contentTypesXML):
|
||||
typeName = fmt.Sprintf("XML%s", ToCamelCase(responseName))
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
td := TypeDefinition{
|
||||
TypeName: typeName,
|
||||
Schema: responseSchema,
|
||||
ResponseName: responseName,
|
||||
}
|
||||
if contentType.Schema.Ref != "" {
|
||||
refType, err := RefPathToGoType(contentType.Schema.Ref)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error dereferencing response Ref")
|
||||
}
|
||||
td.Schema.RefType = refType
|
||||
}
|
||||
tds = append(tds, td)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return tds, nil
|
||||
}
|
||||
|
||||
// This describes a request body
|
||||
type RequestBodyDefinition struct {
|
||||
// Is this body required, or optional?
|
||||
Required bool
|
||||
|
||||
// This is the schema describing this body
|
||||
Schema Schema
|
||||
|
||||
// When we generate type names, we need a Tag for it, such as JSON, in
|
||||
// which case we will produce "JSONBody".
|
||||
NameTag string
|
||||
|
||||
// This is the content type corresponding to the body, eg, application/json
|
||||
ContentType string
|
||||
|
||||
// Whether this is the default body type. For an operation named OpFoo, we
|
||||
// will not add suffixes like OpFooJSONBody for this one.
|
||||
Default bool
|
||||
}
|
||||
|
||||
// Returns the Go type definition for a request body
|
||||
func (r RequestBodyDefinition) TypeDef() string {
|
||||
return r.Schema.TypeDecl()
|
||||
}
|
||||
|
||||
// Returns whether the body is a custom inline type, or pre-defined. This is
|
||||
// poorly named, but it's here for compatibility reasons post-refactoring
|
||||
// TODO: clean up the templates code, it can be simpler.
|
||||
func (r RequestBodyDefinition) CustomType() bool {
|
||||
return r.Schema.RefType == ""
|
||||
}
|
||||
|
||||
// When we're generating multiple functions which relate to request bodies,
|
||||
// this generates the suffix. Such as Operation DoFoo would be suffixed with
|
||||
// DoFooWithXMLBody.
|
||||
func (r RequestBodyDefinition) Suffix() string {
|
||||
// The default response is never suffixed.
|
||||
if r.Default {
|
||||
return ""
|
||||
}
|
||||
return "With" + r.NameTag + "Body"
|
||||
}
|
||||
|
||||
// This function returns the subset of the specified parameters which are of the
|
||||
// specified type.
|
||||
func FilterParameterDefinitionByType(params []ParameterDefinition, in string) []ParameterDefinition {
|
||||
var out []ParameterDefinition
|
||||
for _, p := range params {
|
||||
if p.In == in {
|
||||
out = append(out, p)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// OperationDefinitions returns all operations for a swagger definition.
|
||||
func OperationDefinitions(swagger *openapi3.Swagger) ([]OperationDefinition, error) {
|
||||
var operations []OperationDefinition
|
||||
|
||||
for _, requestPath := range SortedPathsKeys(swagger.Paths) {
|
||||
pathItem := swagger.Paths[requestPath]
|
||||
// These are parameters defined for all methods on a given path. They
|
||||
// are shared by all methods.
|
||||
globalParams, err := DescribeParameters(pathItem.Parameters, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error describing global parameters for %s: %s",
|
||||
requestPath, err)
|
||||
}
|
||||
|
||||
// Each path can have a number of operations, POST, GET, OPTIONS, etc.
|
||||
pathOps := pathItem.Operations()
|
||||
for _, opName := range SortedOperationsKeys(pathOps) {
|
||||
op := pathOps[opName]
|
||||
// We rely on OperationID to generate function names, it's required
|
||||
if op.OperationID == "" {
|
||||
op.OperationID, err = generateDefaultOperationID(opName, requestPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error generating default OperationID for %s/%s: %s",
|
||||
opName, requestPath, err)
|
||||
}
|
||||
op.OperationID = op.OperationID
|
||||
} else {
|
||||
op.OperationID = ToCamelCase(op.OperationID)
|
||||
}
|
||||
|
||||
// These are parameters defined for the specific path method that
|
||||
// we're iterating over.
|
||||
localParams, err := DescribeParameters(op.Parameters, []string{op.OperationID + "Params"})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error describing global parameters for %s/%s: %s",
|
||||
opName, requestPath, err)
|
||||
}
|
||||
// All the parameters required by a handler are the union of the
|
||||
// global parameters and the local parameters.
|
||||
allParams := append(globalParams, localParams...)
|
||||
|
||||
// Order the path parameters to match the order as specified in
|
||||
// the path, not in the swagger spec, and validate that the parameter
|
||||
// names match, as downstream code depends on that.
|
||||
pathParams := FilterParameterDefinitionByType(allParams, "path")
|
||||
pathParams, err = SortParamsByPath(requestPath, pathParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bodyDefinitions, typeDefinitions, err := GenerateBodyDefinitions(op.OperationID, op.RequestBody)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error generating body definitions")
|
||||
}
|
||||
|
||||
opDef := OperationDefinition{
|
||||
PathParams: pathParams,
|
||||
HeaderParams: FilterParameterDefinitionByType(allParams, "header"),
|
||||
QueryParams: FilterParameterDefinitionByType(allParams, "query"),
|
||||
CookieParams: FilterParameterDefinitionByType(allParams, "cookie"),
|
||||
OperationId: ToCamelCase(op.OperationID),
|
||||
// Replace newlines in summary.
|
||||
Summary: op.Summary,
|
||||
Method: opName,
|
||||
Path: requestPath,
|
||||
Spec: op,
|
||||
Bodies: bodyDefinitions,
|
||||
TypeDefinitions: typeDefinitions,
|
||||
}
|
||||
|
||||
// check for overrides of SecurityDefinitions.
|
||||
// See: "Step 2. Applying security:" from the spec:
|
||||
// https://swagger.io/docs/specification/authentication/
|
||||
if op.Security != nil {
|
||||
opDef.SecurityDefinitions = DescribeSecurityDefinition(*op.Security)
|
||||
} else {
|
||||
// use global securityDefinitions
|
||||
// globalSecurityDefinitions contains the top-level securityDefinitions.
|
||||
// They are the default securityPermissions which are injected into each
|
||||
// path, except for the case where a path explicitly overrides them.
|
||||
opDef.SecurityDefinitions = DescribeSecurityDefinition(swagger.Security)
|
||||
|
||||
}
|
||||
|
||||
if op.RequestBody != nil {
|
||||
opDef.BodyRequired = op.RequestBody.Value.Required
|
||||
}
|
||||
|
||||
// Generate all the type definitions needed for this operation
|
||||
opDef.TypeDefinitions = append(opDef.TypeDefinitions, GenerateTypeDefsForOperation(opDef)...)
|
||||
|
||||
operations = append(operations, opDef)
|
||||
}
|
||||
}
|
||||
return operations, nil
|
||||
}
|
||||
|
||||
func generateDefaultOperationID(opName string, requestPath string) (string, error) {
|
||||
var operationId string = strings.ToLower(opName)
|
||||
|
||||
if opName == "" {
|
||||
return "", fmt.Errorf("operation name cannot be an empty string")
|
||||
}
|
||||
|
||||
if requestPath == "" {
|
||||
return "", fmt.Errorf("request path cannot be an empty string")
|
||||
}
|
||||
|
||||
for _, part := range strings.Split(requestPath, "/") {
|
||||
if part != "" {
|
||||
operationId = operationId + "-" + part
|
||||
}
|
||||
}
|
||||
|
||||
return ToCamelCase(operationId), nil
|
||||
}
|
||||
|
||||
// This function turns the Swagger body definitions into a list of our body
|
||||
// definitions which will be used for code generation.
|
||||
func GenerateBodyDefinitions(operationID string, bodyOrRef *openapi3.RequestBodyRef) ([]RequestBodyDefinition, []TypeDefinition, error) {
|
||||
if bodyOrRef == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
body := bodyOrRef.Value
|
||||
|
||||
var bodyDefinitions []RequestBodyDefinition
|
||||
var typeDefinitions []TypeDefinition
|
||||
|
||||
for contentType, content := range body.Content {
|
||||
var tag string
|
||||
var defaultBody bool
|
||||
|
||||
switch contentType {
|
||||
case "application/json":
|
||||
tag = "JSON"
|
||||
defaultBody = true
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
bodyTypeName := operationID + tag + "Body"
|
||||
bodySchema, err := GenerateGoSchema(content.Schema, []string{bodyTypeName})
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "error generating request body definition")
|
||||
}
|
||||
|
||||
// If the body is a pre-defined type
|
||||
if bodyOrRef.Ref != "" {
|
||||
// Convert the reference path to Go type
|
||||
refType, err := RefPathToGoType(bodyOrRef.Ref)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, fmt.Sprintf("error turning reference (%s) into a Go type", bodyOrRef.Ref))
|
||||
}
|
||||
bodySchema.RefType = refType
|
||||
}
|
||||
|
||||
// If the request has a body, but it's not a user defined
|
||||
// type under #/components, we'll define a type for it, so
|
||||
// that we have an easy to use type for marshaling.
|
||||
if bodySchema.RefType == "" {
|
||||
td := TypeDefinition{
|
||||
TypeName: bodyTypeName,
|
||||
Schema: bodySchema,
|
||||
}
|
||||
typeDefinitions = append(typeDefinitions, td)
|
||||
// The body schema now is a reference to a type
|
||||
bodySchema.RefType = bodyTypeName
|
||||
}
|
||||
|
||||
bd := RequestBodyDefinition{
|
||||
Required: body.Required,
|
||||
Schema: bodySchema,
|
||||
NameTag: tag,
|
||||
ContentType: contentType,
|
||||
Default: defaultBody,
|
||||
}
|
||||
bodyDefinitions = append(bodyDefinitions, bd)
|
||||
}
|
||||
return bodyDefinitions, typeDefinitions, nil
|
||||
}
|
||||
|
||||
func GenerateTypeDefsForOperation(op OperationDefinition) []TypeDefinition {
|
||||
var typeDefs []TypeDefinition
|
||||
// Start with the params object itself
|
||||
if len(op.Params()) != 0 {
|
||||
typeDefs = append(typeDefs, GenerateParamsTypes(op)...)
|
||||
}
|
||||
|
||||
// Now, go through all the additional types we need to declare.
|
||||
for _, param := range op.AllParams() {
|
||||
typeDefs = append(typeDefs, param.Schema.GetAdditionalTypeDefs()...)
|
||||
}
|
||||
|
||||
for _, body := range op.Bodies {
|
||||
typeDefs = append(typeDefs, body.Schema.GetAdditionalTypeDefs()...)
|
||||
}
|
||||
return typeDefs
|
||||
}
|
||||
|
||||
// This defines the schema for a parameters definition object which encapsulates
|
||||
// all the query, header and cookie parameters for an operation.
|
||||
func GenerateParamsTypes(op OperationDefinition) []TypeDefinition {
|
||||
var typeDefs []TypeDefinition
|
||||
|
||||
objectParams := op.QueryParams
|
||||
objectParams = append(objectParams, op.HeaderParams...)
|
||||
objectParams = append(objectParams, op.CookieParams...)
|
||||
|
||||
typeName := op.OperationId + "Params"
|
||||
|
||||
s := Schema{}
|
||||
for _, param := range objectParams {
|
||||
pSchema := param.Schema
|
||||
if pSchema.HasAdditionalProperties {
|
||||
propRefName := strings.Join([]string{typeName, param.GoName()}, "_")
|
||||
pSchema.RefType = propRefName
|
||||
typeDefs = append(typeDefs, TypeDefinition{
|
||||
TypeName: propRefName,
|
||||
Schema: param.Schema,
|
||||
})
|
||||
}
|
||||
prop := Property{
|
||||
Description: param.Spec.Description,
|
||||
JsonFieldName: param.ParamName,
|
||||
Required: param.Required,
|
||||
Schema: pSchema,
|
||||
}
|
||||
s.Properties = append(s.Properties, prop)
|
||||
}
|
||||
|
||||
s.GoType = GenStructFromSchema(s)
|
||||
|
||||
td := TypeDefinition{
|
||||
TypeName: typeName,
|
||||
Schema: s,
|
||||
}
|
||||
return append(typeDefs, td)
|
||||
}
|
||||
|
||||
// Generates code for all types produced
|
||||
func GenerateTypesForOperations(t *template.Template, ops []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "param-types.tmpl", ops)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating types for params objects")
|
||||
}
|
||||
|
||||
err = t.ExecuteTemplate(w, "request-bodies.tmpl", ops)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating request bodies for operations")
|
||||
}
|
||||
|
||||
// Generate boiler plate for all additional types.
|
||||
var td []TypeDefinition
|
||||
for _, op := range ops {
|
||||
td = append(td, op.TypeDefinitions...)
|
||||
}
|
||||
|
||||
addProps, err := GenerateAdditionalPropertyBoilerplate(t, td)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating additional properties boilerplate for operations")
|
||||
}
|
||||
|
||||
_, err = w.WriteString("\n")
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating additional properties boilerplate for operations")
|
||||
}
|
||||
|
||||
_, err = w.WriteString(addProps)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating additional properties boilerplate for operations")
|
||||
}
|
||||
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error flushing output buffer for server interface")
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// GenerateChiServer This function generates all the go code for the ServerInterface as well as
|
||||
// all the wrapper functions around our handlers.
|
||||
func GenerateChiServer(t *template.Template, operations []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "chi-interface.tmpl", operations)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating server interface")
|
||||
}
|
||||
|
||||
err = t.ExecuteTemplate(w, "chi-middleware.tmpl", operations)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating server middleware")
|
||||
}
|
||||
|
||||
err = t.ExecuteTemplate(w, "chi-handler.tmpl", operations)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating server http handler")
|
||||
}
|
||||
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error flushing output buffer for server")
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// GenerateEchoServer This function generates all the go code for the ServerInterface as well as
|
||||
// all the wrapper functions around our handlers.
|
||||
func GenerateEchoServer(t *template.Template, operations []OperationDefinition) (string, error) {
|
||||
si, err := GenerateServerInterface(t, operations)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error generating server types and interface: %s", err)
|
||||
}
|
||||
|
||||
wrappers, err := GenerateWrappers(t, operations)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error generating handler wrappers: %s", err)
|
||||
}
|
||||
|
||||
register, err := GenerateRegistration(t, operations)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error generating handler registration: %s", err)
|
||||
}
|
||||
return strings.Join([]string{si, wrappers, register}, "\n"), nil
|
||||
}
|
||||
|
||||
// Uses the template engine to generate the server interface
|
||||
func GenerateServerInterface(t *template.Template, ops []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "server-interface.tmpl", ops)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error generating server interface: %s", err)
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error flushing output buffer for server interface: %s", err)
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// Uses the template engine to generate all the wrappers which wrap our simple
|
||||
// interface functions and perform marshallin/unmarshalling from HTTP
|
||||
// request objects.
|
||||
func GenerateWrappers(t *template.Template, ops []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "wrappers.tmpl", ops)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error generating server interface: %s", err)
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error flushing output buffer for server interface: %s", err)
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// Uses the template engine to generate the function which registers our wrappers
|
||||
// as Echo path handlers.
|
||||
func GenerateRegistration(t *template.Template, ops []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "register.tmpl", ops)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error generating route registration: %s", err)
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error flushing output buffer for route registration: %s", err)
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// Uses the template engine to generate the function which registers our wrappers
|
||||
// as Echo path handlers.
|
||||
func GenerateClient(t *template.Template, ops []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "client.tmpl", ops)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error generating client bindings: %s", err)
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error flushing output buffer for client: %s", err)
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// This generates a client which extends the basic client which does response
|
||||
// unmarshaling.
|
||||
func GenerateClientWithResponses(t *template.Template, ops []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "client-with-responses.tmpl", ops)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error generating client bindings: %s", err)
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error flushing output buffer for client: %s", err)
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
483
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/prune.go
generated
vendored
Normal file
483
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/prune.go
generated
vendored
Normal file
|
|
@ -0,0 +1,483 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
)
|
||||
|
||||
func stringInSlice(a string, list []string) bool {
|
||||
for _, b := range list {
|
||||
if b == a {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type RefWrapper struct {
|
||||
Ref string
|
||||
HasValue bool
|
||||
SourceRef interface{}
|
||||
}
|
||||
|
||||
func walkSwagger(swagger *openapi3.Swagger, doFn func(RefWrapper) (bool, error)) error {
|
||||
if swagger == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, p := range swagger.Paths {
|
||||
for _, param := range p.Parameters {
|
||||
walkParameterRef(param, doFn)
|
||||
}
|
||||
for _, op := range p.Operations() {
|
||||
walkOperation(op, doFn)
|
||||
}
|
||||
}
|
||||
|
||||
walkComponents(&swagger.Components, doFn)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkOperation(op *openapi3.Operation, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if op == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, param := range op.Parameters {
|
||||
_ = walkParameterRef(param, doFn)
|
||||
}
|
||||
|
||||
_ = walkRequestBodyRef(op.RequestBody, doFn)
|
||||
|
||||
for _, response := range op.Responses {
|
||||
walkResponseRef(response, doFn)
|
||||
}
|
||||
|
||||
for _, callback := range op.Callbacks {
|
||||
walkCallbackRef(callback, doFn)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkComponents(components *openapi3.Components, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if components == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, schema := range components.Schemas {
|
||||
_ = walkSchemaRef(schema, doFn)
|
||||
}
|
||||
|
||||
for _, param := range components.Parameters {
|
||||
_ = walkParameterRef(param, doFn)
|
||||
}
|
||||
|
||||
for _, header := range components.Headers {
|
||||
_ = walkHeaderRef(header, doFn)
|
||||
}
|
||||
|
||||
for _, requestBody := range components.RequestBodies {
|
||||
_ = walkRequestBodyRef(requestBody, doFn)
|
||||
}
|
||||
|
||||
for _, response := range components.Responses {
|
||||
_ = walkResponseRef(response, doFn)
|
||||
}
|
||||
|
||||
for _, securityScheme := range components.SecuritySchemes {
|
||||
_ = walkSecuritySchemeRef(securityScheme, doFn)
|
||||
}
|
||||
|
||||
for _, example := range components.Examples {
|
||||
_ = walkExampleRef(example, doFn)
|
||||
}
|
||||
|
||||
for _, link := range components.Links {
|
||||
_ = walkLinkRef(link, doFn)
|
||||
}
|
||||
|
||||
for _, callback := range components.Callbacks {
|
||||
_ = walkCallbackRef(callback, doFn)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkSchemaRef(ref *openapi3.SchemaRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, ref := range ref.Value.OneOf {
|
||||
walkSchemaRef(ref, doFn)
|
||||
}
|
||||
|
||||
for _, ref := range ref.Value.AnyOf {
|
||||
walkSchemaRef(ref, doFn)
|
||||
}
|
||||
|
||||
for _, ref := range ref.Value.AllOf {
|
||||
walkSchemaRef(ref, doFn)
|
||||
}
|
||||
|
||||
walkSchemaRef(ref.Value.Not, doFn)
|
||||
walkSchemaRef(ref.Value.Items, doFn)
|
||||
|
||||
for _, ref := range ref.Value.Properties {
|
||||
walkSchemaRef(ref, doFn)
|
||||
}
|
||||
|
||||
walkSchemaRef(ref.Value.AdditionalProperties, doFn)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkParameterRef(ref *openapi3.ParameterRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
walkSchemaRef(ref.Value.Schema, doFn)
|
||||
|
||||
for _, example := range ref.Value.Examples {
|
||||
walkExampleRef(example, doFn)
|
||||
}
|
||||
|
||||
for _, mediaType := range ref.Value.Content {
|
||||
if mediaType == nil {
|
||||
continue
|
||||
}
|
||||
walkSchemaRef(mediaType.Schema, doFn)
|
||||
|
||||
for _, example := range mediaType.Examples {
|
||||
walkExampleRef(example, doFn)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkRequestBodyRef(ref *openapi3.RequestBodyRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, mediaType := range ref.Value.Content {
|
||||
if mediaType == nil {
|
||||
continue
|
||||
}
|
||||
walkSchemaRef(mediaType.Schema, doFn)
|
||||
|
||||
for _, example := range mediaType.Examples {
|
||||
walkExampleRef(example, doFn)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkResponseRef(ref *openapi3.ResponseRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, header := range ref.Value.Headers {
|
||||
walkHeaderRef(header, doFn)
|
||||
}
|
||||
|
||||
for _, mediaType := range ref.Value.Content {
|
||||
if mediaType == nil {
|
||||
continue
|
||||
}
|
||||
walkSchemaRef(mediaType.Schema, doFn)
|
||||
|
||||
for _, example := range mediaType.Examples {
|
||||
walkExampleRef(example, doFn)
|
||||
}
|
||||
}
|
||||
|
||||
for _, link := range ref.Value.Links {
|
||||
walkLinkRef(link, doFn)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkCallbackRef(ref *openapi3.CallbackRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, pathItem := range *ref.Value {
|
||||
for _, parameter := range pathItem.Parameters {
|
||||
walkParameterRef(parameter, doFn)
|
||||
}
|
||||
walkOperation(pathItem.Connect, doFn)
|
||||
walkOperation(pathItem.Delete, doFn)
|
||||
walkOperation(pathItem.Get, doFn)
|
||||
walkOperation(pathItem.Head, doFn)
|
||||
walkOperation(pathItem.Options, doFn)
|
||||
walkOperation(pathItem.Patch, doFn)
|
||||
walkOperation(pathItem.Post, doFn)
|
||||
walkOperation(pathItem.Put, doFn)
|
||||
walkOperation(pathItem.Trace, doFn)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkHeaderRef(ref *openapi3.HeaderRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
walkSchemaRef(ref.Value.Schema, doFn)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkSecuritySchemeRef(ref *openapi3.SecuritySchemeRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NOTE: `SecuritySchemeRef`s don't contain any children that can contain refs
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkLinkRef(ref *openapi3.LinkRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func walkExampleRef(ref *openapi3.ExampleRef, doFn func(RefWrapper) (bool, error)) error {
|
||||
// Not a valid ref, ignore it and continue
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
refWrapper := RefWrapper{Ref: ref.Ref, HasValue: ref.Value != nil, SourceRef: ref}
|
||||
shouldContinue, err := doFn(refWrapper)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !shouldContinue {
|
||||
return nil
|
||||
}
|
||||
if ref.Value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NOTE: `ExampleRef`s don't contain any children that can contain refs
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func findComponentRefs(swagger *openapi3.Swagger) []string {
|
||||
refs := []string{}
|
||||
|
||||
walkSwagger(swagger, func(ref RefWrapper) (bool, error) {
|
||||
if ref.Ref != "" {
|
||||
refs = append(refs, ref.Ref)
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
return refs
|
||||
}
|
||||
|
||||
func removeOrphanedComponents(swagger *openapi3.Swagger, refs []string) int {
|
||||
countRemoved := 0
|
||||
|
||||
for key, _ := range swagger.Components.Schemas {
|
||||
ref := fmt.Sprintf("#/components/schemas/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Schemas, key)
|
||||
}
|
||||
}
|
||||
|
||||
for key, _ := range swagger.Components.Parameters {
|
||||
ref := fmt.Sprintf("#/components/parameters/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Parameters, key)
|
||||
}
|
||||
}
|
||||
|
||||
// securitySchemes are an exception. definitions in securitySchemes
|
||||
// are referenced directly by name. and not by $ref
|
||||
|
||||
// for key, _ := range swagger.Components.SecuritySchemes {
|
||||
// ref := fmt.Sprintf("#/components/securitySchemes/%s", key)
|
||||
// if !stringInSlice(ref, refs) {
|
||||
// countRemoved++
|
||||
// delete(swagger.Components.SecuritySchemes, key)
|
||||
// }
|
||||
// }
|
||||
|
||||
for key, _ := range swagger.Components.RequestBodies {
|
||||
ref := fmt.Sprintf("#/components/requestBodies/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.RequestBodies, key)
|
||||
}
|
||||
}
|
||||
|
||||
for key, _ := range swagger.Components.Responses {
|
||||
ref := fmt.Sprintf("#/components/responses/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Responses, key)
|
||||
}
|
||||
}
|
||||
|
||||
for key, _ := range swagger.Components.Headers {
|
||||
ref := fmt.Sprintf("#/components/headers/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Headers, key)
|
||||
}
|
||||
}
|
||||
|
||||
for key, _ := range swagger.Components.Examples {
|
||||
ref := fmt.Sprintf("#/components/examples/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Examples, key)
|
||||
}
|
||||
}
|
||||
|
||||
for key, _ := range swagger.Components.Links {
|
||||
ref := fmt.Sprintf("#/components/links/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Links, key)
|
||||
}
|
||||
}
|
||||
|
||||
for key, _ := range swagger.Components.Callbacks {
|
||||
ref := fmt.Sprintf("#/components/callbacks/%s", key)
|
||||
if !stringInSlice(ref, refs) {
|
||||
countRemoved++
|
||||
delete(swagger.Components.Callbacks, key)
|
||||
}
|
||||
}
|
||||
|
||||
return countRemoved
|
||||
}
|
||||
|
||||
func pruneUnusedComponents(swagger *openapi3.Swagger) {
|
||||
for {
|
||||
refs := findComponentRefs(swagger)
|
||||
countRemoved := removeOrphanedComponents(swagger, refs)
|
||||
if countRemoved < 1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
489
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/schema.go
generated
vendored
Normal file
489
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/schema.go
generated
vendored
Normal file
|
|
@ -0,0 +1,489 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// This describes a Schema, a type definition.
|
||||
type Schema struct {
|
||||
GoType string // The Go type needed to represent the schema
|
||||
RefType string // If the type has a type name, this is set
|
||||
|
||||
EnumValues map[string]string // Enum values
|
||||
|
||||
Properties []Property // For an object, the fields with names
|
||||
HasAdditionalProperties bool // Whether we support additional properties
|
||||
AdditionalPropertiesType *Schema // And if we do, their type
|
||||
AdditionalTypes []TypeDefinition // We may need to generate auxiliary helper types, stored here
|
||||
|
||||
SkipOptionalPointer bool // Some types don't need a * in front when they're optional
|
||||
}
|
||||
|
||||
func (s Schema) IsRef() bool {
|
||||
return s.RefType != ""
|
||||
}
|
||||
|
||||
func (s Schema) TypeDecl() string {
|
||||
if s.IsRef() {
|
||||
return s.RefType
|
||||
}
|
||||
return s.GoType
|
||||
}
|
||||
|
||||
func (s *Schema) MergeProperty(p Property) error {
|
||||
// Scan all existing properties for a conflict
|
||||
for _, e := range s.Properties {
|
||||
if e.JsonFieldName == p.JsonFieldName && !PropertiesEqual(e, p) {
|
||||
return errors.New(fmt.Sprintf("property '%s' already exists with a different type", e.JsonFieldName))
|
||||
}
|
||||
}
|
||||
s.Properties = append(s.Properties, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s Schema) GetAdditionalTypeDefs() []TypeDefinition {
|
||||
var result []TypeDefinition
|
||||
for _, p := range s.Properties {
|
||||
result = append(result, p.Schema.GetAdditionalTypeDefs()...)
|
||||
}
|
||||
result = append(result, s.AdditionalTypes...)
|
||||
return result
|
||||
}
|
||||
|
||||
type Property struct {
|
||||
Description string
|
||||
JsonFieldName string
|
||||
Schema Schema
|
||||
Required bool
|
||||
Nullable bool
|
||||
}
|
||||
|
||||
func (p Property) GoFieldName() string {
|
||||
return SchemaNameToTypeName(p.JsonFieldName)
|
||||
}
|
||||
|
||||
func (p Property) GoTypeDef() string {
|
||||
typeDef := p.Schema.TypeDecl()
|
||||
if !p.Schema.SkipOptionalPointer && (!p.Required || p.Nullable) {
|
||||
typeDef = "*" + typeDef
|
||||
}
|
||||
return typeDef
|
||||
}
|
||||
|
||||
type TypeDefinition struct {
|
||||
TypeName string
|
||||
JsonName string
|
||||
ResponseName string
|
||||
Schema Schema
|
||||
}
|
||||
|
||||
func PropertiesEqual(a, b Property) bool {
|
||||
return a.JsonFieldName == b.JsonFieldName && a.Schema.TypeDecl() == b.Schema.TypeDecl() && a.Required == b.Required
|
||||
}
|
||||
|
||||
func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) {
|
||||
// If Ref is set on the SchemaRef, it means that this type is actually a reference to
|
||||
// another type. We're not de-referencing, so simply use the referenced type.
|
||||
var refType string
|
||||
|
||||
// Add a fallback value in case the sref is nil.
|
||||
// i.e. the parent schema defines a type:array, but the array has
|
||||
// no items defined. Therefore we have at least valid Go-Code.
|
||||
if sref == nil {
|
||||
return Schema{GoType: "interface{}", RefType: refType}, nil
|
||||
}
|
||||
|
||||
schema := sref.Value
|
||||
|
||||
if sref.Ref != "" {
|
||||
var err error
|
||||
// Convert the reference path to Go type
|
||||
refType, err = RefPathToGoType(sref.Ref)
|
||||
if err != nil {
|
||||
return Schema{}, fmt.Errorf("error turning reference (%s) into a Go type: %s",
|
||||
sref.Ref, err)
|
||||
}
|
||||
return Schema{
|
||||
GoType: refType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// We can't support this in any meaningful way
|
||||
if schema.AnyOf != nil {
|
||||
return Schema{GoType: "interface{}", RefType: refType}, nil
|
||||
}
|
||||
// We can't support this in any meaningful way
|
||||
if schema.OneOf != nil {
|
||||
return Schema{GoType: "interface{}", RefType: refType}, nil
|
||||
}
|
||||
|
||||
// AllOf is interesting, and useful. It's the union of a number of other
|
||||
// schemas. A common usage is to create a union of an object with an ID,
|
||||
// so that in a RESTful paradigm, the Create operation can return
|
||||
// (object, id), so that other operations can refer to (id)
|
||||
if schema.AllOf != nil {
|
||||
mergedSchema, err := MergeSchemas(schema.AllOf, path)
|
||||
if err != nil {
|
||||
return Schema{}, errors.Wrap(err, "error merging schemas")
|
||||
}
|
||||
mergedSchema.RefType = refType
|
||||
return mergedSchema, nil
|
||||
}
|
||||
|
||||
outSchema := Schema{
|
||||
RefType: refType,
|
||||
}
|
||||
|
||||
// Check for custom Go type extension
|
||||
if extension, ok := schema.Extensions[extPropGoType]; ok {
|
||||
typeName, err := extTypeName(extension)
|
||||
if err != nil {
|
||||
return outSchema, errors.Wrapf(err, "invalid value for %q", extPropGoType)
|
||||
}
|
||||
outSchema.GoType = typeName
|
||||
return outSchema, nil
|
||||
}
|
||||
|
||||
// Schema type and format, eg. string / binary
|
||||
t := schema.Type
|
||||
// Handle objects and empty schemas first as a special case
|
||||
if t == "" || t == "object" {
|
||||
var outType string
|
||||
|
||||
if len(schema.Properties) == 0 && !SchemaHasAdditionalProperties(schema) {
|
||||
// If the object has no properties or additional properties, we
|
||||
// have some special cases for its type.
|
||||
if t == "object" {
|
||||
// We have an object with no properties. This is a generic object
|
||||
// expressed as a map.
|
||||
outType = "map[string]interface{}"
|
||||
} else { // t == ""
|
||||
// If we don't even have the object designator, we're a completely
|
||||
// generic type.
|
||||
outType = "interface{}"
|
||||
}
|
||||
outSchema.GoType = outType
|
||||
} else {
|
||||
// We've got an object with some properties.
|
||||
for _, pName := range SortedSchemaKeys(schema.Properties) {
|
||||
p := schema.Properties[pName]
|
||||
propertyPath := append(path, pName)
|
||||
pSchema, err := GenerateGoSchema(p, propertyPath)
|
||||
if err != nil {
|
||||
return Schema{}, errors.Wrap(err, fmt.Sprintf("error generating Go schema for property '%s'", pName))
|
||||
}
|
||||
|
||||
required := StringInArray(pName, schema.Required)
|
||||
|
||||
if pSchema.HasAdditionalProperties && pSchema.RefType == "" {
|
||||
// If we have fields present which have additional properties,
|
||||
// but are not a pre-defined type, we need to define a type
|
||||
// for them, which will be based on the field names we followed
|
||||
// to get to the type.
|
||||
typeName := PathToTypeName(propertyPath)
|
||||
|
||||
typeDef := TypeDefinition{
|
||||
TypeName: typeName,
|
||||
JsonName: strings.Join(propertyPath, "."),
|
||||
Schema: pSchema,
|
||||
}
|
||||
pSchema.AdditionalTypes = append(pSchema.AdditionalTypes, typeDef)
|
||||
|
||||
pSchema.RefType = typeName
|
||||
}
|
||||
description := ""
|
||||
if p.Value != nil {
|
||||
description = p.Value.Description
|
||||
}
|
||||
prop := Property{
|
||||
JsonFieldName: pName,
|
||||
Schema: pSchema,
|
||||
Required: required,
|
||||
Description: description,
|
||||
Nullable: p.Value.Nullable,
|
||||
}
|
||||
outSchema.Properties = append(outSchema.Properties, prop)
|
||||
}
|
||||
|
||||
outSchema.HasAdditionalProperties = SchemaHasAdditionalProperties(schema)
|
||||
outSchema.AdditionalPropertiesType = &Schema{
|
||||
GoType: "interface{}",
|
||||
}
|
||||
if schema.AdditionalProperties != nil {
|
||||
additionalSchema, err := GenerateGoSchema(schema.AdditionalProperties, path)
|
||||
if err != nil {
|
||||
return Schema{}, errors.Wrap(err, "error generating type for additional properties")
|
||||
}
|
||||
outSchema.AdditionalPropertiesType = &additionalSchema
|
||||
}
|
||||
|
||||
outSchema.GoType = GenStructFromSchema(outSchema)
|
||||
}
|
||||
return outSchema, nil
|
||||
} else {
|
||||
f := schema.Format
|
||||
|
||||
switch t {
|
||||
case "array":
|
||||
// For arrays, we'll get the type of the Items and throw a
|
||||
// [] in front of it.
|
||||
arrayType, err := GenerateGoSchema(schema.Items, path)
|
||||
if err != nil {
|
||||
return Schema{}, errors.Wrap(err, "error generating type for array")
|
||||
}
|
||||
outSchema.GoType = "[]" + arrayType.TypeDecl()
|
||||
outSchema.Properties = arrayType.Properties
|
||||
case "integer":
|
||||
// We default to int if format doesn't ask for something else.
|
||||
if f == "int64" {
|
||||
outSchema.GoType = "int64"
|
||||
} else if f == "int32" {
|
||||
outSchema.GoType = "int32"
|
||||
} else if f == "" {
|
||||
outSchema.GoType = "int"
|
||||
} else {
|
||||
return Schema{}, fmt.Errorf("invalid integer format: %s", f)
|
||||
}
|
||||
case "number":
|
||||
// We default to float for "number"
|
||||
if f == "double" {
|
||||
outSchema.GoType = "float64"
|
||||
} else if f == "float" || f == "" {
|
||||
outSchema.GoType = "float32"
|
||||
} else {
|
||||
return Schema{}, fmt.Errorf("invalid number format: %s", f)
|
||||
}
|
||||
case "boolean":
|
||||
if f != "" {
|
||||
return Schema{}, fmt.Errorf("invalid format (%s) for boolean", f)
|
||||
}
|
||||
outSchema.GoType = "bool"
|
||||
case "string":
|
||||
enumValues := make([]string, len(schema.Enum))
|
||||
for i, enumValue := range schema.Enum {
|
||||
enumValues[i] = enumValue.(string)
|
||||
}
|
||||
|
||||
outSchema.EnumValues = SanitizeEnumNames(enumValues)
|
||||
|
||||
// Special case string formats here.
|
||||
switch f {
|
||||
case "byte":
|
||||
outSchema.GoType = "[]byte"
|
||||
case "email":
|
||||
outSchema.GoType = "openapi_types.Email"
|
||||
case "date":
|
||||
outSchema.GoType = "openapi_types.Date"
|
||||
case "date-time":
|
||||
outSchema.GoType = "time.Time"
|
||||
case "json":
|
||||
outSchema.GoType = "json.RawMessage"
|
||||
outSchema.SkipOptionalPointer = true
|
||||
default:
|
||||
// All unrecognized formats are simply a regular string.
|
||||
outSchema.GoType = "string"
|
||||
}
|
||||
default:
|
||||
return Schema{}, fmt.Errorf("unhandled Schema type: %s", t)
|
||||
}
|
||||
}
|
||||
return outSchema, nil
|
||||
}
|
||||
|
||||
// This describes a Schema, a type definition.
|
||||
type SchemaDescriptor struct {
|
||||
Fields []FieldDescriptor
|
||||
HasAdditionalProperties bool
|
||||
AdditionalPropertiesType string
|
||||
}
|
||||
|
||||
type FieldDescriptor struct {
|
||||
Required bool // Is the schema required? If not, we'll pass by pointer
|
||||
GoType string // The Go type needed to represent the json type.
|
||||
GoName string // The Go compatible type name for the type
|
||||
JsonName string // The json type name for the type
|
||||
IsRef bool // Is this schema a reference to predefined object?
|
||||
}
|
||||
|
||||
// Given a list of schema descriptors, produce corresponding field names with
|
||||
// JSON annotations
|
||||
func GenFieldsFromProperties(props []Property) []string {
|
||||
var fields []string
|
||||
for _, p := range props {
|
||||
field := ""
|
||||
// Add a comment to a field in case we have one, otherwise skip.
|
||||
if p.Description != "" {
|
||||
// Separate the comment from a previous-defined, unrelated field.
|
||||
// Make sure the actual field is separated by a newline.
|
||||
field += fmt.Sprintf("\n%s\n", StringToGoComment(p.Description))
|
||||
}
|
||||
field += fmt.Sprintf(" %s %s", p.GoFieldName(), p.GoTypeDef())
|
||||
if p.Required || p.Nullable {
|
||||
field += fmt.Sprintf(" `json:\"%s\"`", p.JsonFieldName)
|
||||
} else {
|
||||
field += fmt.Sprintf(" `json:\"%s,omitempty\"`", p.JsonFieldName)
|
||||
}
|
||||
fields = append(fields, field)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
func GenStructFromSchema(schema Schema) string {
|
||||
// Start out with struct {
|
||||
objectParts := []string{"struct {"}
|
||||
// Append all the field definitions
|
||||
objectParts = append(objectParts, GenFieldsFromProperties(schema.Properties)...)
|
||||
// Close the struct
|
||||
if schema.HasAdditionalProperties {
|
||||
addPropsType := schema.AdditionalPropertiesType.GoType
|
||||
if schema.AdditionalPropertiesType.RefType != "" {
|
||||
addPropsType = schema.AdditionalPropertiesType.RefType
|
||||
}
|
||||
|
||||
objectParts = append(objectParts,
|
||||
fmt.Sprintf("AdditionalProperties map[string]%s `json:\"-\"`", addPropsType))
|
||||
}
|
||||
objectParts = append(objectParts, "}")
|
||||
return strings.Join(objectParts, "\n")
|
||||
}
|
||||
|
||||
// Merge all the fields in the schemas supplied into one giant schema.
|
||||
func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) {
|
||||
var outSchema Schema
|
||||
for _, schemaOrRef := range allOf {
|
||||
ref := schemaOrRef.Ref
|
||||
|
||||
var refType string
|
||||
var err error
|
||||
if ref != "" {
|
||||
refType, err = RefPathToGoType(ref)
|
||||
if err != nil {
|
||||
return Schema{}, errors.Wrap(err, "error converting reference path to a go type")
|
||||
}
|
||||
}
|
||||
|
||||
schema, err := GenerateGoSchema(schemaOrRef, path)
|
||||
if err != nil {
|
||||
return Schema{}, errors.Wrap(err, "error generating Go schema in allOf")
|
||||
}
|
||||
schema.RefType = refType
|
||||
|
||||
for _, p := range schema.Properties {
|
||||
err = outSchema.MergeProperty(p)
|
||||
if err != nil {
|
||||
return Schema{}, errors.Wrap(err, "error merging properties")
|
||||
}
|
||||
}
|
||||
|
||||
if schema.HasAdditionalProperties {
|
||||
if outSchema.HasAdditionalProperties {
|
||||
// Both this schema, and the aggregate schema have additional
|
||||
// properties, they must match.
|
||||
if schema.AdditionalPropertiesType.TypeDecl() != outSchema.AdditionalPropertiesType.TypeDecl() {
|
||||
return Schema{}, errors.New("additional properties in allOf have incompatible types")
|
||||
}
|
||||
} else {
|
||||
// We're switching from having no additional properties to having
|
||||
// them
|
||||
outSchema.HasAdditionalProperties = true
|
||||
outSchema.AdditionalPropertiesType = schema.AdditionalPropertiesType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, we generate the struct which merges together all the fields.
|
||||
var err error
|
||||
outSchema.GoType, err = GenStructFromAllOf(allOf, path)
|
||||
if err != nil {
|
||||
return Schema{}, errors.Wrap(err, "unable to generate aggregate type for AllOf")
|
||||
}
|
||||
return outSchema, nil
|
||||
}
|
||||
|
||||
// This function generates an object that is the union of the objects in the
|
||||
// input array. In the case of Ref objects, we use an embedded struct, otherwise,
|
||||
// we inline the fields.
|
||||
func GenStructFromAllOf(allOf []*openapi3.SchemaRef, path []string) (string, error) {
|
||||
// Start out with struct {
|
||||
objectParts := []string{"struct {"}
|
||||
for _, schemaOrRef := range allOf {
|
||||
ref := schemaOrRef.Ref
|
||||
if ref != "" {
|
||||
// We have a referenced type, we will generate an inlined struct
|
||||
// member.
|
||||
// struct {
|
||||
// InlinedMember
|
||||
// ...
|
||||
// }
|
||||
goType, err := RefPathToGoType(ref)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
objectParts = append(objectParts,
|
||||
fmt.Sprintf(" // Embedded struct due to allOf(%s)", ref))
|
||||
objectParts = append(objectParts,
|
||||
fmt.Sprintf(" %s", goType))
|
||||
} else {
|
||||
// Inline all the fields from the schema into the output struct,
|
||||
// just like in the simple case of generating an object.
|
||||
goSchema, err := GenerateGoSchema(schemaOrRef, path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
objectParts = append(objectParts, " // Embedded fields due to inline allOf schema")
|
||||
objectParts = append(objectParts, GenFieldsFromProperties(goSchema.Properties)...)
|
||||
|
||||
if goSchema.HasAdditionalProperties {
|
||||
addPropsType := goSchema.AdditionalPropertiesType.GoType
|
||||
if goSchema.AdditionalPropertiesType.RefType != "" {
|
||||
addPropsType = goSchema.AdditionalPropertiesType.RefType
|
||||
}
|
||||
|
||||
additionalPropertiesPart := fmt.Sprintf("AdditionalProperties map[string]%s `json:\"-\"`", addPropsType)
|
||||
if !StringInArray(additionalPropertiesPart, objectParts) {
|
||||
objectParts = append(objectParts, additionalPropertiesPart)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
objectParts = append(objectParts, "}")
|
||||
return strings.Join(objectParts, "\n"), nil
|
||||
}
|
||||
|
||||
// This constructs a Go type for a parameter, looking at either the schema or
|
||||
// the content, whichever is available
|
||||
func paramToGoType(param *openapi3.Parameter, path []string) (Schema, error) {
|
||||
if param.Content == nil && param.Schema == nil {
|
||||
return Schema{}, fmt.Errorf("parameter '%s' has no schema or content", param.Name)
|
||||
}
|
||||
|
||||
// We can process the schema through the generic schema processor
|
||||
if param.Schema != nil {
|
||||
return GenerateGoSchema(param.Schema, path)
|
||||
}
|
||||
|
||||
// At this point, we have a content type. We know how to deal with
|
||||
// application/json, but if multiple formats are present, we can't do anything,
|
||||
// so we'll return the parameter as a string, not bothering to decode it.
|
||||
if len(param.Content) > 1 {
|
||||
return Schema{
|
||||
GoType: "string",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Otherwise, look for application/json in there
|
||||
mt, found := param.Content["application/json"]
|
||||
if !found {
|
||||
// If we don't have json, it's a string
|
||||
return Schema{
|
||||
GoType: "string",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// For json, we go through the standard schema mechanism
|
||||
return GenerateGoSchema(mt.Schema, path)
|
||||
}
|
||||
280
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/template_helpers.go
generated
vendored
Normal file
280
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/template_helpers.go
generated
vendored
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
// These allow the case statements to be sorted later:
|
||||
prefixMostSpecific, prefixLessSpecific, prefixLeastSpecific = "3", "6", "9"
|
||||
responseTypeSuffix = "Response"
|
||||
)
|
||||
|
||||
var (
|
||||
contentTypesJSON = []string{echo.MIMEApplicationJSON, "text/x-json"}
|
||||
contentTypesYAML = []string{"application/yaml", "application/x-yaml", "text/yaml", "text/x-yaml"}
|
||||
contentTypesXML = []string{echo.MIMEApplicationXML, echo.MIMETextXML}
|
||||
)
|
||||
|
||||
// This function takes an array of Parameter definition, and generates a valid
|
||||
// Go parameter declaration from them, eg:
|
||||
// ", foo int, bar string, baz float32". The preceding comma is there to save
|
||||
// a lot of work in the template engine.
|
||||
func genParamArgs(params []ParameterDefinition) string {
|
||||
if len(params) == 0 {
|
||||
return ""
|
||||
}
|
||||
parts := make([]string, len(params))
|
||||
for i, p := range params {
|
||||
paramName := p.GoVariableName()
|
||||
parts[i] = fmt.Sprintf("%s %s", paramName, p.TypeDef())
|
||||
}
|
||||
return ", " + strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// This function is much like the one above, except it only produces the
|
||||
// types of the parameters for a type declaration. It would produce this
|
||||
// from the same input as above:
|
||||
// ", int, string, float32".
|
||||
func genParamTypes(params []ParameterDefinition) string {
|
||||
if len(params) == 0 {
|
||||
return ""
|
||||
}
|
||||
parts := make([]string, len(params))
|
||||
for i, p := range params {
|
||||
parts[i] = p.TypeDef()
|
||||
}
|
||||
return ", " + strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// This is another variation of the function above which generates only the
|
||||
// parameter names:
|
||||
// ", foo, bar, baz"
|
||||
func genParamNames(params []ParameterDefinition) string {
|
||||
if len(params) == 0 {
|
||||
return ""
|
||||
}
|
||||
parts := make([]string, len(params))
|
||||
for i, p := range params {
|
||||
parts[i] = p.GoVariableName()
|
||||
}
|
||||
return ", " + strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
func genParamFmtString(path string) string {
|
||||
return ReplacePathParamsWithStr(path)
|
||||
}
|
||||
|
||||
// genResponsePayload generates the payload returned at the end of each client request function
|
||||
func genResponsePayload(operationID string) string {
|
||||
var buffer = bytes.NewBufferString("")
|
||||
|
||||
// Here is where we build up a response:
|
||||
fmt.Fprintf(buffer, "&%s{\n", genResponseTypeName(operationID))
|
||||
fmt.Fprintf(buffer, "Body: bodyBytes,\n")
|
||||
fmt.Fprintf(buffer, "HTTPResponse: rsp,\n")
|
||||
fmt.Fprintf(buffer, "}")
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// genResponseUnmarshal generates unmarshaling steps for structured response payloads
|
||||
func genResponseUnmarshal(op *OperationDefinition) string {
|
||||
var buffer = bytes.NewBufferString("")
|
||||
|
||||
var handledCaseClauses = make(map[string]string)
|
||||
var unhandledCaseClauses = make(map[string]string)
|
||||
|
||||
// Get the type definitions from the operation:
|
||||
typeDefinitions, err := op.GetResponseTypeDefinitions()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Add a case for each possible response:
|
||||
responses := op.Spec.Responses
|
||||
for _, typeDefinition := range typeDefinitions {
|
||||
|
||||
responseRef, ok := responses[typeDefinition.ResponseName]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// We can't do much without a value:
|
||||
if responseRef.Value == nil {
|
||||
fmt.Fprintf(os.Stderr, "Response %s.%s has nil value\n", op.OperationId, typeDefinition.ResponseName)
|
||||
continue
|
||||
}
|
||||
|
||||
// If there is no content-type then we have no unmarshaling to do:
|
||||
if len(responseRef.Value.Content) == 0 {
|
||||
caseAction := "break // No content-type"
|
||||
if typeDefinition.ResponseName == "default" {
|
||||
caseClauseKey := "default:"
|
||||
unhandledCaseClauses[prefixLeastSpecific+caseClauseKey] = fmt.Sprintf("%s\n%s\n", caseClauseKey, caseAction)
|
||||
} else {
|
||||
caseClauseKey := fmt.Sprintf("case rsp.StatusCode == %s:", typeDefinition.ResponseName)
|
||||
unhandledCaseClauses[prefixLessSpecific+caseClauseKey] = fmt.Sprintf("%s\n%s\n", caseClauseKey, caseAction)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// If we made it this far then we need to handle unmarshaling for each content-type:
|
||||
sortedContentKeys := SortedContentKeys(responseRef.Value.Content)
|
||||
for _, contentTypeName := range sortedContentKeys {
|
||||
|
||||
// We get "interface{}" when using "anyOf" or "oneOf" (which doesn't work with Go types):
|
||||
if typeDefinition.TypeName == "interface{}" {
|
||||
// Unable to unmarshal this, so we leave it out:
|
||||
continue
|
||||
}
|
||||
|
||||
// Add content-types here (json / yaml / xml etc):
|
||||
switch {
|
||||
|
||||
// JSON:
|
||||
case StringInArray(contentTypeName, contentTypesJSON):
|
||||
var caseAction string
|
||||
|
||||
caseAction = fmt.Sprintf("var dest %s\n"+
|
||||
"if err := json.Unmarshal(bodyBytes, &dest); err != nil { \n"+
|
||||
" return nil, err \n"+
|
||||
"}\n"+
|
||||
"response.%s = &dest",
|
||||
typeDefinition.Schema.TypeDecl(),
|
||||
typeDefinition.TypeName)
|
||||
|
||||
caseKey, caseClause := buildUnmarshalCase(typeDefinition, caseAction, "json")
|
||||
handledCaseClauses[caseKey] = caseClause
|
||||
|
||||
// YAML:
|
||||
case StringInArray(contentTypeName, contentTypesYAML):
|
||||
var caseAction string
|
||||
caseAction = fmt.Sprintf("var dest %s\n"+
|
||||
"if err := yaml.Unmarshal(bodyBytes, &dest); err != nil { \n"+
|
||||
" return nil, err \n"+
|
||||
"}\n"+
|
||||
"response.%s = &dest",
|
||||
typeDefinition.Schema.TypeDecl(),
|
||||
typeDefinition.TypeName)
|
||||
caseKey, caseClause := buildUnmarshalCase(typeDefinition, caseAction, "yaml")
|
||||
handledCaseClauses[caseKey] = caseClause
|
||||
|
||||
// XML:
|
||||
case StringInArray(contentTypeName, contentTypesXML):
|
||||
var caseAction string
|
||||
caseAction = fmt.Sprintf("var dest %s\n"+
|
||||
"if err := xml.Unmarshal(bodyBytes, &dest); err != nil { \n"+
|
||||
" return nil, err \n"+
|
||||
"}\n"+
|
||||
"response.%s = &dest",
|
||||
typeDefinition.Schema.TypeDecl(),
|
||||
typeDefinition.TypeName)
|
||||
caseKey, caseClause := buildUnmarshalCase(typeDefinition, caseAction, "xml")
|
||||
handledCaseClauses[caseKey] = caseClause
|
||||
|
||||
// Everything else:
|
||||
default:
|
||||
caseAction := fmt.Sprintf("// Content-type (%s) unsupported", contentTypeName)
|
||||
if typeDefinition.ResponseName == "default" {
|
||||
caseClauseKey := "default:"
|
||||
unhandledCaseClauses[prefixLeastSpecific+caseClauseKey] = fmt.Sprintf("%s\n%s\n", caseClauseKey, caseAction)
|
||||
} else {
|
||||
caseClauseKey := fmt.Sprintf("case rsp.StatusCode == %s:", typeDefinition.ResponseName)
|
||||
unhandledCaseClauses[prefixLessSpecific+caseClauseKey] = fmt.Sprintf("%s\n%s\n", caseClauseKey, caseAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now build the switch statement in order of most-to-least specific:
|
||||
// See: https://github.com/deepmap/oapi-codegen/issues/127 for why we handle this in two separate
|
||||
// groups.
|
||||
fmt.Fprintf(buffer, "switch {\n")
|
||||
for _, caseClauseKey := range SortedStringKeys(handledCaseClauses) {
|
||||
|
||||
fmt.Fprintf(buffer, "%s\n", handledCaseClauses[caseClauseKey])
|
||||
}
|
||||
for _, caseClauseKey := range SortedStringKeys(unhandledCaseClauses) {
|
||||
|
||||
fmt.Fprintf(buffer, "%s\n", unhandledCaseClauses[caseClauseKey])
|
||||
}
|
||||
fmt.Fprintf(buffer, "}\n")
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// buildUnmarshalCase builds an unmarshalling case clause for different content-types:
|
||||
func buildUnmarshalCase(typeDefinition TypeDefinition, caseAction string, contentType string) (caseKey string, caseClause string) {
|
||||
caseKey = fmt.Sprintf("%s.%s.%s", prefixLeastSpecific, contentType, typeDefinition.ResponseName)
|
||||
if typeDefinition.ResponseName == "default" {
|
||||
caseClause = fmt.Sprintf("case strings.Contains(rsp.Header.Get(\"%s\"), \"%s\"):\n%s\n", echo.HeaderContentType, contentType, caseAction)
|
||||
} else {
|
||||
caseClause = fmt.Sprintf("case strings.Contains(rsp.Header.Get(\"%s\"), \"%s\") && rsp.StatusCode == %s:\n%s\n", echo.HeaderContentType, contentType, typeDefinition.ResponseName, caseAction)
|
||||
}
|
||||
return caseKey, caseClause
|
||||
}
|
||||
|
||||
// genResponseTypeName creates the name of generated response types (given the operationID):
|
||||
func genResponseTypeName(operationID string) string {
|
||||
return fmt.Sprintf("%s%s", UppercaseFirstCharacter(operationID), responseTypeSuffix)
|
||||
}
|
||||
|
||||
func getResponseTypeDefinitions(op *OperationDefinition) []TypeDefinition {
|
||||
td, err := op.GetResponseTypeDefinitions()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return td
|
||||
}
|
||||
|
||||
// This outputs a string array
|
||||
func toStringArray(sarr []string) string {
|
||||
return `[]string{"` + strings.Join(sarr, `","`) + `"}`
|
||||
}
|
||||
|
||||
func stripNewLines(s string) string {
|
||||
r := strings.NewReplacer("\n", "")
|
||||
return r.Replace(s)
|
||||
}
|
||||
|
||||
// This function map is passed to the template engine, and we can call each
|
||||
// function here by keyName from the template code.
|
||||
var TemplateFunctions = template.FuncMap{
|
||||
"genParamArgs": genParamArgs,
|
||||
"genParamTypes": genParamTypes,
|
||||
"genParamNames": genParamNames,
|
||||
"genParamFmtString": genParamFmtString,
|
||||
"swaggerUriToEchoUri": SwaggerUriToEchoUri,
|
||||
"swaggerUriToChiUri": SwaggerUriToChiUri,
|
||||
"lcFirst": LowercaseFirstCharacter,
|
||||
"ucFirst": UppercaseFirstCharacter,
|
||||
"camelCase": ToCamelCase,
|
||||
"genResponsePayload": genResponsePayload,
|
||||
"genResponseTypeName": genResponseTypeName,
|
||||
"genResponseUnmarshal": genResponseUnmarshal,
|
||||
"getResponseTypeDefinitions": getResponseTypeDefinitions,
|
||||
"toStringArray": toStringArray,
|
||||
"lower": strings.ToLower,
|
||||
"title": strings.Title,
|
||||
"stripNewLines": stripNewLines,
|
||||
}
|
||||
70
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/additional-properties.tmpl
generated
vendored
Normal file
70
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/additional-properties.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
{{range .Types}}{{$addType := .Schema.AdditionalPropertiesType.TypeDecl}}
|
||||
|
||||
// Getter for additional properties for {{.TypeName}}. Returns the specified
|
||||
// element and whether it was found
|
||||
func (a {{.TypeName}}) Get(fieldName string) (value {{$addType}}, found bool) {
|
||||
if a.AdditionalProperties != nil {
|
||||
value, found = a.AdditionalProperties[fieldName]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Setter for additional properties for {{.TypeName}}
|
||||
func (a *{{.TypeName}}) Set(fieldName string, value {{$addType}}) {
|
||||
if a.AdditionalProperties == nil {
|
||||
a.AdditionalProperties = make(map[string]{{$addType}})
|
||||
}
|
||||
a.AdditionalProperties[fieldName] = value
|
||||
}
|
||||
|
||||
// Override default JSON handling for {{.TypeName}} to handle AdditionalProperties
|
||||
func (a *{{.TypeName}}) UnmarshalJSON(b []byte) error {
|
||||
object := make(map[string]json.RawMessage)
|
||||
err := json.Unmarshal(b, &object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
{{range .Schema.Properties}}
|
||||
if raw, found := object["{{.JsonFieldName}}"]; found {
|
||||
err = json.Unmarshal(raw, &a.{{.GoFieldName}})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error reading '{{.JsonFieldName}}'")
|
||||
}
|
||||
delete(object, "{{.JsonFieldName}}")
|
||||
}
|
||||
{{end}}
|
||||
if len(object) != 0 {
|
||||
a.AdditionalProperties = make(map[string]{{$addType}})
|
||||
for fieldName, fieldBuf := range object {
|
||||
var fieldVal {{$addType}}
|
||||
err := json.Unmarshal(fieldBuf, &fieldVal)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("error unmarshaling field %s", fieldName))
|
||||
}
|
||||
a.AdditionalProperties[fieldName] = fieldVal
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Override default JSON handling for {{.TypeName}} to handle AdditionalProperties
|
||||
func (a {{.TypeName}}) MarshalJSON() ([]byte, error) {
|
||||
var err error
|
||||
object := make(map[string]json.RawMessage)
|
||||
{{range .Schema.Properties}}
|
||||
{{if not .Required}}if a.{{.GoFieldName}} != nil { {{end}}
|
||||
object["{{.JsonFieldName}}"], err = json.Marshal(a.{{.GoFieldName}})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("error marshaling '{{.JsonFieldName}}'"))
|
||||
}
|
||||
{{if not .Required}} }{{end}}
|
||||
{{end}}
|
||||
for fieldName, field := range a.AdditionalProperties {
|
||||
object[fieldName], err = json.Marshal(field)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("error marshaling '%s'", fieldName))
|
||||
}
|
||||
}
|
||||
return json.Marshal(object)
|
||||
}
|
||||
{{end}}
|
||||
17
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/chi-handler.tmpl
generated
vendored
Normal file
17
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/chi-handler.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Handler creates http.Handler with routing matching OpenAPI spec.
|
||||
func Handler(si ServerInterface) http.Handler {
|
||||
return HandlerFromMux(si, chi.NewRouter())
|
||||
}
|
||||
|
||||
// HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
|
||||
func HandlerFromMux(si ServerInterface, r chi.Router) http.Handler {
|
||||
{{if .}}wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
}
|
||||
{{end}}
|
||||
{{range .}}r.Group(func(r chi.Router) {
|
||||
r.{{.Method | lower | title }}("{{.Path | swaggerUriToChiUri}}", wrapper.{{.OperationId}})
|
||||
})
|
||||
{{end}}
|
||||
return r
|
||||
}
|
||||
7
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/chi-interface.tmpl
generated
vendored
Normal file
7
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/chi-interface.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// ServerInterface represents all server handlers.
|
||||
type ServerInterface interface {
|
||||
{{range .}}{{.SummaryAsComment }}
|
||||
// ({{.Method}} {{.Path}})
|
||||
{{.OperationId}}(w http.ResponseWriter, r *http.Request{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}})
|
||||
{{end}}
|
||||
}
|
||||
167
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/chi-middleware.tmpl
generated
vendored
Normal file
167
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/chi-middleware.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
// ServerInterfaceWrapper converts contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
}
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}
|
||||
|
||||
// {{$opid}} operation middleware
|
||||
func (siw *ServerInterfaceWrapper) {{$opid}}(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
{{if or .RequiresParamObject (gt (len .PathParams) 0) }}
|
||||
var err error
|
||||
{{end}}
|
||||
|
||||
{{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
|
||||
var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
{{$varName}} = chi.URLParam(r, "{{.ParamName}}")
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(chi.URLParam(r, "{{.ParamName}}")), &{{$varName}})
|
||||
if err != nil {
|
||||
http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", chi.URLParam(r, "{{.ParamName}}"), &{{$varName}})
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
||||
{{range .SecurityDefinitions}}
|
||||
ctx = context.WithValue(ctx, "{{.ProviderName}}.Scopes", {{toStringArray .Scopes}})
|
||||
{{end}}
|
||||
|
||||
{{if .RequiresParamObject}}
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params {{.OperationId}}Params
|
||||
|
||||
{{range $paramIdx, $param := .QueryParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
|
||||
if paramValue := r.URL.Query().Get("{{.ParamName}}"); paramValue != "" {
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}paramValue
|
||||
{{end}}
|
||||
|
||||
{{if .IsJson}}
|
||||
var value {{.TypeDef}}
|
||||
err = json.Unmarshal([]byte(paramValue), &value)
|
||||
if err != nil {
|
||||
http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
http.Error(w, "Query argument {{.ParamName}} is required, but not found", http.StatusBadRequest)
|
||||
return
|
||||
}{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", r.URL.Query(), ¶ms.{{.GoName}})
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if .HeaderParams}}
|
||||
headers := r.Header
|
||||
|
||||
{{range .HeaderParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} header parameter "{{.ParamName}}" -------------
|
||||
if valueList, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found {
|
||||
var {{.GoName}} {{.TypeDef}}
|
||||
n := len(valueList)
|
||||
if n != 1 {
|
||||
http.Error(w, fmt.Sprintf("Expected one value for {{.ParamName}}, got %d", n), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
|
||||
{{end}}
|
||||
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
|
||||
if err != nil {
|
||||
http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", valueList[0], &{{.GoName}})
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
|
||||
|
||||
} {{if .Required}}else {
|
||||
http.Error(w, fmt.Sprintf("Header parameter {{.ParamName}} is required, but not found: %s", err), http.StatusBadRequest)
|
||||
return
|
||||
}{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .CookieParams}}
|
||||
if cookie, err := r.Cookie("{{.ParamName}}"); err == nil {
|
||||
|
||||
{{- if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}cookie.Value
|
||||
{{end}}
|
||||
|
||||
{{- if .IsJson}}
|
||||
var value {{.TypeDef}}
|
||||
var decoded string
|
||||
decoded, err := url.QueryUnescape(cookie.Value)
|
||||
if err != nil {
|
||||
http.Error(w, "Error unescaping cookie parameter '{{.ParamName}}'", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(decoded), &value)
|
||||
if err != nil {
|
||||
http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
{{- if .IsStyled}}
|
||||
var value {{.TypeDef}}
|
||||
err = runtime.BindStyledParameter("simple",{{.Explode}}, "{{.ParamName}}", cookie.Value, &value)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid format for parameter {{.ParamName}}: %s", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
}
|
||||
|
||||
{{- if .Required}} else {
|
||||
http.Error(w, "Query argument {{.ParamName}} is required, but not found", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{- end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
siw.Handler.{{.OperationId}}(w, r.WithContext(ctx){{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
|
||||
}
|
||||
{{end}}
|
||||
|
||||
|
||||
|
||||
115
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/client-with-responses.tmpl
generated
vendored
Normal file
115
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/client-with-responses.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
// ClientWithResponses builds on ClientInterface to offer response payloads
|
||||
type ClientWithResponses struct {
|
||||
ClientInterface
|
||||
}
|
||||
|
||||
// NewClientWithResponses creates a new ClientWithResponses, which wraps
|
||||
// Client with return type handling
|
||||
func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) {
|
||||
client, err := NewClient(server, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ClientWithResponses{client}, nil
|
||||
}
|
||||
|
||||
// WithBaseURL overrides the baseURL.
|
||||
func WithBaseURL(baseURL string) ClientOption {
|
||||
return func(c *Client) error {
|
||||
newBaseURL, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Server = newBaseURL.String()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ClientWithResponsesInterface is the interface specification for the client with responses above.
|
||||
type ClientWithResponsesInterface interface {
|
||||
{{range . -}}
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$opid := .OperationId -}}
|
||||
// {{$opid}} request {{if .HasBody}} with any body{{end}}
|
||||
{{$opid}}{{if .HasBody}}WithBody{{end}}WithResponse(ctx context.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}) (*{{genResponseTypeName $opid}}, error)
|
||||
{{range .Bodies}}
|
||||
{{$opid}}{{.Suffix}}WithResponse(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody) (*{{genResponseTypeName $opid}}, error)
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
{{end}}{{/* range . $opid := .OperationId */}}
|
||||
}
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}{{$op := .}}
|
||||
type {{$opid | ucFirst}}Response struct {
|
||||
Body []byte
|
||||
HTTPResponse *http.Response
|
||||
{{- range getResponseTypeDefinitions .}}
|
||||
{{.TypeName}} *{{.Schema.TypeDecl}}
|
||||
{{- end}}
|
||||
}
|
||||
|
||||
// Status returns HTTPResponse.Status
|
||||
func (r {{$opid | ucFirst}}Response) Status() string {
|
||||
if r.HTTPResponse != nil {
|
||||
return r.HTTPResponse.Status
|
||||
}
|
||||
return http.StatusText(0)
|
||||
}
|
||||
|
||||
// StatusCode returns HTTPResponse.StatusCode
|
||||
func (r {{$opid | ucFirst}}Response) StatusCode() int {
|
||||
if r.HTTPResponse != nil {
|
||||
return r.HTTPResponse.StatusCode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
{{end}}
|
||||
|
||||
|
||||
{{range .}}
|
||||
{{$opid := .OperationId -}}
|
||||
{{/* Generate client methods (with responses)*/}}
|
||||
|
||||
// {{$opid}}{{if .HasBody}}WithBody{{end}}WithResponse request{{if .HasBody}} with arbitrary body{{end}} returning *{{$opid}}Response
|
||||
func (c *ClientWithResponses) {{$opid}}{{if .HasBody}}WithBody{{end}}WithResponse(ctx context.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}) (*{{genResponseTypeName $opid}}, error){
|
||||
rsp, err := c.{{$opid}}{{if .HasBody}}WithBody{{end}}(ctx{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}}{{if .HasBody}}, contentType, body{{end}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Parse{{genResponseTypeName $opid | ucFirst}}(rsp)
|
||||
}
|
||||
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$bodyRequired := .BodyRequired -}}
|
||||
{{range .Bodies}}
|
||||
func (c *ClientWithResponses) {{$opid}}{{.Suffix}}WithResponse(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody) (*{{genResponseTypeName $opid}}, error) {
|
||||
rsp, err := c.{{$opid}}{{.Suffix}}(ctx{{genParamNames $pathParams}}{{if $hasParams}}, params{{end}}, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Parse{{genResponseTypeName $opid | ucFirst}}(rsp)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{end}}{{/* operations */}}
|
||||
|
||||
{{/* Generate parse functions for responses*/}}
|
||||
{{range .}}{{$opid := .OperationId}}
|
||||
|
||||
// Parse{{genResponseTypeName $opid | ucFirst}} parses an HTTP response from a {{$opid}}WithResponse call
|
||||
func Parse{{genResponseTypeName $opid | ucFirst}}(rsp *http.Response) (*{{genResponseTypeName $opid}}, error) {
|
||||
bodyBytes, err := ioutil.ReadAll(rsp.Body)
|
||||
defer rsp.Body.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := {{genResponsePayload $opid}}
|
||||
|
||||
{{genResponseUnmarshal .}}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
{{end}}{{/* range . $opid := .OperationId */}}
|
||||
|
||||
273
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/client.tmpl
generated
vendored
Normal file
273
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/client.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
// RequestEditorFn is the function signature for the RequestEditor callback function
|
||||
type RequestEditorFn func(ctx context.Context, req *http.Request) error
|
||||
|
||||
// Doer performs HTTP requests.
|
||||
//
|
||||
// The standard http.Client implements this interface.
|
||||
type HttpRequestDoer interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
// Client which conforms to the OpenAPI3 specification for this service.
|
||||
type Client struct {
|
||||
// The endpoint of the server conforming to this interface, with scheme,
|
||||
// https://api.deepmap.com for example.
|
||||
Server string
|
||||
|
||||
// Doer for performing requests, typically a *http.Client with any
|
||||
// customized settings, such as certificate chains.
|
||||
Client HttpRequestDoer
|
||||
|
||||
// A callback for modifying requests which are generated before sending over
|
||||
// the network.
|
||||
RequestEditor RequestEditorFn
|
||||
}
|
||||
|
||||
// ClientOption allows setting custom parameters during construction
|
||||
type ClientOption func(*Client) error
|
||||
|
||||
// Creates a new Client, with reasonable defaults
|
||||
func NewClient(server string, opts ...ClientOption) (*Client, error) {
|
||||
// create a client with sane default values
|
||||
client := Client{
|
||||
Server: server,
|
||||
}
|
||||
// mutate client and add all optional params
|
||||
for _, o := range opts {
|
||||
if err := o(&client); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// ensure the server URL always has a trailing slash
|
||||
if !strings.HasSuffix(client.Server, "/") {
|
||||
client.Server += "/"
|
||||
}
|
||||
// create httpClient, if not already present
|
||||
if client.Client == nil {
|
||||
client.Client = http.DefaultClient
|
||||
}
|
||||
return &client, nil
|
||||
}
|
||||
|
||||
// WithHTTPClient allows overriding the default Doer, which is
|
||||
// automatically created using http.Client. This is useful for tests.
|
||||
func WithHTTPClient(doer HttpRequestDoer) ClientOption {
|
||||
return func(c *Client) error {
|
||||
c.Client = doer
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithRequestEditorFn allows setting up a callback function, which will be
|
||||
// called right before sending the request. This can be used to mutate the request.
|
||||
func WithRequestEditorFn(fn RequestEditorFn) ClientOption {
|
||||
return func(c *Client) error {
|
||||
c.RequestEditor = fn
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// The interface specification for the client above.
|
||||
type ClientInterface interface {
|
||||
{{range . -}}
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$opid := .OperationId -}}
|
||||
// {{$opid}} request {{if .HasBody}} with any body{{end}}
|
||||
{{$opid}}{{if .HasBody}}WithBody{{end}}(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}) (*http.Response, error)
|
||||
{{range .Bodies}}
|
||||
{{$opid}}{{.Suffix}}(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody) (*http.Response, error)
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
{{end}}{{/* range . $opid := .OperationId */}}
|
||||
}
|
||||
|
||||
|
||||
{{/* Generate client methods */}}
|
||||
{{range . -}}
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$opid := .OperationId -}}
|
||||
|
||||
func (c *Client) {{$opid}}{{if .HasBody}}WithBody{{end}}(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}) (*http.Response, error) {
|
||||
req, err := New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(c.Server{{genParamNames .PathParams}}{{if $hasParams}}, params{{end}}{{if .HasBody}}, contentType, body{{end}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
if c.RequestEditor != nil {
|
||||
err = c.RequestEditor(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return c.Client.Do(req)
|
||||
}
|
||||
|
||||
{{range .Bodies}}
|
||||
func (c *Client) {{$opid}}{{.Suffix}}(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody) (*http.Response, error) {
|
||||
req, err := New{{$opid}}{{.Suffix}}Request(c.Server{{genParamNames $pathParams}}{{if $hasParams}}, params{{end}}, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
if c.RequestEditor != nil {
|
||||
err = c.RequestEditor(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return c.Client.Do(req)
|
||||
}
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
{{end}}
|
||||
|
||||
{{/* Generate request builders */}}
|
||||
{{range .}}
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$bodyRequired := .BodyRequired -}}
|
||||
{{$opid := .OperationId -}}
|
||||
|
||||
{{range .Bodies}}
|
||||
// New{{$opid}}Request{{.Suffix}} calls the generic {{$opid}} builder with {{.ContentType}} body
|
||||
func New{{$opid}}Request{{.Suffix}}(server string{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody) (*http.Request, error) {
|
||||
var bodyReader io.Reader
|
||||
buf, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bodyReader = bytes.NewReader(buf)
|
||||
return New{{$opid}}RequestWithBody(server{{genParamNames $pathParams}}{{if $hasParams}}, params{{end}}, "{{.ContentType}}", bodyReader)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
// New{{$opid}}Request{{if .HasBody}}WithBody{{end}} generates requests for {{$opid}}{{if .HasBody}} with any type of body{{end}}
|
||||
func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}) (*http.Request, error) {
|
||||
var err error
|
||||
{{range $paramIdx, $param := .PathParams}}
|
||||
var pathParam{{$paramIdx}} string
|
||||
{{if .IsPassThrough}}
|
||||
pathParam{{$paramIdx}} = {{.ParamName}}
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var pathParamBuf{{$paramIdx}} []byte
|
||||
pathParamBuf{{$paramIdx}}, err = json.Marshal({{.ParamName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pathParam{{$paramIdx}} = string(pathParamBuf{{$paramIdx}})
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
pathParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, "{{.ParamName}}", {{.GoVariableName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
queryUrl, err := url.Parse(server)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
basePath := fmt.Sprintf("{{genParamFmtString .Path}}"{{range $paramIdx, $param := .PathParams}}, pathParam{{$paramIdx}}{{end}})
|
||||
if basePath[0] == '/' {
|
||||
basePath = basePath[1:]
|
||||
}
|
||||
|
||||
queryUrl, err = queryUrl.Parse(basePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{if .QueryParams}}
|
||||
queryValues := queryUrl.Query()
|
||||
{{range $paramIdx, $param := .QueryParams}}
|
||||
{{if not .Required}} if params.{{.GoName}} != nil { {{end}}
|
||||
{{if .IsPassThrough}}
|
||||
queryValues.Add("{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
if queryParamBuf, err := json.Marshal({{if not .Required}}*{{end}}params.{{.GoName}}); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
queryValues.Add("{{.ParamName}}", string(queryParamBuf))
|
||||
}
|
||||
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
if queryFrag, err := runtime.StyleParam("{{.Style}}", {{.Explode}}, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}); err != nil {
|
||||
return nil, err
|
||||
} else if parsed, err := url.ParseQuery(queryFrag); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
for k, v := range parsed {
|
||||
for _, v2 := range v {
|
||||
queryValues.Add(k, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
{{if not .Required}}}{{end}}
|
||||
{{end}}
|
||||
queryUrl.RawQuery = queryValues.Encode()
|
||||
{{end}}{{/* if .QueryParams */}}
|
||||
req, err := http.NewRequest("{{.Method}}", queryUrl.String(), {{if .HasBody}}body{{else}}nil{{end}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
{{range $paramIdx, $param := .HeaderParams}}
|
||||
{{if not .Required}} if params.{{.GoName}} != nil { {{end}}
|
||||
var headerParam{{$paramIdx}} string
|
||||
{{if .IsPassThrough}}
|
||||
headerParam{{$paramIdx}} = {{if not .Required}}*{{end}}params.{{.GoName}}
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var headerParamBuf{{$paramIdx}} []byte
|
||||
headerParamBuf{{$paramIdx}}, err = json.Marshal({{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
headerParam{{$paramIdx}} = string(headerParamBuf{{$paramIdx}})
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
headerParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{end}}
|
||||
req.Header.Add("{{.ParamName}}", headerParam{{$paramIdx}})
|
||||
{{if not .Required}}}{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range $paramIdx, $param := .CookieParams}}
|
||||
{{if not .Required}} if params.{{.GoName}} != nil { {{end}}
|
||||
var cookieParam{{$paramIdx}} string
|
||||
{{if .IsPassThrough}}
|
||||
cookieParam{{$paramIdx}} = {{if not .Required}}*{{end}}params.{{.GoName}}
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var cookieParamBuf{{$paramIdx}} []byte
|
||||
cookieParamBuf{{$paramIdx}}, err = json.Marshal({{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cookieParam{{$paramIdx}} = url.QueryEscape(string(cookieParamBuf{{$paramIdx}}))
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
cookieParam{{$paramIdx}}, err = runtime.StyleParam("simple", {{.Explode}}, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{end}}
|
||||
cookie{{$paramIdx}} := &http.Cookie{
|
||||
Name:"{{.ParamName}}",
|
||||
Value:cookieParam{{$paramIdx}},
|
||||
}
|
||||
req.AddCookie(cookie{{$paramIdx}})
|
||||
{{if not .Required}}}{{end}}
|
||||
{{end}}
|
||||
{{if .HasBody}}req.Header.Add("Content-Type", contentType){{end}}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
{{end}}{{/* Range */}}
|
||||
3
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/doc.go
generated
vendored
Normal file
3
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
package templates
|
||||
|
||||
//go:generate go run github.com/cyberdelia/templates -s . -o templates.gen.go
|
||||
10
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/imports.tmpl
generated
vendored
Normal file
10
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/imports.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// Package {{.PackageName}} provides primitives to interact the openapi HTTP API.
|
||||
//
|
||||
// Code generated by github.com/deepmap/oapi-codegen DO NOT EDIT.
|
||||
package {{.PackageName}}
|
||||
|
||||
{{if .Imports}}
|
||||
import (
|
||||
{{range .Imports}} {{ . }}
|
||||
{{end}})
|
||||
{{end}}
|
||||
29
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/inline.tmpl
generated
vendored
Normal file
29
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/inline.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||
var swaggerSpec = []string{
|
||||
{{range .}}
|
||||
"{{.}}",{{end}}
|
||||
}
|
||||
|
||||
// GetSwagger returns the Swagger specification corresponding to the generated code
|
||||
// in this file.
|
||||
func GetSwagger() (*openapi3.Swagger, error) {
|
||||
zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error base64 decoding spec: %s", err)
|
||||
}
|
||||
zr, err := gzip.NewReader(bytes.NewReader(zipped))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decompressing spec: %s", err)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
_, err = buf.ReadFrom(zr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decompressing spec: %s", err)
|
||||
}
|
||||
|
||||
swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(buf.Bytes())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error loading Swagger: %s", err)
|
||||
}
|
||||
return swagger, nil
|
||||
}
|
||||
6
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/param-types.tmpl
generated
vendored
Normal file
6
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/param-types.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{{range .}}{{$opid := .OperationId}}
|
||||
{{range .TypeDefinitions}}
|
||||
// {{.TypeName}} defines parameters for {{$opid}}.
|
||||
type {{.TypeName}} {{.Schema.TypeDecl}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
27
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/register.tmpl
generated
vendored
Normal file
27
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/register.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
|
||||
// This is a simple interface which specifies echo.Route addition functions which
|
||||
// are present on both echo.Echo and echo.Group, since we want to allow using
|
||||
// either of them for path registration
|
||||
type EchoRouter interface {
|
||||
CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
}
|
||||
|
||||
// RegisterHandlers adds each server route to the EchoRouter.
|
||||
func RegisterHandlers(router EchoRouter, si ServerInterface) {
|
||||
{{if .}}
|
||||
wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
}
|
||||
{{end}}
|
||||
{{range .}}router.{{.Method}}("{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}})
|
||||
{{end}}
|
||||
}
|
||||
6
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/request-bodies.tmpl
generated
vendored
Normal file
6
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/request-bodies.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{{range .}}{{$opid := .OperationId}}
|
||||
{{range .Bodies}}
|
||||
// {{$opid}}RequestBody defines body for {{$opid}} for application/json ContentType.
|
||||
type {{$opid}}{{.NameTag}}RequestBody {{.TypeDef}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
7
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/server-interface.tmpl
generated
vendored
Normal file
7
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/server-interface.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// ServerInterface represents all server handlers.
|
||||
type ServerInterface interface {
|
||||
{{range .}}{{.SummaryAsComment }}
|
||||
// ({{.Method}} {{.Path}})
|
||||
{{.OperationId}}(ctx echo.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}}) error
|
||||
{{end}}
|
||||
}
|
||||
914
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/templates.gen.go
generated
vendored
Normal file
914
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/templates.gen.go
generated
vendored
Normal file
|
|
@ -0,0 +1,914 @@
|
|||
package templates
|
||||
|
||||
import "text/template"
|
||||
|
||||
var templates = map[string]string{"additional-properties.tmpl": `{{range .Types}}{{$addType := .Schema.AdditionalPropertiesType.TypeDecl}}
|
||||
|
||||
// Getter for additional properties for {{.TypeName}}. Returns the specified
|
||||
// element and whether it was found
|
||||
func (a {{.TypeName}}) Get(fieldName string) (value {{$addType}}, found bool) {
|
||||
if a.AdditionalProperties != nil {
|
||||
value, found = a.AdditionalProperties[fieldName]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Setter for additional properties for {{.TypeName}}
|
||||
func (a *{{.TypeName}}) Set(fieldName string, value {{$addType}}) {
|
||||
if a.AdditionalProperties == nil {
|
||||
a.AdditionalProperties = make(map[string]{{$addType}})
|
||||
}
|
||||
a.AdditionalProperties[fieldName] = value
|
||||
}
|
||||
|
||||
// Override default JSON handling for {{.TypeName}} to handle AdditionalProperties
|
||||
func (a *{{.TypeName}}) UnmarshalJSON(b []byte) error {
|
||||
object := make(map[string]json.RawMessage)
|
||||
err := json.Unmarshal(b, &object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
{{range .Schema.Properties}}
|
||||
if raw, found := object["{{.JsonFieldName}}"]; found {
|
||||
err = json.Unmarshal(raw, &a.{{.GoFieldName}})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error reading '{{.JsonFieldName}}'")
|
||||
}
|
||||
delete(object, "{{.JsonFieldName}}")
|
||||
}
|
||||
{{end}}
|
||||
if len(object) != 0 {
|
||||
a.AdditionalProperties = make(map[string]{{$addType}})
|
||||
for fieldName, fieldBuf := range object {
|
||||
var fieldVal {{$addType}}
|
||||
err := json.Unmarshal(fieldBuf, &fieldVal)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("error unmarshaling field %s", fieldName))
|
||||
}
|
||||
a.AdditionalProperties[fieldName] = fieldVal
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Override default JSON handling for {{.TypeName}} to handle AdditionalProperties
|
||||
func (a {{.TypeName}}) MarshalJSON() ([]byte, error) {
|
||||
var err error
|
||||
object := make(map[string]json.RawMessage)
|
||||
{{range .Schema.Properties}}
|
||||
{{if not .Required}}if a.{{.GoFieldName}} != nil { {{end}}
|
||||
object["{{.JsonFieldName}}"], err = json.Marshal(a.{{.GoFieldName}})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("error marshaling '{{.JsonFieldName}}'"))
|
||||
}
|
||||
{{if not .Required}} }{{end}}
|
||||
{{end}}
|
||||
for fieldName, field := range a.AdditionalProperties {
|
||||
object[fieldName], err = json.Marshal(field)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("error marshaling '%s'", fieldName))
|
||||
}
|
||||
}
|
||||
return json.Marshal(object)
|
||||
}
|
||||
{{end}}
|
||||
`,
|
||||
"chi-handler.tmpl": `// Handler creates http.Handler with routing matching OpenAPI spec.
|
||||
func Handler(si ServerInterface) http.Handler {
|
||||
return HandlerFromMux(si, chi.NewRouter())
|
||||
}
|
||||
|
||||
// HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
|
||||
func HandlerFromMux(si ServerInterface, r chi.Router) http.Handler {
|
||||
{{if .}}wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
}
|
||||
{{end}}
|
||||
{{range .}}r.Group(func(r chi.Router) {
|
||||
r.{{.Method | lower | title }}("{{.Path | swaggerUriToChiUri}}", wrapper.{{.OperationId}})
|
||||
})
|
||||
{{end}}
|
||||
return r
|
||||
}
|
||||
`,
|
||||
"chi-interface.tmpl": `// ServerInterface represents all server handlers.
|
||||
type ServerInterface interface {
|
||||
{{range .}}{{.SummaryAsComment }}
|
||||
// ({{.Method}} {{.Path}})
|
||||
{{.OperationId}}(w http.ResponseWriter, r *http.Request{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}})
|
||||
{{end}}
|
||||
}
|
||||
`,
|
||||
"chi-middleware.tmpl": `// ServerInterfaceWrapper converts contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
}
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}
|
||||
|
||||
// {{$opid}} operation middleware
|
||||
func (siw *ServerInterfaceWrapper) {{$opid}}(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
{{if or .RequiresParamObject (gt (len .PathParams) 0) }}
|
||||
var err error
|
||||
{{end}}
|
||||
|
||||
{{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
|
||||
var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
{{$varName}} = chi.URLParam(r, "{{.ParamName}}")
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(chi.URLParam(r, "{{.ParamName}}")), &{{$varName}})
|
||||
if err != nil {
|
||||
http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", chi.URLParam(r, "{{.ParamName}}"), &{{$varName}})
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
||||
{{range .SecurityDefinitions}}
|
||||
ctx = context.WithValue(ctx, "{{.ProviderName}}.Scopes", {{toStringArray .Scopes}})
|
||||
{{end}}
|
||||
|
||||
{{if .RequiresParamObject}}
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params {{.OperationId}}Params
|
||||
|
||||
{{range $paramIdx, $param := .QueryParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
|
||||
if paramValue := r.URL.Query().Get("{{.ParamName}}"); paramValue != "" {
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}paramValue
|
||||
{{end}}
|
||||
|
||||
{{if .IsJson}}
|
||||
var value {{.TypeDef}}
|
||||
err = json.Unmarshal([]byte(paramValue), &value)
|
||||
if err != nil {
|
||||
http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
http.Error(w, "Query argument {{.ParamName}} is required, but not found", http.StatusBadRequest)
|
||||
return
|
||||
}{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", r.URL.Query(), ¶ms.{{.GoName}})
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if .HeaderParams}}
|
||||
headers := r.Header
|
||||
|
||||
{{range .HeaderParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} header parameter "{{.ParamName}}" -------------
|
||||
if valueList, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found {
|
||||
var {{.GoName}} {{.TypeDef}}
|
||||
n := len(valueList)
|
||||
if n != 1 {
|
||||
http.Error(w, fmt.Sprintf("Expected one value for {{.ParamName}}, got %d", n), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
|
||||
{{end}}
|
||||
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
|
||||
if err != nil {
|
||||
http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", valueList[0], &{{.GoName}})
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
|
||||
|
||||
} {{if .Required}}else {
|
||||
http.Error(w, fmt.Sprintf("Header parameter {{.ParamName}} is required, but not found: %s", err), http.StatusBadRequest)
|
||||
return
|
||||
}{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .CookieParams}}
|
||||
if cookie, err := r.Cookie("{{.ParamName}}"); err == nil {
|
||||
|
||||
{{- if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}cookie.Value
|
||||
{{end}}
|
||||
|
||||
{{- if .IsJson}}
|
||||
var value {{.TypeDef}}
|
||||
var decoded string
|
||||
decoded, err := url.QueryUnescape(cookie.Value)
|
||||
if err != nil {
|
||||
http.Error(w, "Error unescaping cookie parameter '{{.ParamName}}'", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(decoded), &value)
|
||||
if err != nil {
|
||||
http.Error(w, "Error unmarshaling parameter '{{.ParamName}}' as JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
{{- if .IsStyled}}
|
||||
var value {{.TypeDef}}
|
||||
err = runtime.BindStyledParameter("simple",{{.Explode}}, "{{.ParamName}}", cookie.Value, &value)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid format for parameter {{.ParamName}}: %s", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
|
||||
}
|
||||
|
||||
{{- if .Required}} else {
|
||||
http.Error(w, "Query argument {{.ParamName}} is required, but not found", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
{{- end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
siw.Handler.{{.OperationId}}(w, r.WithContext(ctx){{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
|
||||
}
|
||||
{{end}}
|
||||
|
||||
|
||||
|
||||
`,
|
||||
"client-with-responses.tmpl": `// ClientWithResponses builds on ClientInterface to offer response payloads
|
||||
type ClientWithResponses struct {
|
||||
ClientInterface
|
||||
}
|
||||
|
||||
// NewClientWithResponses creates a new ClientWithResponses, which wraps
|
||||
// Client with return type handling
|
||||
func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) {
|
||||
client, err := NewClient(server, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ClientWithResponses{client}, nil
|
||||
}
|
||||
|
||||
// WithBaseURL overrides the baseURL.
|
||||
func WithBaseURL(baseURL string) ClientOption {
|
||||
return func(c *Client) error {
|
||||
newBaseURL, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Server = newBaseURL.String()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ClientWithResponsesInterface is the interface specification for the client with responses above.
|
||||
type ClientWithResponsesInterface interface {
|
||||
{{range . -}}
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$opid := .OperationId -}}
|
||||
// {{$opid}} request {{if .HasBody}} with any body{{end}}
|
||||
{{$opid}}{{if .HasBody}}WithBody{{end}}WithResponse(ctx context.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}) (*{{genResponseTypeName $opid}}, error)
|
||||
{{range .Bodies}}
|
||||
{{$opid}}{{.Suffix}}WithResponse(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody) (*{{genResponseTypeName $opid}}, error)
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
{{end}}{{/* range . $opid := .OperationId */}}
|
||||
}
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}{{$op := .}}
|
||||
type {{$opid | ucFirst}}Response struct {
|
||||
Body []byte
|
||||
HTTPResponse *http.Response
|
||||
{{- range getResponseTypeDefinitions .}}
|
||||
{{.TypeName}} *{{.Schema.TypeDecl}}
|
||||
{{- end}}
|
||||
}
|
||||
|
||||
// Status returns HTTPResponse.Status
|
||||
func (r {{$opid | ucFirst}}Response) Status() string {
|
||||
if r.HTTPResponse != nil {
|
||||
return r.HTTPResponse.Status
|
||||
}
|
||||
return http.StatusText(0)
|
||||
}
|
||||
|
||||
// StatusCode returns HTTPResponse.StatusCode
|
||||
func (r {{$opid | ucFirst}}Response) StatusCode() int {
|
||||
if r.HTTPResponse != nil {
|
||||
return r.HTTPResponse.StatusCode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
{{end}}
|
||||
|
||||
|
||||
{{range .}}
|
||||
{{$opid := .OperationId -}}
|
||||
{{/* Generate client methods (with responses)*/}}
|
||||
|
||||
// {{$opid}}{{if .HasBody}}WithBody{{end}}WithResponse request{{if .HasBody}} with arbitrary body{{end}} returning *{{$opid}}Response
|
||||
func (c *ClientWithResponses) {{$opid}}{{if .HasBody}}WithBody{{end}}WithResponse(ctx context.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}) (*{{genResponseTypeName $opid}}, error){
|
||||
rsp, err := c.{{$opid}}{{if .HasBody}}WithBody{{end}}(ctx{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}}{{if .HasBody}}, contentType, body{{end}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Parse{{genResponseTypeName $opid | ucFirst}}(rsp)
|
||||
}
|
||||
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$bodyRequired := .BodyRequired -}}
|
||||
{{range .Bodies}}
|
||||
func (c *ClientWithResponses) {{$opid}}{{.Suffix}}WithResponse(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody) (*{{genResponseTypeName $opid}}, error) {
|
||||
rsp, err := c.{{$opid}}{{.Suffix}}(ctx{{genParamNames $pathParams}}{{if $hasParams}}, params{{end}}, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Parse{{genResponseTypeName $opid | ucFirst}}(rsp)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{end}}{{/* operations */}}
|
||||
|
||||
{{/* Generate parse functions for responses*/}}
|
||||
{{range .}}{{$opid := .OperationId}}
|
||||
|
||||
// Parse{{genResponseTypeName $opid | ucFirst}} parses an HTTP response from a {{$opid}}WithResponse call
|
||||
func Parse{{genResponseTypeName $opid | ucFirst}}(rsp *http.Response) (*{{genResponseTypeName $opid}}, error) {
|
||||
bodyBytes, err := ioutil.ReadAll(rsp.Body)
|
||||
defer rsp.Body.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := {{genResponsePayload $opid}}
|
||||
|
||||
{{genResponseUnmarshal .}}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
{{end}}{{/* range . $opid := .OperationId */}}
|
||||
|
||||
`,
|
||||
"client.tmpl": `// RequestEditorFn is the function signature for the RequestEditor callback function
|
||||
type RequestEditorFn func(ctx context.Context, req *http.Request) error
|
||||
|
||||
// Doer performs HTTP requests.
|
||||
//
|
||||
// The standard http.Client implements this interface.
|
||||
type HttpRequestDoer interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
// Client which conforms to the OpenAPI3 specification for this service.
|
||||
type Client struct {
|
||||
// The endpoint of the server conforming to this interface, with scheme,
|
||||
// https://api.deepmap.com for example.
|
||||
Server string
|
||||
|
||||
// Doer for performing requests, typically a *http.Client with any
|
||||
// customized settings, such as certificate chains.
|
||||
Client HttpRequestDoer
|
||||
|
||||
// A callback for modifying requests which are generated before sending over
|
||||
// the network.
|
||||
RequestEditor RequestEditorFn
|
||||
}
|
||||
|
||||
// ClientOption allows setting custom parameters during construction
|
||||
type ClientOption func(*Client) error
|
||||
|
||||
// Creates a new Client, with reasonable defaults
|
||||
func NewClient(server string, opts ...ClientOption) (*Client, error) {
|
||||
// create a client with sane default values
|
||||
client := Client{
|
||||
Server: server,
|
||||
}
|
||||
// mutate client and add all optional params
|
||||
for _, o := range opts {
|
||||
if err := o(&client); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// ensure the server URL always has a trailing slash
|
||||
if !strings.HasSuffix(client.Server, "/") {
|
||||
client.Server += "/"
|
||||
}
|
||||
// create httpClient, if not already present
|
||||
if client.Client == nil {
|
||||
client.Client = http.DefaultClient
|
||||
}
|
||||
return &client, nil
|
||||
}
|
||||
|
||||
// WithHTTPClient allows overriding the default Doer, which is
|
||||
// automatically created using http.Client. This is useful for tests.
|
||||
func WithHTTPClient(doer HttpRequestDoer) ClientOption {
|
||||
return func(c *Client) error {
|
||||
c.Client = doer
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithRequestEditorFn allows setting up a callback function, which will be
|
||||
// called right before sending the request. This can be used to mutate the request.
|
||||
func WithRequestEditorFn(fn RequestEditorFn) ClientOption {
|
||||
return func(c *Client) error {
|
||||
c.RequestEditor = fn
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// The interface specification for the client above.
|
||||
type ClientInterface interface {
|
||||
{{range . -}}
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$opid := .OperationId -}}
|
||||
// {{$opid}} request {{if .HasBody}} with any body{{end}}
|
||||
{{$opid}}{{if .HasBody}}WithBody{{end}}(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}) (*http.Response, error)
|
||||
{{range .Bodies}}
|
||||
{{$opid}}{{.Suffix}}(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody) (*http.Response, error)
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
{{end}}{{/* range . $opid := .OperationId */}}
|
||||
}
|
||||
|
||||
|
||||
{{/* Generate client methods */}}
|
||||
{{range . -}}
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$opid := .OperationId -}}
|
||||
|
||||
func (c *Client) {{$opid}}{{if .HasBody}}WithBody{{end}}(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}) (*http.Response, error) {
|
||||
req, err := New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(c.Server{{genParamNames .PathParams}}{{if $hasParams}}, params{{end}}{{if .HasBody}}, contentType, body{{end}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
if c.RequestEditor != nil {
|
||||
err = c.RequestEditor(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return c.Client.Do(req)
|
||||
}
|
||||
|
||||
{{range .Bodies}}
|
||||
func (c *Client) {{$opid}}{{.Suffix}}(ctx context.Context{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody) (*http.Response, error) {
|
||||
req, err := New{{$opid}}{{.Suffix}}Request(c.Server{{genParamNames $pathParams}}{{if $hasParams}}, params{{end}}, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
if c.RequestEditor != nil {
|
||||
err = c.RequestEditor(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return c.Client.Do(req)
|
||||
}
|
||||
{{end}}{{/* range .Bodies */}}
|
||||
{{end}}
|
||||
|
||||
{{/* Generate request builders */}}
|
||||
{{range .}}
|
||||
{{$hasParams := .RequiresParamObject -}}
|
||||
{{$pathParams := .PathParams -}}
|
||||
{{$bodyRequired := .BodyRequired -}}
|
||||
{{$opid := .OperationId -}}
|
||||
|
||||
{{range .Bodies}}
|
||||
// New{{$opid}}Request{{.Suffix}} calls the generic {{$opid}} builder with {{.ContentType}} body
|
||||
func New{{$opid}}Request{{.Suffix}}(server string{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}, body {{$opid}}{{.NameTag}}RequestBody) (*http.Request, error) {
|
||||
var bodyReader io.Reader
|
||||
buf, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bodyReader = bytes.NewReader(buf)
|
||||
return New{{$opid}}RequestWithBody(server{{genParamNames $pathParams}}{{if $hasParams}}, params{{end}}, "{{.ContentType}}", bodyReader)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
// New{{$opid}}Request{{if .HasBody}}WithBody{{end}} generates requests for {{$opid}}{{if .HasBody}} with any type of body{{end}}
|
||||
func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamArgs $pathParams}}{{if $hasParams}}, params *{{$opid}}Params{{end}}{{if .HasBody}}, contentType string, body io.Reader{{end}}) (*http.Request, error) {
|
||||
var err error
|
||||
{{range $paramIdx, $param := .PathParams}}
|
||||
var pathParam{{$paramIdx}} string
|
||||
{{if .IsPassThrough}}
|
||||
pathParam{{$paramIdx}} = {{.ParamName}}
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var pathParamBuf{{$paramIdx}} []byte
|
||||
pathParamBuf{{$paramIdx}}, err = json.Marshal({{.ParamName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pathParam{{$paramIdx}} = string(pathParamBuf{{$paramIdx}})
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
pathParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, "{{.ParamName}}", {{.GoVariableName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
queryUrl, err := url.Parse(server)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
basePath := fmt.Sprintf("{{genParamFmtString .Path}}"{{range $paramIdx, $param := .PathParams}}, pathParam{{$paramIdx}}{{end}})
|
||||
if basePath[0] == '/' {
|
||||
basePath = basePath[1:]
|
||||
}
|
||||
|
||||
queryUrl, err = queryUrl.Parse(basePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{if .QueryParams}}
|
||||
queryValues := queryUrl.Query()
|
||||
{{range $paramIdx, $param := .QueryParams}}
|
||||
{{if not .Required}} if params.{{.GoName}} != nil { {{end}}
|
||||
{{if .IsPassThrough}}
|
||||
queryValues.Add("{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
if queryParamBuf, err := json.Marshal({{if not .Required}}*{{end}}params.{{.GoName}}); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
queryValues.Add("{{.ParamName}}", string(queryParamBuf))
|
||||
}
|
||||
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
if queryFrag, err := runtime.StyleParam("{{.Style}}", {{.Explode}}, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}); err != nil {
|
||||
return nil, err
|
||||
} else if parsed, err := url.ParseQuery(queryFrag); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
for k, v := range parsed {
|
||||
for _, v2 := range v {
|
||||
queryValues.Add(k, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
{{if not .Required}}}{{end}}
|
||||
{{end}}
|
||||
queryUrl.RawQuery = queryValues.Encode()
|
||||
{{end}}{{/* if .QueryParams */}}
|
||||
req, err := http.NewRequest("{{.Method}}", queryUrl.String(), {{if .HasBody}}body{{else}}nil{{end}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
{{range $paramIdx, $param := .HeaderParams}}
|
||||
{{if not .Required}} if params.{{.GoName}} != nil { {{end}}
|
||||
var headerParam{{$paramIdx}} string
|
||||
{{if .IsPassThrough}}
|
||||
headerParam{{$paramIdx}} = {{if not .Required}}*{{end}}params.{{.GoName}}
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var headerParamBuf{{$paramIdx}} []byte
|
||||
headerParamBuf{{$paramIdx}}, err = json.Marshal({{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
headerParam{{$paramIdx}} = string(headerParamBuf{{$paramIdx}})
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
headerParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{end}}
|
||||
req.Header.Add("{{.ParamName}}", headerParam{{$paramIdx}})
|
||||
{{if not .Required}}}{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range $paramIdx, $param := .CookieParams}}
|
||||
{{if not .Required}} if params.{{.GoName}} != nil { {{end}}
|
||||
var cookieParam{{$paramIdx}} string
|
||||
{{if .IsPassThrough}}
|
||||
cookieParam{{$paramIdx}} = {{if not .Required}}*{{end}}params.{{.GoName}}
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var cookieParamBuf{{$paramIdx}} []byte
|
||||
cookieParamBuf{{$paramIdx}}, err = json.Marshal({{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cookieParam{{$paramIdx}} = url.QueryEscape(string(cookieParamBuf{{$paramIdx}}))
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
cookieParam{{$paramIdx}}, err = runtime.StyleParam("simple", {{.Explode}}, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{end}}
|
||||
cookie{{$paramIdx}} := &http.Cookie{
|
||||
Name:"{{.ParamName}}",
|
||||
Value:cookieParam{{$paramIdx}},
|
||||
}
|
||||
req.AddCookie(cookie{{$paramIdx}})
|
||||
{{if not .Required}}}{{end}}
|
||||
{{end}}
|
||||
{{if .HasBody}}req.Header.Add("Content-Type", contentType){{end}}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
{{end}}{{/* Range */}}
|
||||
`,
|
||||
"imports.tmpl": `// Package {{.PackageName}} provides primitives to interact the openapi HTTP API.
|
||||
//
|
||||
// Code generated by github.com/deepmap/oapi-codegen DO NOT EDIT.
|
||||
package {{.PackageName}}
|
||||
|
||||
{{if .Imports}}
|
||||
import (
|
||||
{{range .Imports}} {{ . }}
|
||||
{{end}})
|
||||
{{end}}
|
||||
`,
|
||||
"inline.tmpl": `// Base64 encoded, gzipped, json marshaled Swagger object
|
||||
var swaggerSpec = []string{
|
||||
{{range .}}
|
||||
"{{.}}",{{end}}
|
||||
}
|
||||
|
||||
// GetSwagger returns the Swagger specification corresponding to the generated code
|
||||
// in this file.
|
||||
func GetSwagger() (*openapi3.Swagger, error) {
|
||||
zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error base64 decoding spec: %s", err)
|
||||
}
|
||||
zr, err := gzip.NewReader(bytes.NewReader(zipped))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decompressing spec: %s", err)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
_, err = buf.ReadFrom(zr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decompressing spec: %s", err)
|
||||
}
|
||||
|
||||
swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(buf.Bytes())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error loading Swagger: %s", err)
|
||||
}
|
||||
return swagger, nil
|
||||
}
|
||||
`,
|
||||
"param-types.tmpl": `{{range .}}{{$opid := .OperationId}}
|
||||
{{range .TypeDefinitions}}
|
||||
// {{.TypeName}} defines parameters for {{$opid}}.
|
||||
type {{.TypeName}} {{.Schema.TypeDecl}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
`,
|
||||
"register.tmpl": `
|
||||
|
||||
// This is a simple interface which specifies echo.Route addition functions which
|
||||
// are present on both echo.Echo and echo.Group, since we want to allow using
|
||||
// either of them for path registration
|
||||
type EchoRouter interface {
|
||||
CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
|
||||
}
|
||||
|
||||
// RegisterHandlers adds each server route to the EchoRouter.
|
||||
func RegisterHandlers(router EchoRouter, si ServerInterface) {
|
||||
{{if .}}
|
||||
wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
}
|
||||
{{end}}
|
||||
{{range .}}router.{{.Method}}("{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}})
|
||||
{{end}}
|
||||
}
|
||||
`,
|
||||
"request-bodies.tmpl": `{{range .}}{{$opid := .OperationId}}
|
||||
{{range .Bodies}}
|
||||
// {{$opid}}RequestBody defines body for {{$opid}} for application/json ContentType.
|
||||
type {{$opid}}{{.NameTag}}RequestBody {{.TypeDef}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
`,
|
||||
"server-interface.tmpl": `// ServerInterface represents all server handlers.
|
||||
type ServerInterface interface {
|
||||
{{range .}}{{.SummaryAsComment }}
|
||||
// ({{.Method}} {{.Path}})
|
||||
{{.OperationId}}(ctx echo.Context{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}}) error
|
||||
{{end}}
|
||||
}
|
||||
`,
|
||||
"typedef.tmpl": `{{range .Types}}
|
||||
// {{.TypeName}} defines model for {{.JsonName}}.
|
||||
type {{.TypeName}} {{.Schema.TypeDecl}}
|
||||
{{- if gt (len .Schema.EnumValues) 0 }}
|
||||
// List of {{ .TypeName }}
|
||||
const (
|
||||
{{- $typeName := .TypeName }}
|
||||
{{- range $key, $value := .Schema.EnumValues }}
|
||||
{{ $typeName }}_{{ $key }} {{ $typeName }} = "{{ $value }}"
|
||||
{{- end }}
|
||||
)
|
||||
{{- end }}
|
||||
{{end}}
|
||||
`,
|
||||
"wrappers.tmpl": `// ServerInterfaceWrapper converts echo contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
}
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}// {{$opid}} converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx echo.Context) error {
|
||||
var err error
|
||||
{{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
|
||||
var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
|
||||
{{if .IsPassThrough}}
|
||||
{{$varName}} = ctx.Param("{{.ParamName}}")
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(ctx.Param("{{.ParamName}}")), &{{$varName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", ctx.Param("{{.ParamName}}"), &{{$varName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err))
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .SecurityDefinitions}}
|
||||
ctx.Set("{{.ProviderName}}.Scopes", {{toStringArray .Scopes}})
|
||||
{{end}}
|
||||
|
||||
{{if .RequiresParamObject}}
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params {{.OperationId}}Params
|
||||
{{range $paramIdx, $param := .QueryParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", ctx.QueryParams(), ¶ms.{{.GoName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err))
|
||||
}
|
||||
{{else}}
|
||||
if paramValue := ctx.QueryParam("{{.ParamName}}"); paramValue != "" {
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}paramValue
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var value {{.TypeDef}}
|
||||
err = json.Unmarshal([]byte(paramValue), &value)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Query argument {{.ParamName}} is required, but not found"))
|
||||
}{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if .HeaderParams}}
|
||||
headers := ctx.Request().Header
|
||||
{{range .HeaderParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} header parameter "{{.ParamName}}" -------------
|
||||
if valueList, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found {
|
||||
var {{.GoName}} {{.TypeDef}}
|
||||
n := len(valueList)
|
||||
if n != 1 {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for {{.ParamName}}, got %d", n))
|
||||
}
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", valueList[0], &{{.GoName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err))
|
||||
}
|
||||
{{end}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
|
||||
} {{if .Required}}else {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Header parameter {{.ParamName}} is required, but not found"))
|
||||
}{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .CookieParams}}
|
||||
if cookie, err := ctx.Cookie("{{.ParamName}}"); err == nil {
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}cookie.Value
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var value {{.TypeDef}}
|
||||
var decoded string
|
||||
decoded, err := url.QueryUnescape(cookie.Value)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unescaping cookie parameter '{{.ParamName}}'")
|
||||
}
|
||||
err = json.Unmarshal([]byte(decoded), &value)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
var value {{.TypeDef}}
|
||||
err = runtime.BindStyledParameter("simple",{{.Explode}}, "{{.ParamName}}", cookie.Value, &value)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err))
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Query argument {{.ParamName}} is required, but not found"))
|
||||
}{{end}}
|
||||
|
||||
{{end}}{{/* .CookieParams */}}
|
||||
|
||||
{{end}}{{/* .RequiresParamObject */}}
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.{{.OperationId}}(ctx{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
|
||||
return err
|
||||
}
|
||||
{{end}}
|
||||
`,
|
||||
}
|
||||
|
||||
// Parse parses declared templates.
|
||||
func Parse(t *template.Template) (*template.Template, error) {
|
||||
for name, s := range templates {
|
||||
var tmpl *template.Template
|
||||
if t == nil {
|
||||
t = template.New(name)
|
||||
}
|
||||
if name == t.Name() {
|
||||
tmpl = t
|
||||
} else {
|
||||
tmpl = t.New(name)
|
||||
}
|
||||
if _, err := tmpl.Parse(s); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
13
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/typedef.tmpl
generated
vendored
Normal file
13
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/typedef.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{{range .Types}}
|
||||
// {{.TypeName}} defines model for {{.JsonName}}.
|
||||
type {{.TypeName}} {{.Schema.TypeDecl}}
|
||||
{{- if gt (len .Schema.EnumValues) 0 }}
|
||||
// List of {{ .TypeName }}
|
||||
const (
|
||||
{{- $typeName := .TypeName }}
|
||||
{{- range $key, $value := .Schema.EnumValues }}
|
||||
{{ $typeName }}_{{ $key }} {{ $typeName }} = "{{ $value }}"
|
||||
{{- end }}
|
||||
)
|
||||
{{- end }}
|
||||
{{end}}
|
||||
128
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/wrappers.tmpl
generated
vendored
Normal file
128
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/templates/wrappers.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
// ServerInterfaceWrapper converts echo contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
}
|
||||
|
||||
{{range .}}{{$opid := .OperationId}}// {{$opid}} converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx echo.Context) error {
|
||||
var err error
|
||||
{{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
|
||||
var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
|
||||
{{if .IsPassThrough}}
|
||||
{{$varName}} = ctx.Param("{{.ParamName}}")
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(ctx.Param("{{.ParamName}}")), &{{$varName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", ctx.Param("{{.ParamName}}"), &{{$varName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err))
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .SecurityDefinitions}}
|
||||
ctx.Set("{{.ProviderName}}.Scopes", {{toStringArray .Scopes}})
|
||||
{{end}}
|
||||
|
||||
{{if .RequiresParamObject}}
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params {{.OperationId}}Params
|
||||
{{range $paramIdx, $param := .QueryParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", ctx.QueryParams(), ¶ms.{{.GoName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err))
|
||||
}
|
||||
{{else}}
|
||||
if paramValue := ctx.QueryParam("{{.ParamName}}"); paramValue != "" {
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}paramValue
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var value {{.TypeDef}}
|
||||
err = json.Unmarshal([]byte(paramValue), &value)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Query argument {{.ParamName}} is required, but not found"))
|
||||
}{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if .HeaderParams}}
|
||||
headers := ctx.Request().Header
|
||||
{{range .HeaderParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} header parameter "{{.ParamName}}" -------------
|
||||
if valueList, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found {
|
||||
var {{.GoName}} {{.TypeDef}}
|
||||
n := len(valueList)
|
||||
if n != 1 {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for {{.ParamName}}, got %d", n))
|
||||
}
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
}
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", valueList[0], &{{.GoName}})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err))
|
||||
}
|
||||
{{end}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
|
||||
} {{if .Required}}else {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Header parameter {{.ParamName}} is required, but not found"))
|
||||
}{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range .CookieParams}}
|
||||
if cookie, err := ctx.Cookie("{{.ParamName}}"); err == nil {
|
||||
{{if .IsPassThrough}}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}cookie.Value
|
||||
{{end}}
|
||||
{{if .IsJson}}
|
||||
var value {{.TypeDef}}
|
||||
var decoded string
|
||||
decoded, err := url.QueryUnescape(cookie.Value)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unescaping cookie parameter '{{.ParamName}}'")
|
||||
}
|
||||
err = json.Unmarshal([]byte(decoded), &value)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter '{{.ParamName}}' as JSON")
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
{{if .IsStyled}}
|
||||
var value {{.TypeDef}}
|
||||
err = runtime.BindStyledParameter("simple",{{.Explode}}, "{{.ParamName}}", cookie.Value, &value)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err))
|
||||
}
|
||||
params.{{.GoName}} = {{if not .Required}}&{{end}}value
|
||||
{{end}}
|
||||
}{{if .Required}} else {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Query argument {{.ParamName}} is required, but not found"))
|
||||
}{{end}}
|
||||
|
||||
{{end}}{{/* .CookieParams */}}
|
||||
|
||||
{{end}}{{/* .RequiresParamObject */}}
|
||||
// Invoke the callback with all the unmarshalled arguments
|
||||
err = w.Handler.{{.OperationId}}(ctx{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
|
||||
return err
|
||||
}
|
||||
{{end}}
|
||||
534
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/utils.go
generated
vendored
Normal file
534
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/utils.go
generated
vendored
Normal file
|
|
@ -0,0 +1,534 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
)
|
||||
|
||||
var pathParamRE *regexp.Regexp
|
||||
|
||||
func init() {
|
||||
pathParamRE = regexp.MustCompile("{[.;?]?([^{}*]+)\\*?}")
|
||||
}
|
||||
|
||||
// Uppercase the first character in a string. This assumes UTF-8, so we have
|
||||
// to be careful with unicode, don't treat it as a byte array.
|
||||
func UppercaseFirstCharacter(str string) string {
|
||||
if str == "" {
|
||||
return ""
|
||||
}
|
||||
runes := []rune(str)
|
||||
runes[0] = unicode.ToUpper(runes[0])
|
||||
return string(runes)
|
||||
}
|
||||
|
||||
// Same as above, except lower case
|
||||
func LowercaseFirstCharacter(str string) string {
|
||||
if str == "" {
|
||||
return ""
|
||||
}
|
||||
runes := []rune(str)
|
||||
runes[0] = unicode.ToLower(runes[0])
|
||||
return string(runes)
|
||||
}
|
||||
|
||||
// This function will convert query-arg style strings to CamelCase. We will
|
||||
// use `., -, +, :, ;, _, ~, ' ', (, ), {, }, [, ]` as valid delimiters for words.
|
||||
// So, "word.word-word+word:word;word_word~word word(word)word{word}[word]"
|
||||
// would be converted to WordWordWordWordWordWordWordWordWordWordWordWordWord
|
||||
func ToCamelCase(str string) string {
|
||||
separators := "-#@!$&=.+:;_~ (){}[]"
|
||||
s := strings.Trim(str, " ")
|
||||
|
||||
n := ""
|
||||
capNext := true
|
||||
for _, v := range s {
|
||||
if unicode.IsUpper(v) {
|
||||
n += string(v)
|
||||
}
|
||||
if unicode.IsDigit(v) {
|
||||
n += string(v)
|
||||
}
|
||||
if unicode.IsLower(v) {
|
||||
if capNext {
|
||||
n += strings.ToUpper(string(v))
|
||||
} else {
|
||||
n += string(v)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.ContainsRune(separators, v) {
|
||||
capNext = true
|
||||
} else {
|
||||
capNext = false
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// This function returns the keys of the given SchemaRef dictionary in sorted
|
||||
// order, since Golang scrambles dictionary keys
|
||||
func SortedSchemaKeys(dict map[string]*openapi3.SchemaRef) []string {
|
||||
keys := make([]string, len(dict))
|
||||
i := 0
|
||||
for key := range dict {
|
||||
keys[i] = key
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// This function is the same as above, except it sorts the keys for a Paths
|
||||
// dictionary.
|
||||
func SortedPathsKeys(dict openapi3.Paths) []string {
|
||||
keys := make([]string, len(dict))
|
||||
i := 0
|
||||
for key := range dict {
|
||||
keys[i] = key
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// This function returns Operation dictionary keys in sorted order
|
||||
func SortedOperationsKeys(dict map[string]*openapi3.Operation) []string {
|
||||
keys := make([]string, len(dict))
|
||||
i := 0
|
||||
for key := range dict {
|
||||
keys[i] = key
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// This function returns Responses dictionary keys in sorted order
|
||||
func SortedResponsesKeys(dict openapi3.Responses) []string {
|
||||
keys := make([]string, len(dict))
|
||||
i := 0
|
||||
for key := range dict {
|
||||
keys[i] = key
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// This returns Content dictionary keys in sorted order
|
||||
func SortedContentKeys(dict openapi3.Content) []string {
|
||||
keys := make([]string, len(dict))
|
||||
i := 0
|
||||
for key := range dict {
|
||||
keys[i] = key
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// This returns string map keys in sorted order
|
||||
func SortedStringKeys(dict map[string]string) []string {
|
||||
keys := make([]string, len(dict))
|
||||
i := 0
|
||||
for key := range dict {
|
||||
keys[i] = key
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// This returns sorted keys for a ParameterRef dict
|
||||
func SortedParameterKeys(dict map[string]*openapi3.ParameterRef) []string {
|
||||
keys := make([]string, len(dict))
|
||||
i := 0
|
||||
for key := range dict {
|
||||
keys[i] = key
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
func SortedRequestBodyKeys(dict map[string]*openapi3.RequestBodyRef) []string {
|
||||
keys := make([]string, len(dict))
|
||||
i := 0
|
||||
for key := range dict {
|
||||
keys[i] = key
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// This function checks whether the specified string is present in an array
|
||||
// of strings
|
||||
func StringInArray(str string, array []string) bool {
|
||||
for _, elt := range array {
|
||||
if elt == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// This function takes a $ref value and converts it to a Go typename.
|
||||
// #/components/schemas/Foo -> Foo
|
||||
// #/components/parameters/Bar -> Bar
|
||||
// #/components/responses/Baz -> Baz
|
||||
// Remote components (document.json#/Foo) are supported if they present in --import-mapping
|
||||
// URL components (http://deepmap.com/schemas/document.json#Foo) are supported if they present in --import-mapping
|
||||
//
|
||||
func RefPathToGoType(refPath string) (string, error) {
|
||||
if refPath[0] == '#' {
|
||||
pathParts := strings.Split(refPath, "/")
|
||||
if depth := len(pathParts); depth != 4 {
|
||||
return "", fmt.Errorf("Parameter nesting is deeper than supported: %s has %d", refPath, depth)
|
||||
}
|
||||
return SchemaNameToTypeName(pathParts[3]), nil
|
||||
}
|
||||
pathParts := strings.Split(refPath, "#")
|
||||
if len(pathParts) != 2 {
|
||||
return "", fmt.Errorf("unsupported reference: %s", refPath)
|
||||
}
|
||||
remoteComponent, flatComponent := pathParts[0], pathParts[1]
|
||||
if goImport, ok := importMapping[remoteComponent]; !ok {
|
||||
return "", fmt.Errorf("unrecognized external reference '%s'; please provide the known import for this reference using option --import-mapping", remoteComponent)
|
||||
} else {
|
||||
goType, err := RefPathToGoType("#" + flatComponent)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", goImport.alias, goType), nil
|
||||
}
|
||||
}
|
||||
|
||||
// This function converts a swagger style path URI with parameters to a
|
||||
// Echo compatible path URI. We need to replace all of Swagger parameters with
|
||||
// ":param". Valid input parameters are:
|
||||
// {param}
|
||||
// {param*}
|
||||
// {.param}
|
||||
// {.param*}
|
||||
// {;param}
|
||||
// {;param*}
|
||||
// {?param}
|
||||
// {?param*}
|
||||
func SwaggerUriToEchoUri(uri string) string {
|
||||
return pathParamRE.ReplaceAllString(uri, ":$1")
|
||||
}
|
||||
|
||||
// This function converts a swagger style path URI with parameters to a
|
||||
// Chi compatible path URI. We need to replace all of Swagger parameters with
|
||||
// "{param}". Valid input parameters are:
|
||||
// {param}
|
||||
// {param*}
|
||||
// {.param}
|
||||
// {.param*}
|
||||
// {;param}
|
||||
// {;param*}
|
||||
// {?param}
|
||||
// {?param*}
|
||||
func SwaggerUriToChiUri(uri string) string {
|
||||
return pathParamRE.ReplaceAllString(uri, "{$1}")
|
||||
}
|
||||
|
||||
// Returns the argument names, in order, in a given URI string, so for
|
||||
// /path/{param1}/{.param2*}/{?param3}, it would return param1, param2, param3
|
||||
func OrderedParamsFromUri(uri string) []string {
|
||||
matches := pathParamRE.FindAllStringSubmatch(uri, -1)
|
||||
result := make([]string, len(matches))
|
||||
for i, m := range matches {
|
||||
result[i] = m[1]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Replaces path parameters with %s
|
||||
func ReplacePathParamsWithStr(uri string) string {
|
||||
return pathParamRE.ReplaceAllString(uri, "%s")
|
||||
}
|
||||
|
||||
// Reorders the given parameter definitions to match those in the path URI.
|
||||
func SortParamsByPath(path string, in []ParameterDefinition) ([]ParameterDefinition, error) {
|
||||
pathParams := OrderedParamsFromUri(path)
|
||||
n := len(in)
|
||||
if len(pathParams) != n {
|
||||
return nil, fmt.Errorf("path '%s' has %d positional parameters, but spec has %d declared",
|
||||
path, len(pathParams), n)
|
||||
}
|
||||
out := make([]ParameterDefinition, len(in))
|
||||
for i, name := range pathParams {
|
||||
p := ParameterDefinitions(in).FindByName(name)
|
||||
if p == nil {
|
||||
return nil, fmt.Errorf("path '%s' refers to parameter '%s', which doesn't exist in specification",
|
||||
path, name)
|
||||
}
|
||||
out[i] = *p
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Returns whether the given string is a go keyword
|
||||
func IsGoKeyword(str string) bool {
|
||||
keywords := []string{
|
||||
"break",
|
||||
"case",
|
||||
"chan",
|
||||
"const",
|
||||
"continue",
|
||||
"default",
|
||||
"defer",
|
||||
"else",
|
||||
"fallthrough",
|
||||
"for",
|
||||
"func",
|
||||
"go",
|
||||
"goto",
|
||||
"if",
|
||||
"import",
|
||||
"interface",
|
||||
"map",
|
||||
"package",
|
||||
"range",
|
||||
"return",
|
||||
"select",
|
||||
"struct",
|
||||
"switch",
|
||||
"type",
|
||||
"var",
|
||||
}
|
||||
|
||||
for _, k := range keywords {
|
||||
if k == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsPredeclaredGoIdentifier returns whether the given string
|
||||
// is a predefined go indentifier.
|
||||
//
|
||||
// See https://golang.org/ref/spec#Predeclared_identifiers
|
||||
func IsPredeclaredGoIdentifier(str string) bool {
|
||||
predeclaredIdentifiers := []string{
|
||||
// Types
|
||||
"bool",
|
||||
"byte",
|
||||
"complex64",
|
||||
"complex128",
|
||||
"error",
|
||||
"float32",
|
||||
"float64",
|
||||
"int",
|
||||
"int8",
|
||||
"int16",
|
||||
"int32",
|
||||
"int64",
|
||||
"rune",
|
||||
"string",
|
||||
"uint",
|
||||
"uint8",
|
||||
"uint16",
|
||||
"uint32",
|
||||
"uint64",
|
||||
"uintptr",
|
||||
// Constants
|
||||
"true",
|
||||
"false",
|
||||
"iota",
|
||||
// Zero value
|
||||
"nil",
|
||||
// Functions
|
||||
"append",
|
||||
"cap",
|
||||
"close",
|
||||
"complex",
|
||||
"copy",
|
||||
"delete",
|
||||
"imag",
|
||||
"len",
|
||||
"make",
|
||||
"new",
|
||||
"panic",
|
||||
"print",
|
||||
"println",
|
||||
"real",
|
||||
"recover",
|
||||
}
|
||||
|
||||
for _, k := range predeclaredIdentifiers {
|
||||
if k == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// IsGoIdentity checks if the given string can be used as an identity
|
||||
// in the generated code like a type name or constant name.
|
||||
//
|
||||
// See https://golang.org/ref/spec#Identifiers
|
||||
func IsGoIdentity(str string) bool {
|
||||
for i, c := range str {
|
||||
if !isValidRuneForGoID(i, c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return IsGoKeyword(str)
|
||||
}
|
||||
|
||||
func isValidRuneForGoID(index int, char rune) bool {
|
||||
if index == 0 && unicode.IsNumber(char) {
|
||||
return false
|
||||
}
|
||||
|
||||
return unicode.IsLetter(char) || char == '_' || unicode.IsNumber(char)
|
||||
}
|
||||
|
||||
// IsValidGoIdentity checks if the given string can be used as a
|
||||
// name of variable, constant, or type.
|
||||
func IsValidGoIdentity(str string) bool {
|
||||
if IsGoIdentity(str) {
|
||||
return false
|
||||
}
|
||||
|
||||
return !IsPredeclaredGoIdentifier(str)
|
||||
}
|
||||
|
||||
// SanitizeGoIdentity deletes and replaces the illegal runes in the given
|
||||
// string to use the string as a valid identity.
|
||||
func SanitizeGoIdentity(str string) string {
|
||||
sanitized := []rune(str)
|
||||
|
||||
for i, c := range sanitized {
|
||||
if !isValidRuneForGoID(i, c) {
|
||||
sanitized[i] = '_'
|
||||
} else {
|
||||
sanitized[i] = c
|
||||
}
|
||||
}
|
||||
|
||||
str = string(sanitized)
|
||||
|
||||
if IsGoKeyword(str) || IsPredeclaredGoIdentifier(str) {
|
||||
str = "_" + str
|
||||
}
|
||||
|
||||
if !IsValidGoIdentity(str) {
|
||||
panic("here is a bug")
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
// SanitizeEnumNames fixes illegal chars in the enum names
|
||||
// and removes duplicates
|
||||
func SanitizeEnumNames(enumNames []string) map[string]string {
|
||||
dupCheck := make(map[string]int, len(enumNames))
|
||||
deDup := make([]string, 0, len(enumNames))
|
||||
|
||||
for _, n := range enumNames {
|
||||
if _, dup := dupCheck[n]; !dup {
|
||||
deDup = append(deDup, n)
|
||||
}
|
||||
|
||||
dupCheck[n] = 0
|
||||
}
|
||||
|
||||
dupCheck = make(map[string]int, len(deDup))
|
||||
sanitizedDeDup := make(map[string]string, len(deDup))
|
||||
|
||||
for _, n := range deDup {
|
||||
sanitized := SanitizeGoIdentity(n)
|
||||
|
||||
if _, dup := dupCheck[sanitized]; !dup {
|
||||
sanitizedDeDup[sanitized] = n
|
||||
dupCheck[sanitized]++
|
||||
} else {
|
||||
sanitizedDeDup[sanitized+strconv.Itoa(dupCheck[sanitized])] = n
|
||||
}
|
||||
}
|
||||
|
||||
return sanitizedDeDup
|
||||
}
|
||||
|
||||
// Converts a Schema name to a valid Go type name. It converts to camel case, and makes sure the name is
|
||||
// valid in Go
|
||||
func SchemaNameToTypeName(name string) string {
|
||||
name = ToCamelCase(name)
|
||||
// Prepend "N" to schemas starting with a number
|
||||
if name != "" && unicode.IsDigit([]rune(name)[0]) {
|
||||
name = "N" + name
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// According to the spec, additionalProperties may be true, false, or a
|
||||
// schema. If not present, true is implied. If it's a schema, true is implied.
|
||||
// If it's false, no additional properties are allowed. We're going to act a little
|
||||
// differently, in that if you want additionalProperties code to be generated,
|
||||
// you must specify an additionalProperties type
|
||||
// If additionalProperties it true/false, this field will be non-nil.
|
||||
func SchemaHasAdditionalProperties(schema *openapi3.Schema) bool {
|
||||
if schema.AdditionalPropertiesAllowed != nil {
|
||||
return *schema.AdditionalPropertiesAllowed
|
||||
}
|
||||
if schema.AdditionalProperties != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// This converts a path, like Object/field1/nestedField into a go
|
||||
// type name.
|
||||
func PathToTypeName(path []string) string {
|
||||
for i, p := range path {
|
||||
path[i] = ToCamelCase(p)
|
||||
}
|
||||
return strings.Join(path, "_")
|
||||
}
|
||||
|
||||
// StringToGoComment renders a possible multi-line string as a valid Go-Comment.
|
||||
// Each line is prefixed as a comment.
|
||||
func StringToGoComment(in string) string {
|
||||
// Normalize newlines from Windows/Mac to Linux
|
||||
in = strings.Replace(in, "\r\n", "\n", -1)
|
||||
in = strings.Replace(in, "\r", "\n", -1)
|
||||
|
||||
// Add comment to each line
|
||||
var lines []string
|
||||
for _, line := range strings.Split(in, "\n") {
|
||||
lines = append(lines, fmt.Sprintf("// %s", line))
|
||||
}
|
||||
in = strings.Join(lines, "\n")
|
||||
|
||||
// in case we have a multiline string which ends with \n, we would generate
|
||||
// empty-line-comments, like `// `. Therefore remove this line comment.
|
||||
in = strings.TrimSuffix(in, "\n// ")
|
||||
return in
|
||||
}
|
||||
60
vendor/github.com/deepmap/oapi-codegen/pkg/util/inputmapping.go
generated
vendored
Normal file
60
vendor/github.com/deepmap/oapi-codegen/pkg/util/inputmapping.go
generated
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// The input mapping is experessed on the command line as `key1:value1,key2:value2,...`
|
||||
// We parse it here, but need to keep in mind that keys or values may contain
|
||||
// commas and colons. We will allow escaping those using double quotes, so
|
||||
// when passing in "key1":"value1", we will not look inside the quoted sections.
|
||||
func ParseCommandlineMap(src string) (map[string]string, error) {
|
||||
result := make(map[string]string)
|
||||
tuples := splitString(src, ',')
|
||||
for _, t := range tuples {
|
||||
kv := splitString(t, ':')
|
||||
if len(kv) != 2 {
|
||||
return nil, fmt.Errorf("expected key:value, got :%s", t)
|
||||
}
|
||||
key := strings.TrimLeft(kv[0], `"`)
|
||||
key = strings.TrimRight(key, `"`)
|
||||
|
||||
value := strings.TrimLeft(kv[1], `"`)
|
||||
value = strings.TrimRight(value, `"`)
|
||||
|
||||
result[key] = value
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// This function splits a string along the specifed separator, but it
|
||||
// ignores anything between double quotes for splitting. We do simple
|
||||
// inside/outside quote counting. Quotes are not stripped from output.
|
||||
func splitString(s string, sep rune) ([]string) {
|
||||
const escapeChar rune = '"'
|
||||
|
||||
var parts []string
|
||||
var part string
|
||||
inQuotes := false
|
||||
|
||||
for _, c := range s {
|
||||
if c == escapeChar{
|
||||
if inQuotes {
|
||||
inQuotes = false
|
||||
} else {
|
||||
inQuotes = true
|
||||
}
|
||||
}
|
||||
|
||||
// If we've gotten the separator rune, consider the previous part
|
||||
// complete, but only if we're outside of quoted sections
|
||||
if c == sep && !inQuotes {
|
||||
parts = append(parts, part)
|
||||
part = ""
|
||||
continue
|
||||
}
|
||||
part = part + string(c)
|
||||
}
|
||||
return append(parts, part)
|
||||
}
|
||||
20
vendor/github.com/deepmap/oapi-codegen/pkg/util/loader.go
generated
vendored
Normal file
20
vendor/github.com/deepmap/oapi-codegen/pkg/util/loader.go
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
)
|
||||
|
||||
func LoadSwagger(filePath string) (swagger *openapi3.Swagger, err error) {
|
||||
|
||||
loader := openapi3.NewSwaggerLoader()
|
||||
loader.IsExternalRefsAllowed = true
|
||||
|
||||
u, err := url.Parse(filePath)
|
||||
if err == nil && u.Scheme != "" && u.Host != "" {
|
||||
return loader.LoadSwaggerFromURI(u)
|
||||
} else {
|
||||
return loader.LoadSwaggerFromFile(filePath)
|
||||
}
|
||||
}
|
||||
21
vendor/github.com/getkin/kin-openapi/LICENSE
generated
vendored
Normal file
21
vendor/github.com/getkin/kin-openapi/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017-2018 the project authors.
|
||||
|
||||
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.
|
||||
2
vendor/github.com/getkin/kin-openapi/jsoninfo/doc.go
generated
vendored
Normal file
2
vendor/github.com/getkin/kin-openapi/jsoninfo/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
// Package jsoninfo provides information and functions for marshalling/unmarshalling JSON.
|
||||
package jsoninfo
|
||||
122
vendor/github.com/getkin/kin-openapi/jsoninfo/field_info.go
generated
vendored
Normal file
122
vendor/github.com/getkin/kin-openapi/jsoninfo/field_info.go
generated
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
package jsoninfo
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// FieldInfo contains information about JSON serialization of a field.
|
||||
type FieldInfo struct {
|
||||
MultipleFields bool // Whether multiple Go fields share this JSON name
|
||||
HasJSONTag bool
|
||||
TypeIsMarshaller bool
|
||||
TypeIsUnmarshaller bool
|
||||
JSONOmitEmpty bool
|
||||
JSONString bool
|
||||
Index []int
|
||||
Type reflect.Type
|
||||
JSONName string
|
||||
}
|
||||
|
||||
func AppendFields(fields []FieldInfo, parentIndex []int, t reflect.Type) []FieldInfo {
|
||||
// For each field
|
||||
numField := t.NumField()
|
||||
iteration:
|
||||
for i := 0; i < numField; i++ {
|
||||
f := t.Field(i)
|
||||
index := make([]int, 0, len(parentIndex)+1)
|
||||
index = append(index, parentIndex...)
|
||||
index = append(index, i)
|
||||
|
||||
// See whether this is an embedded field
|
||||
if f.Anonymous {
|
||||
if f.Tag.Get("json") == "-" {
|
||||
continue
|
||||
}
|
||||
fields = AppendFields(fields, index, f.Type)
|
||||
continue iteration
|
||||
}
|
||||
|
||||
// Ignore certain types
|
||||
switch f.Type.Kind() {
|
||||
case reflect.Func, reflect.Chan:
|
||||
continue iteration
|
||||
}
|
||||
|
||||
// Is it a private (lowercase) field?
|
||||
firstRune, _ := utf8.DecodeRuneInString(f.Name)
|
||||
if unicode.IsLower(firstRune) {
|
||||
continue iteration
|
||||
}
|
||||
|
||||
// Declare a field
|
||||
field := FieldInfo{
|
||||
Index: index,
|
||||
Type: f.Type,
|
||||
JSONName: f.Name,
|
||||
}
|
||||
|
||||
// Read "json" tag
|
||||
jsonTag := f.Tag.Get("json")
|
||||
|
||||
// Read our custom "multijson" tag that
|
||||
// allows multiple fields with the same name.
|
||||
if v := f.Tag.Get("multijson"); len(v) > 0 {
|
||||
field.MultipleFields = true
|
||||
jsonTag = v
|
||||
}
|
||||
|
||||
// Handle "-"
|
||||
if jsonTag == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Parse the tag
|
||||
if len(jsonTag) > 0 {
|
||||
field.HasJSONTag = true
|
||||
for i, part := range strings.Split(jsonTag, ",") {
|
||||
if i == 0 {
|
||||
if len(part) > 0 {
|
||||
field.JSONName = part
|
||||
}
|
||||
} else {
|
||||
switch part {
|
||||
case "omitempty":
|
||||
field.JSONOmitEmpty = true
|
||||
case "string":
|
||||
field.JSONString = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := field.Type.MethodByName("MarshalJSON"); ok {
|
||||
field.TypeIsMarshaller = true
|
||||
}
|
||||
if _, ok := field.Type.MethodByName("UnmarshalJSON"); ok {
|
||||
field.TypeIsUnmarshaller = true
|
||||
}
|
||||
|
||||
// Field is done
|
||||
fields = append(fields, field)
|
||||
}
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
type sortableFieldInfos []FieldInfo
|
||||
|
||||
func (list sortableFieldInfos) Len() int {
|
||||
return len(list)
|
||||
}
|
||||
|
||||
func (list sortableFieldInfos) Less(i, j int) bool {
|
||||
return list[i].JSONName < list[j].JSONName
|
||||
}
|
||||
|
||||
func (list sortableFieldInfos) Swap(i, j int) {
|
||||
a, b := list[i], list[j]
|
||||
list[i], list[j] = b, a
|
||||
}
|
||||
162
vendor/github.com/getkin/kin-openapi/jsoninfo/marshal.go
generated
vendored
Normal file
162
vendor/github.com/getkin/kin-openapi/jsoninfo/marshal.go
generated
vendored
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
package jsoninfo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// MarshalStrictStruct function:
|
||||
// * Marshals struct fields, ignoring MarshalJSON() and fields without 'json' tag.
|
||||
// * Correctly handles StrictStruct semantics.
|
||||
func MarshalStrictStruct(value StrictStruct) ([]byte, error) {
|
||||
encoder := NewObjectEncoder()
|
||||
if err := value.EncodeWith(encoder, value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encoder.Bytes()
|
||||
}
|
||||
|
||||
type ObjectEncoder struct {
|
||||
result map[string]json.RawMessage
|
||||
}
|
||||
|
||||
func NewObjectEncoder() *ObjectEncoder {
|
||||
return &ObjectEncoder{
|
||||
result: make(map[string]json.RawMessage, 8),
|
||||
}
|
||||
}
|
||||
|
||||
// Bytes returns the result of encoding.
|
||||
func (encoder *ObjectEncoder) Bytes() ([]byte, error) {
|
||||
return json.Marshal(encoder.result)
|
||||
}
|
||||
|
||||
// EncodeExtension adds a key/value to the current JSON object.
|
||||
func (encoder *ObjectEncoder) EncodeExtension(key string, value interface{}) error {
|
||||
data, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
encoder.result[key] = data
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeExtensionMap adds all properties to the result.
|
||||
func (encoder *ObjectEncoder) EncodeExtensionMap(value map[string]json.RawMessage) error {
|
||||
if value != nil {
|
||||
result := encoder.result
|
||||
for k, v := range value {
|
||||
result[k] = v
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (encoder *ObjectEncoder) EncodeStructFieldsAndExtensions(value interface{}) error {
|
||||
reflection := reflect.ValueOf(value)
|
||||
|
||||
// Follow "encoding/json" semantics
|
||||
if reflection.Kind() != reflect.Ptr {
|
||||
// Panic because this is a clear programming error
|
||||
panic(fmt.Errorf("Value %s is not a pointer", reflection.Type().String()))
|
||||
}
|
||||
if reflection.IsNil() {
|
||||
// Panic because this is a clear programming error
|
||||
panic(fmt.Errorf("Value %s is nil", reflection.Type().String()))
|
||||
}
|
||||
|
||||
// Take the element
|
||||
reflection = reflection.Elem()
|
||||
|
||||
// Obtain typeInfo
|
||||
typeInfo := GetTypeInfo(reflection.Type())
|
||||
|
||||
// Declare result
|
||||
result := encoder.result
|
||||
|
||||
// Supported fields
|
||||
iteration:
|
||||
for _, field := range typeInfo.Fields {
|
||||
// Fields without JSON tag are ignored
|
||||
if !field.HasJSONTag {
|
||||
continue
|
||||
}
|
||||
|
||||
// Marshal
|
||||
fieldValue := reflection.FieldByIndex(field.Index)
|
||||
if v, ok := fieldValue.Interface().(json.Marshaler); ok {
|
||||
if fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() {
|
||||
if field.JSONOmitEmpty {
|
||||
continue iteration
|
||||
}
|
||||
result[field.JSONName] = []byte("null")
|
||||
continue
|
||||
}
|
||||
fieldData, err := v.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result[field.JSONName] = fieldData
|
||||
continue
|
||||
}
|
||||
switch fieldValue.Kind() {
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
if fieldValue.IsNil() {
|
||||
if field.JSONOmitEmpty {
|
||||
continue iteration
|
||||
}
|
||||
result[field.JSONName] = []byte("null")
|
||||
continue
|
||||
}
|
||||
case reflect.Struct:
|
||||
case reflect.Map:
|
||||
if field.JSONOmitEmpty && (fieldValue.IsNil() || fieldValue.Len() == 0) {
|
||||
continue iteration
|
||||
}
|
||||
case reflect.Slice:
|
||||
if field.JSONOmitEmpty && fieldValue.Len() == 0 {
|
||||
continue iteration
|
||||
}
|
||||
case reflect.Bool:
|
||||
x := fieldValue.Bool()
|
||||
if field.JSONOmitEmpty && !x {
|
||||
continue iteration
|
||||
}
|
||||
s := "false"
|
||||
if x {
|
||||
s = "true"
|
||||
}
|
||||
result[field.JSONName] = []byte(s)
|
||||
continue iteration
|
||||
case reflect.Int64, reflect.Int, reflect.Int32:
|
||||
if field.JSONOmitEmpty && fieldValue.Int() == 0 {
|
||||
continue iteration
|
||||
}
|
||||
case reflect.Uint64, reflect.Uint, reflect.Uint32:
|
||||
if field.JSONOmitEmpty && fieldValue.Uint() == 0 {
|
||||
continue iteration
|
||||
}
|
||||
case reflect.Float64:
|
||||
if field.JSONOmitEmpty && fieldValue.Float() == 0.0 {
|
||||
continue iteration
|
||||
}
|
||||
case reflect.String:
|
||||
if field.JSONOmitEmpty && len(fieldValue.String()) == 0 {
|
||||
continue iteration
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("Field '%s' has unsupported type %s", field.JSONName, field.Type.String()))
|
||||
}
|
||||
|
||||
// No special treament is needed
|
||||
// Use plain old "encoding/json".Marshal
|
||||
fieldData, err := json.Marshal(fieldValue.Addr().Interface())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result[field.JSONName] = fieldData
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
30
vendor/github.com/getkin/kin-openapi/jsoninfo/marshal_ref.go
generated
vendored
Normal file
30
vendor/github.com/getkin/kin-openapi/jsoninfo/marshal_ref.go
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
package jsoninfo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func MarshalRef(value string, otherwise interface{}) ([]byte, error) {
|
||||
if len(value) > 0 {
|
||||
return json.Marshal(&refProps{
|
||||
Ref: value,
|
||||
})
|
||||
}
|
||||
return json.Marshal(otherwise)
|
||||
}
|
||||
|
||||
func UnmarshalRef(data []byte, destRef *string, destOtherwise interface{}) error {
|
||||
refProps := &refProps{}
|
||||
if err := json.Unmarshal(data, refProps); err == nil {
|
||||
ref := refProps.Ref
|
||||
if len(ref) > 0 {
|
||||
*destRef = ref
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return json.Unmarshal(data, destOtherwise)
|
||||
}
|
||||
|
||||
type refProps struct {
|
||||
Ref string `json:"$ref,omitempty"`
|
||||
}
|
||||
6
vendor/github.com/getkin/kin-openapi/jsoninfo/strict_struct.go
generated
vendored
Normal file
6
vendor/github.com/getkin/kin-openapi/jsoninfo/strict_struct.go
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
package jsoninfo
|
||||
|
||||
type StrictStruct interface {
|
||||
EncodeWith(encoder *ObjectEncoder, value interface{}) error
|
||||
DecodeWith(decoder *ObjectDecoder, value interface{}) error
|
||||
}
|
||||
68
vendor/github.com/getkin/kin-openapi/jsoninfo/type_info.go
generated
vendored
Normal file
68
vendor/github.com/getkin/kin-openapi/jsoninfo/type_info.go
generated
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package jsoninfo
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
typeInfos = map[reflect.Type]*TypeInfo{}
|
||||
typeInfosMutex sync.RWMutex
|
||||
)
|
||||
|
||||
// TypeInfo contains information about JSON serialization of a type
|
||||
type TypeInfo struct {
|
||||
Type reflect.Type
|
||||
Fields []FieldInfo
|
||||
}
|
||||
|
||||
func GetTypeInfoForValue(value interface{}) *TypeInfo {
|
||||
return GetTypeInfo(reflect.TypeOf(value))
|
||||
}
|
||||
|
||||
// GetTypeInfo returns TypeInfo for the given type.
|
||||
func GetTypeInfo(t reflect.Type) *TypeInfo {
|
||||
for t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
typeInfosMutex.RLock()
|
||||
typeInfo, exists := typeInfos[t]
|
||||
typeInfosMutex.RUnlock()
|
||||
if exists {
|
||||
return typeInfo
|
||||
}
|
||||
if t.Kind() != reflect.Struct {
|
||||
typeInfo = &TypeInfo{
|
||||
Type: t,
|
||||
}
|
||||
} else {
|
||||
// Allocate
|
||||
typeInfo = &TypeInfo{
|
||||
Type: t,
|
||||
Fields: make([]FieldInfo, 0, 16),
|
||||
}
|
||||
|
||||
// Add fields
|
||||
typeInfo.Fields = AppendFields(nil, nil, t)
|
||||
|
||||
// Sort fields
|
||||
sort.Sort(sortableFieldInfos(typeInfo.Fields))
|
||||
}
|
||||
|
||||
// Publish
|
||||
typeInfosMutex.Lock()
|
||||
typeInfos[t] = typeInfo
|
||||
typeInfosMutex.Unlock()
|
||||
return typeInfo
|
||||
}
|
||||
|
||||
// FieldNames returns all field names
|
||||
func (typeInfo *TypeInfo) FieldNames() []string {
|
||||
fields := typeInfo.Fields
|
||||
names := make([]string, 0, len(fields))
|
||||
for _, field := range fields {
|
||||
names = append(names, field.JSONName)
|
||||
}
|
||||
return names
|
||||
}
|
||||
121
vendor/github.com/getkin/kin-openapi/jsoninfo/unmarshal.go
generated
vendored
Normal file
121
vendor/github.com/getkin/kin-openapi/jsoninfo/unmarshal.go
generated
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
package jsoninfo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// UnmarshalStrictStruct function:
|
||||
// * Unmarshals struct fields, ignoring UnmarshalJSON(...) and fields without 'json' tag.
|
||||
// * Correctly handles StrictStruct
|
||||
func UnmarshalStrictStruct(data []byte, value StrictStruct) error {
|
||||
decoder, err := NewObjectDecoder(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return value.DecodeWith(decoder, value)
|
||||
}
|
||||
|
||||
type ObjectDecoder struct {
|
||||
Data []byte
|
||||
remainingFields map[string]json.RawMessage
|
||||
}
|
||||
|
||||
func NewObjectDecoder(data []byte) (*ObjectDecoder, error) {
|
||||
var remainingFields map[string]json.RawMessage
|
||||
if err := json.Unmarshal(data, &remainingFields); err != nil {
|
||||
return nil, fmt.Errorf("Failed to unmarshal extension properties: %v\nInput: %s", err, data)
|
||||
}
|
||||
return &ObjectDecoder{
|
||||
Data: data,
|
||||
remainingFields: remainingFields,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DecodeExtensionMap returns all properties that were not decoded previously.
|
||||
func (decoder *ObjectDecoder) DecodeExtensionMap() map[string]json.RawMessage {
|
||||
return decoder.remainingFields
|
||||
}
|
||||
|
||||
func (decoder *ObjectDecoder) DecodeStructFieldsAndExtensions(value interface{}) error {
|
||||
reflection := reflect.ValueOf(value)
|
||||
if reflection.Kind() != reflect.Ptr {
|
||||
panic(fmt.Errorf("Value %T is not a pointer", value))
|
||||
}
|
||||
if reflection.IsNil() {
|
||||
panic(fmt.Errorf("Value %T is nil", value))
|
||||
}
|
||||
reflection = reflection.Elem()
|
||||
for (reflection.Kind() == reflect.Interface || reflection.Kind() == reflect.Ptr) && !reflection.IsNil() {
|
||||
reflection = reflection.Elem()
|
||||
}
|
||||
reflectionType := reflection.Type()
|
||||
if reflectionType.Kind() != reflect.Struct {
|
||||
panic(fmt.Errorf("Value %T is not a struct", value))
|
||||
}
|
||||
typeInfo := GetTypeInfo(reflectionType)
|
||||
|
||||
// Supported fields
|
||||
fields := typeInfo.Fields
|
||||
remainingFields := decoder.remainingFields
|
||||
for fieldIndex, field := range fields {
|
||||
// Fields without JSON tag are ignored
|
||||
if !field.HasJSONTag {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get data
|
||||
fieldData, exists := remainingFields[field.JSONName]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
// Unmarshal
|
||||
if field.TypeIsUnmarshaller {
|
||||
fieldType := field.Type
|
||||
isPtr := false
|
||||
if fieldType.Kind() == reflect.Ptr {
|
||||
fieldType = fieldType.Elem()
|
||||
isPtr = true
|
||||
}
|
||||
fieldValue := reflect.New(fieldType)
|
||||
if err := fieldValue.Interface().(json.Unmarshaler).UnmarshalJSON(fieldData); err != nil {
|
||||
if field.MultipleFields {
|
||||
i := fieldIndex + 1
|
||||
if i < len(fields) && fields[i].JSONName == field.JSONName {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("Error while unmarshalling property '%s' (%s): %v",
|
||||
field.JSONName, fieldValue.Type().String(), err)
|
||||
}
|
||||
if !isPtr {
|
||||
fieldValue = fieldValue.Elem()
|
||||
}
|
||||
reflection.FieldByIndex(field.Index).Set(fieldValue)
|
||||
|
||||
// Remove the field from remaining fields
|
||||
delete(remainingFields, field.JSONName)
|
||||
} else {
|
||||
fieldPtr := reflection.FieldByIndex(field.Index)
|
||||
if fieldPtr.Kind() != reflect.Ptr || fieldPtr.IsNil() {
|
||||
fieldPtr = fieldPtr.Addr()
|
||||
}
|
||||
if err := json.Unmarshal(fieldData, fieldPtr.Interface()); err != nil {
|
||||
if field.MultipleFields {
|
||||
i := fieldIndex + 1
|
||||
if i < len(fields) && fields[i].JSONName == field.JSONName {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("Error while unmarshalling property '%s' (%s): %v",
|
||||
field.JSONName, fieldPtr.Type().String(), err)
|
||||
}
|
||||
|
||||
// Remove the field from remaining fields
|
||||
delete(remainingFields, field.JSONName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
45
vendor/github.com/getkin/kin-openapi/jsoninfo/unsupported_properties_error.go
generated
vendored
Normal file
45
vendor/github.com/getkin/kin-openapi/jsoninfo/unsupported_properties_error.go
generated
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package jsoninfo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// UnsupportedPropertiesError is a helper for extensions that want to refuse
|
||||
// unsupported JSON object properties.
|
||||
//
|
||||
// It produces a helpful error message.
|
||||
type UnsupportedPropertiesError struct {
|
||||
Value interface{}
|
||||
UnsupportedProperties map[string]json.RawMessage
|
||||
}
|
||||
|
||||
func NewUnsupportedPropertiesError(v interface{}, m map[string]json.RawMessage) error {
|
||||
return &UnsupportedPropertiesError{
|
||||
Value: v,
|
||||
UnsupportedProperties: m,
|
||||
}
|
||||
}
|
||||
|
||||
func (err *UnsupportedPropertiesError) Error() string {
|
||||
m := err.UnsupportedProperties
|
||||
typeInfo := GetTypeInfoForValue(err.Value)
|
||||
if m == nil || typeInfo == nil {
|
||||
return "Invalid UnsupportedPropertiesError"
|
||||
}
|
||||
keys := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
supported := typeInfo.FieldNames()
|
||||
if len(supported) == 0 {
|
||||
return fmt.Sprintf("Type '%T' doesn't take any properties. Unsupported properties: '%s'\n",
|
||||
err.Value, strings.Join(keys, "', '"))
|
||||
}
|
||||
return fmt.Sprintf("Unsupported properties: '%s'\nSupported properties are: '%s'",
|
||||
strings.Join(keys, "', '"),
|
||||
strings.Join(supported, "', '"))
|
||||
}
|
||||
15
vendor/github.com/getkin/kin-openapi/openapi3/callback.go
generated
vendored
Normal file
15
vendor/github.com/getkin/kin-openapi/openapi3/callback.go
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package openapi3
|
||||
|
||||
import "context"
|
||||
|
||||
// Callback is specified by OpenAPI/Swagger standard version 3.0.
|
||||
type Callback map[string]*PathItem
|
||||
|
||||
func (value Callback) Validate(c context.Context) error {
|
||||
for _, v := range value {
|
||||
if err := v.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
104
vendor/github.com/getkin/kin-openapi/openapi3/components.go
generated
vendored
Normal file
104
vendor/github.com/getkin/kin-openapi/openapi3/components.go
generated
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Components is specified by OpenAPI/Swagger standard version 3.0.
|
||||
type Components struct {
|
||||
ExtensionProps
|
||||
Schemas map[string]*SchemaRef `json:"schemas,omitempty" yaml:"schemas,omitempty"`
|
||||
Parameters map[string]*ParameterRef `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
Headers map[string]*HeaderRef `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
RequestBodies map[string]*RequestBodyRef `json:"requestBodies,omitempty" yaml:"requestBodies,omitempty"`
|
||||
Responses map[string]*ResponseRef `json:"responses,omitempty" yaml:"responses,omitempty"`
|
||||
SecuritySchemes map[string]*SecuritySchemeRef `json:"securitySchemes,omitempty" yaml:"securitySchemes,omitempty"`
|
||||
Examples map[string]*ExampleRef `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Links map[string]*LinkRef `json:"links,omitempty" yaml:"links,omitempty"`
|
||||
Callbacks map[string]*CallbackRef `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
||||
}
|
||||
|
||||
func NewComponents() Components {
|
||||
return Components{}
|
||||
}
|
||||
|
||||
func (components *Components) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(components)
|
||||
}
|
||||
|
||||
func (components *Components) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, components)
|
||||
}
|
||||
|
||||
func (components *Components) Validate(c context.Context) (err error) {
|
||||
for k, v := range components.Schemas {
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return
|
||||
}
|
||||
if err = v.Validate(c); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range components.Parameters {
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return
|
||||
}
|
||||
if err = v.Validate(c); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range components.RequestBodies {
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return
|
||||
}
|
||||
if err = v.Validate(c); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range components.Responses {
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return
|
||||
}
|
||||
if err = v.Validate(c); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range components.Headers {
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return
|
||||
}
|
||||
if err = v.Validate(c); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range components.SecuritySchemes {
|
||||
if err = ValidateIdentifier(k); err != nil {
|
||||
return
|
||||
}
|
||||
if err = v.Validate(c); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const identifierPattern = `^[a-zA-Z0-9.\-_]+$`
|
||||
|
||||
var identifierRegExp = regexp.MustCompile(identifierPattern)
|
||||
|
||||
func ValidateIdentifier(value string) error {
|
||||
if identifierRegExp.MatchString(value) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Identifier '%s' is not supported by OpenAPI version 3 standard (regexp: '%s')", value, identifierPattern)
|
||||
}
|
||||
77
vendor/github.com/getkin/kin-openapi/openapi3/content.go
generated
vendored
Normal file
77
vendor/github.com/getkin/kin-openapi/openapi3/content.go
generated
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Content is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type Content map[string]*MediaType
|
||||
|
||||
func NewContent() Content {
|
||||
return make(map[string]*MediaType, 4)
|
||||
}
|
||||
|
||||
func NewContentWithJSONSchema(schema *Schema) Content {
|
||||
return Content{
|
||||
"application/json": NewMediaType().WithSchema(schema),
|
||||
}
|
||||
}
|
||||
func NewContentWithJSONSchemaRef(schema *SchemaRef) Content {
|
||||
return Content{
|
||||
"application/json": NewMediaType().WithSchemaRef(schema),
|
||||
}
|
||||
}
|
||||
|
||||
func (content Content) Get(mime string) *MediaType {
|
||||
// If the mime is empty then short-circuit to the wildcard.
|
||||
// We do this here so that we catch only the specific case of
|
||||
// and empty mime rather than a present, but invalid, mime type.
|
||||
if mime == "" {
|
||||
return content["*/*"]
|
||||
}
|
||||
// Start by making the most specific match possible
|
||||
// by using the mime type in full.
|
||||
if v := content[mime]; v != nil {
|
||||
return v
|
||||
}
|
||||
// If an exact match is not found then we strip all
|
||||
// metadata from the mime type and only use the x/y
|
||||
// portion.
|
||||
i := strings.IndexByte(mime, ';')
|
||||
if i < 0 {
|
||||
// If there is no metadata then preserve the full mime type
|
||||
// string for later wildcard searches.
|
||||
i = len(mime)
|
||||
}
|
||||
mime = mime[:i]
|
||||
if v := content[mime]; v != nil {
|
||||
return v
|
||||
}
|
||||
// If the x/y pattern has no specific match then we
|
||||
// try the x/* pattern.
|
||||
i = strings.IndexByte(mime, '/')
|
||||
if i < 0 {
|
||||
// In the case that the given mime type is not valid because it is
|
||||
// missing the subtype we return nil so that this does not accidentally
|
||||
// resolve with the wildcard.
|
||||
return nil
|
||||
}
|
||||
mime = mime[:i] + "/*"
|
||||
if v := content[mime]; v != nil {
|
||||
return v
|
||||
}
|
||||
// Finally, the most generic match of */* is returned
|
||||
// as a catch-all.
|
||||
return content["*/*"]
|
||||
}
|
||||
|
||||
func (content Content) Validate(c context.Context) error {
|
||||
for _, v := range content {
|
||||
// Validate MediaType
|
||||
if err := v.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
26
vendor/github.com/getkin/kin-openapi/openapi3/discriminator.go
generated
vendored
Normal file
26
vendor/github.com/getkin/kin-openapi/openapi3/discriminator.go
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Discriminator is specified by OpenAPI/Swagger standard version 3.0.
|
||||
type Discriminator struct {
|
||||
ExtensionProps
|
||||
PropertyName string `json:"propertyName" yaml:"propertyName"`
|
||||
Mapping map[string]string `json:"mapping,omitempty" yaml:"mapping,omitempty"`
|
||||
}
|
||||
|
||||
func (value *Discriminator) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(value)
|
||||
}
|
||||
|
||||
func (value *Discriminator) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
}
|
||||
|
||||
func (value *Discriminator) Validate(c context.Context) error {
|
||||
return nil
|
||||
}
|
||||
5
vendor/github.com/getkin/kin-openapi/openapi3/doc.go
generated
vendored
Normal file
5
vendor/github.com/getkin/kin-openapi/openapi3/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// Package openapi3 parses and writes OpenAPI 3 specifications.
|
||||
//
|
||||
// The OpenAPI 3.0 specification can be found at:
|
||||
// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.md
|
||||
package openapi3
|
||||
93
vendor/github.com/getkin/kin-openapi/openapi3/encoding.go
generated
vendored
Normal file
93
vendor/github.com/getkin/kin-openapi/openapi3/encoding.go
generated
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Encoding is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type Encoding struct {
|
||||
ExtensionProps
|
||||
|
||||
ContentType string `json:"contentType,omitempty" yaml:"contentType,omitempty"`
|
||||
Headers map[string]*HeaderRef `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
Style string `json:"style,omitempty" yaml:"style,omitempty"`
|
||||
Explode *bool `json:"explode,omitempty" yaml:"explode,omitempty"`
|
||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
||||
}
|
||||
|
||||
func NewEncoding() *Encoding {
|
||||
return &Encoding{}
|
||||
}
|
||||
|
||||
func (encoding *Encoding) WithHeader(name string, header *Header) *Encoding {
|
||||
return encoding.WithHeaderRef(name, &HeaderRef{
|
||||
Value: header,
|
||||
})
|
||||
}
|
||||
|
||||
func (encoding *Encoding) WithHeaderRef(name string, ref *HeaderRef) *Encoding {
|
||||
headers := encoding.Headers
|
||||
if headers == nil {
|
||||
headers = make(map[string]*HeaderRef)
|
||||
encoding.Headers = headers
|
||||
}
|
||||
headers[name] = ref
|
||||
return encoding
|
||||
}
|
||||
|
||||
func (encoding *Encoding) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(encoding)
|
||||
}
|
||||
|
||||
func (encoding *Encoding) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, encoding)
|
||||
}
|
||||
|
||||
// SerializationMethod returns a serialization method of request body.
|
||||
// When serialization method is not defined the method returns the default serialization method.
|
||||
func (encoding *Encoding) SerializationMethod() *SerializationMethod {
|
||||
sm := &SerializationMethod{Style: SerializationForm, Explode: true}
|
||||
if encoding != nil {
|
||||
if encoding.Style != "" {
|
||||
sm.Style = encoding.Style
|
||||
}
|
||||
if encoding.Explode != nil {
|
||||
sm.Explode = *encoding.Explode
|
||||
}
|
||||
}
|
||||
return sm
|
||||
}
|
||||
|
||||
func (encoding *Encoding) Validate(c context.Context) error {
|
||||
if encoding == nil {
|
||||
return nil
|
||||
}
|
||||
for k, v := range encoding.Headers {
|
||||
if err := ValidateIdentifier(k); err != nil {
|
||||
return nil
|
||||
}
|
||||
if err := v.Validate(c); err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Validate a media types's serialization method.
|
||||
sm := encoding.SerializationMethod()
|
||||
switch {
|
||||
case sm.Style == SerializationForm && sm.Explode,
|
||||
sm.Style == SerializationForm && !sm.Explode,
|
||||
sm.Style == SerializationSpaceDelimited && sm.Explode,
|
||||
sm.Style == SerializationSpaceDelimited && !sm.Explode,
|
||||
sm.Style == SerializationPipeDelimited && sm.Explode,
|
||||
sm.Style == SerializationPipeDelimited && !sm.Explode,
|
||||
sm.Style == SerializationDeepObject && sm.Explode:
|
||||
// it is a valid
|
||||
default:
|
||||
return fmt.Errorf("Serialization method with style=%q and explode=%v is not supported by media type", sm.Style, sm.Explode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
29
vendor/github.com/getkin/kin-openapi/openapi3/examples.go
generated
vendored
Normal file
29
vendor/github.com/getkin/kin-openapi/openapi3/examples.go
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Example is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type Example struct {
|
||||
ExtensionProps
|
||||
|
||||
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Value interface{} `json:"value,omitempty" yaml:"value,omitempty"`
|
||||
ExternalValue string `json:"externalValue,omitempty" yaml:"externalValue,omitempty"`
|
||||
}
|
||||
|
||||
func NewExample(value interface{}) *Example {
|
||||
return &Example{
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
||||
func (example *Example) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(example)
|
||||
}
|
||||
|
||||
func (example *Example) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, example)
|
||||
}
|
||||
38
vendor/github.com/getkin/kin-openapi/openapi3/extension.go
generated
vendored
Normal file
38
vendor/github.com/getkin/kin-openapi/openapi3/extension.go
generated
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// ExtensionProps provides support for OpenAPI extensions.
|
||||
// It reads/writes all properties that begin with "x-".
|
||||
type ExtensionProps struct {
|
||||
Extensions map[string]interface{} `json:"-" yaml:"-"`
|
||||
}
|
||||
|
||||
// Assert that the type implements the interface
|
||||
var _ jsoninfo.StrictStruct = &ExtensionProps{}
|
||||
|
||||
// EncodeWith will be invoked by package "jsoninfo"
|
||||
func (props *ExtensionProps) EncodeWith(encoder *jsoninfo.ObjectEncoder, value interface{}) error {
|
||||
for k, v := range props.Extensions {
|
||||
if err := encoder.EncodeExtension(k, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return encoder.EncodeStructFieldsAndExtensions(value)
|
||||
}
|
||||
|
||||
// DecodeWith will be invoked by package "jsoninfo"
|
||||
func (props *ExtensionProps) DecodeWith(decoder *jsoninfo.ObjectDecoder, value interface{}) error {
|
||||
if err := decoder.DecodeStructFieldsAndExtensions(value); err != nil {
|
||||
return err
|
||||
}
|
||||
source := decoder.DecodeExtensionMap()
|
||||
result := make(map[string]interface{}, len(source))
|
||||
for k, v := range source {
|
||||
result[k] = v
|
||||
}
|
||||
props.Extensions = result
|
||||
return nil
|
||||
}
|
||||
21
vendor/github.com/getkin/kin-openapi/openapi3/external_docs.go
generated
vendored
Normal file
21
vendor/github.com/getkin/kin-openapi/openapi3/external_docs.go
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// ExternalDocs is specified by OpenAPI/Swagger standard version 3.0.
|
||||
type ExternalDocs struct {
|
||||
ExtensionProps
|
||||
|
||||
Description string `json:"description,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
func (e *ExternalDocs) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(e)
|
||||
}
|
||||
|
||||
func (e *ExternalDocs) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, e)
|
||||
}
|
||||
33
vendor/github.com/getkin/kin-openapi/openapi3/header.go
generated
vendored
Normal file
33
vendor/github.com/getkin/kin-openapi/openapi3/header.go
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
type Header struct {
|
||||
ExtensionProps
|
||||
|
||||
// Optional description. Should use CommonMark syntax.
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Schema *SchemaRef `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Example interface{} `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Examples map[string]*ExampleRef `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Content Content `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
}
|
||||
|
||||
func (value *Header) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
}
|
||||
|
||||
func (value *Header) Validate(c context.Context) error {
|
||||
if v := value.Schema; v != nil {
|
||||
if err := v.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
93
vendor/github.com/getkin/kin-openapi/openapi3/info.go
generated
vendored
Normal file
93
vendor/github.com/getkin/kin-openapi/openapi3/info.go
generated
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Info is specified by OpenAPI/Swagger standard version 3.0.
|
||||
type Info struct {
|
||||
ExtensionProps
|
||||
Title string `json:"title" yaml:"title"` // Required
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
TermsOfService string `json:"termsOfService,omitempty" yaml:"termsOfService,omitempty"`
|
||||
Contact *Contact `json:"contact,omitempty" yaml:"contact,omitempty"`
|
||||
License *License `json:"license,omitempty" yaml:"license,omitempty"`
|
||||
Version string `json:"version" yaml:"version"` // Required
|
||||
}
|
||||
|
||||
func (value *Info) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(value)
|
||||
}
|
||||
|
||||
func (value *Info) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
}
|
||||
|
||||
func (value *Info) Validate(c context.Context) error {
|
||||
if contact := value.Contact; contact != nil {
|
||||
if err := contact.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if license := value.License; license != nil {
|
||||
if err := license.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if value.Version == "" {
|
||||
return errors.New("value of version must be a non-empty JSON string")
|
||||
}
|
||||
|
||||
if value.Title == "" {
|
||||
return errors.New("value of title must be a non-empty JSON string")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Contact is specified by OpenAPI/Swagger standard version 3.0.
|
||||
type Contact struct {
|
||||
ExtensionProps
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
Email string `json:"email,omitempty" yaml:"email,omitempty"`
|
||||
}
|
||||
|
||||
func (value *Contact) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(value)
|
||||
}
|
||||
|
||||
func (value *Contact) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
}
|
||||
|
||||
func (value *Contact) Validate(c context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// License is specified by OpenAPI/Swagger standard version 3.0.
|
||||
type License struct {
|
||||
ExtensionProps
|
||||
Name string `json:"name" yaml:"name"` // Required
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
}
|
||||
|
||||
func (value *License) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(value)
|
||||
}
|
||||
|
||||
func (value *License) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
}
|
||||
|
||||
func (value *License) Validate(c context.Context) error {
|
||||
if value.Name == "" {
|
||||
return errors.New("value of license name must be a non-empty JSON string")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
38
vendor/github.com/getkin/kin-openapi/openapi3/link.go
generated
vendored
Normal file
38
vendor/github.com/getkin/kin-openapi/openapi3/link.go
generated
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Link is specified by OpenAPI/Swagger standard version 3.0.
|
||||
type Link struct {
|
||||
ExtensionProps
|
||||
OperationID string `json:"operationId,omitempty" yaml:"operationId,omitempty"`
|
||||
OperationRef string `json:"operationRef,omitempty" yaml:"operationRef,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Parameters map[string]interface{} `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
Server *Server `json:"server,omitempty" yaml:"server,omitempty"`
|
||||
RequestBody interface{} `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`
|
||||
}
|
||||
|
||||
func (value *Link) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(value)
|
||||
}
|
||||
|
||||
func (value *Link) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, value)
|
||||
}
|
||||
|
||||
func (value *Link) Validate(c context.Context) error {
|
||||
if value.OperationID == "" && value.OperationRef == "" {
|
||||
return errors.New("missing operationId or operationRef on link")
|
||||
}
|
||||
if value.OperationID != "" && value.OperationRef != "" {
|
||||
return fmt.Errorf("operationId '%s' and operationRef '%s' are mutually exclusive", value.OperationID, value.OperationRef)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
79
vendor/github.com/getkin/kin-openapi/openapi3/media_type.go
generated
vendored
Normal file
79
vendor/github.com/getkin/kin-openapi/openapi3/media_type.go
generated
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// MediaType is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type MediaType struct {
|
||||
ExtensionProps
|
||||
|
||||
Schema *SchemaRef `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Example interface{} `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Examples map[string]*ExampleRef `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Encoding map[string]*Encoding `json:"encoding,omitempty" yaml:"encoding,omitempty"`
|
||||
}
|
||||
|
||||
func NewMediaType() *MediaType {
|
||||
return &MediaType{}
|
||||
}
|
||||
|
||||
func (mediaType *MediaType) WithSchema(schema *Schema) *MediaType {
|
||||
if schema == nil {
|
||||
mediaType.Schema = nil
|
||||
} else {
|
||||
mediaType.Schema = &SchemaRef{
|
||||
Value: schema,
|
||||
}
|
||||
}
|
||||
return mediaType
|
||||
}
|
||||
|
||||
func (mediaType *MediaType) WithSchemaRef(schema *SchemaRef) *MediaType {
|
||||
mediaType.Schema = schema
|
||||
return mediaType
|
||||
}
|
||||
|
||||
func (mediaType *MediaType) WithExample(name string, value interface{}) *MediaType {
|
||||
example := mediaType.Examples
|
||||
if example == nil {
|
||||
example = make(map[string]*ExampleRef)
|
||||
mediaType.Examples = example
|
||||
}
|
||||
example[name] = &ExampleRef{
|
||||
Value: NewExample(value),
|
||||
}
|
||||
return mediaType
|
||||
}
|
||||
|
||||
func (mediaType *MediaType) WithEncoding(name string, enc *Encoding) *MediaType {
|
||||
encoding := mediaType.Encoding
|
||||
if encoding == nil {
|
||||
encoding = make(map[string]*Encoding)
|
||||
mediaType.Encoding = encoding
|
||||
}
|
||||
encoding[name] = enc
|
||||
return mediaType
|
||||
}
|
||||
|
||||
func (mediaType *MediaType) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(mediaType)
|
||||
}
|
||||
|
||||
func (mediaType *MediaType) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, mediaType)
|
||||
}
|
||||
|
||||
func (mediaType *MediaType) Validate(c context.Context) error {
|
||||
if mediaType == nil {
|
||||
return nil
|
||||
}
|
||||
if schema := mediaType.Schema; schema != nil {
|
||||
if err := schema.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
102
vendor/github.com/getkin/kin-openapi/openapi3/operation.go
generated
vendored
Normal file
102
vendor/github.com/getkin/kin-openapi/openapi3/operation.go
generated
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Operation represents "operation" specified by" OpenAPI/Swagger 3.0 standard.
|
||||
type Operation struct {
|
||||
ExtensionProps
|
||||
|
||||
// Optional tags for documentation.
|
||||
Tags []string `json:"tags,omitempty" yaml:"tags,omitempty"`
|
||||
|
||||
// Optional short summary.
|
||||
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
|
||||
// Optional description. Should use CommonMark syntax.
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
|
||||
// Optional operation ID.
|
||||
OperationID string `json:"operationId,omitempty" yaml:"operationId,omitempty"`
|
||||
|
||||
// Optional parameters.
|
||||
Parameters Parameters `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
|
||||
// Optional body parameter.
|
||||
RequestBody *RequestBodyRef `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`
|
||||
|
||||
// Responses.
|
||||
Responses Responses `json:"responses" yaml:"responses"` // Required
|
||||
|
||||
// Optional callbacks
|
||||
Callbacks map[string]*CallbackRef `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
||||
|
||||
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
|
||||
// Optional security requirements that overrides top-level security.
|
||||
Security *SecurityRequirements `json:"security,omitempty" yaml:"security,omitempty"`
|
||||
|
||||
// Optional servers that overrides top-level servers.
|
||||
Servers *Servers `json:"servers,omitempty" yaml:"servers,omitempty"`
|
||||
|
||||
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
}
|
||||
|
||||
func NewOperation() *Operation {
|
||||
return &Operation{}
|
||||
}
|
||||
|
||||
func (operation *Operation) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(operation)
|
||||
}
|
||||
|
||||
func (operation *Operation) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, operation)
|
||||
}
|
||||
|
||||
func (operation *Operation) AddParameter(p *Parameter) {
|
||||
operation.Parameters = append(operation.Parameters, &ParameterRef{
|
||||
Value: p,
|
||||
})
|
||||
}
|
||||
|
||||
func (operation *Operation) AddResponse(status int, response *Response) {
|
||||
responses := operation.Responses
|
||||
if responses == nil {
|
||||
responses = NewResponses()
|
||||
operation.Responses = responses
|
||||
}
|
||||
code := "default"
|
||||
if status != 0 {
|
||||
code = strconv.FormatInt(int64(status), 10)
|
||||
}
|
||||
responses[code] = &ResponseRef{
|
||||
Value: response,
|
||||
}
|
||||
}
|
||||
|
||||
func (operation *Operation) Validate(c context.Context) error {
|
||||
if v := operation.Parameters; v != nil {
|
||||
if err := v.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if v := operation.RequestBody; v != nil {
|
||||
if err := v.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if v := operation.Responses; v != nil {
|
||||
if err := v.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return errors.New("value of responses must be a JSON object")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
224
vendor/github.com/getkin/kin-openapi/openapi3/parameter.go
generated
vendored
Normal file
224
vendor/github.com/getkin/kin-openapi/openapi3/parameter.go
generated
vendored
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Parameters is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type Parameters []*ParameterRef
|
||||
|
||||
func NewParameters() Parameters {
|
||||
return make(Parameters, 0, 4)
|
||||
}
|
||||
|
||||
func (parameters Parameters) GetByInAndName(in string, name string) *Parameter {
|
||||
for _, item := range parameters {
|
||||
if v := item.Value; v != nil {
|
||||
if v.Name == name && v.In == in {
|
||||
return v
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (parameters Parameters) Validate(c context.Context) error {
|
||||
dupes := make(map[string]struct{})
|
||||
for _, item := range parameters {
|
||||
if v := item.Value; v != nil {
|
||||
key := v.In + ":" + v.Name
|
||||
if _, ok := dupes[key]; ok {
|
||||
return fmt.Errorf("more than one %q parameter has name %q", v.In, v.Name)
|
||||
}
|
||||
dupes[key] = struct{}{}
|
||||
}
|
||||
|
||||
if err := item.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parameter is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type Parameter struct {
|
||||
ExtensionProps
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
In string `json:"in,omitempty" yaml:"in,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Style string `json:"style,omitempty" yaml:"style,omitempty"`
|
||||
Explode *bool `json:"explode,omitempty" yaml:"explode,omitempty"`
|
||||
AllowEmptyValue bool `json:"allowEmptyValue,omitempty" yaml:"allowEmptyValue,omitempty"`
|
||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
||||
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Schema *SchemaRef `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Example interface{} `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Examples map[string]*ExampleRef `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Content Content `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
ParameterInPath = "path"
|
||||
ParameterInQuery = "query"
|
||||
ParameterInHeader = "header"
|
||||
ParameterInCookie = "cookie"
|
||||
)
|
||||
|
||||
func NewPathParameter(name string) *Parameter {
|
||||
return &Parameter{
|
||||
Name: name,
|
||||
In: ParameterInPath,
|
||||
Required: true,
|
||||
}
|
||||
}
|
||||
|
||||
func NewQueryParameter(name string) *Parameter {
|
||||
return &Parameter{
|
||||
Name: name,
|
||||
In: ParameterInQuery,
|
||||
}
|
||||
}
|
||||
|
||||
func NewHeaderParameter(name string) *Parameter {
|
||||
return &Parameter{
|
||||
Name: name,
|
||||
In: ParameterInHeader,
|
||||
}
|
||||
}
|
||||
|
||||
func NewCookieParameter(name string) *Parameter {
|
||||
return &Parameter{
|
||||
Name: name,
|
||||
In: ParameterInCookie,
|
||||
}
|
||||
}
|
||||
|
||||
func (parameter *Parameter) WithDescription(value string) *Parameter {
|
||||
parameter.Description = value
|
||||
return parameter
|
||||
}
|
||||
|
||||
func (parameter *Parameter) WithRequired(value bool) *Parameter {
|
||||
parameter.Required = value
|
||||
return parameter
|
||||
}
|
||||
|
||||
func (parameter *Parameter) WithSchema(value *Schema) *Parameter {
|
||||
if value == nil {
|
||||
parameter.Schema = nil
|
||||
} else {
|
||||
parameter.Schema = &SchemaRef{
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
return parameter
|
||||
}
|
||||
|
||||
func (parameter *Parameter) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(parameter)
|
||||
}
|
||||
|
||||
func (parameter *Parameter) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, parameter)
|
||||
}
|
||||
|
||||
// SerializationMethod returns a parameter's serialization method.
|
||||
// When a parameter's serialization method is not defined the method returns
|
||||
// the default serialization method corresponding to a parameter's location.
|
||||
func (parameter *Parameter) SerializationMethod() (*SerializationMethod, error) {
|
||||
switch parameter.In {
|
||||
case ParameterInPath, ParameterInHeader:
|
||||
style := parameter.Style
|
||||
if style == "" {
|
||||
style = SerializationSimple
|
||||
}
|
||||
explode := false
|
||||
if parameter.Explode != nil {
|
||||
explode = *parameter.Explode
|
||||
}
|
||||
return &SerializationMethod{Style: style, Explode: explode}, nil
|
||||
case ParameterInQuery, ParameterInCookie:
|
||||
style := parameter.Style
|
||||
if style == "" {
|
||||
style = SerializationForm
|
||||
}
|
||||
explode := true
|
||||
if parameter.Explode != nil {
|
||||
explode = *parameter.Explode
|
||||
}
|
||||
return &SerializationMethod{Style: style, Explode: explode}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected parameter's 'in': %q", parameter.In)
|
||||
}
|
||||
}
|
||||
|
||||
func (parameter *Parameter) Validate(c context.Context) error {
|
||||
if parameter.Name == "" {
|
||||
return errors.New("parameter name can't be blank")
|
||||
}
|
||||
in := parameter.In
|
||||
switch in {
|
||||
case
|
||||
ParameterInPath,
|
||||
ParameterInQuery,
|
||||
ParameterInHeader,
|
||||
ParameterInCookie:
|
||||
default:
|
||||
return fmt.Errorf("parameter can't have 'in' value %q", parameter.In)
|
||||
}
|
||||
|
||||
// Validate a parameter's serialization method.
|
||||
sm, err := parameter.SerializationMethod()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var smSupported bool
|
||||
switch {
|
||||
case parameter.In == ParameterInPath && sm.Style == SerializationSimple && !sm.Explode,
|
||||
parameter.In == ParameterInPath && sm.Style == SerializationSimple && sm.Explode,
|
||||
parameter.In == ParameterInPath && sm.Style == SerializationLabel && !sm.Explode,
|
||||
parameter.In == ParameterInPath && sm.Style == SerializationLabel && sm.Explode,
|
||||
parameter.In == ParameterInPath && sm.Style == SerializationMatrix && !sm.Explode,
|
||||
parameter.In == ParameterInPath && sm.Style == SerializationMatrix && sm.Explode,
|
||||
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationForm && sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationForm && !sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationSpaceDelimited && sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationSpaceDelimited && !sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationPipeDelimited && sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationPipeDelimited && !sm.Explode,
|
||||
parameter.In == ParameterInQuery && sm.Style == SerializationDeepObject && sm.Explode,
|
||||
|
||||
parameter.In == ParameterInHeader && sm.Style == SerializationSimple && !sm.Explode,
|
||||
parameter.In == ParameterInHeader && sm.Style == SerializationSimple && sm.Explode,
|
||||
|
||||
parameter.In == ParameterInCookie && sm.Style == SerializationForm && !sm.Explode,
|
||||
parameter.In == ParameterInCookie && sm.Style == SerializationForm && sm.Explode:
|
||||
smSupported = true
|
||||
}
|
||||
if !smSupported {
|
||||
e := fmt.Errorf("serialization method with style=%q and explode=%v is not supported by a %s parameter", sm.Style, sm.Explode, in)
|
||||
return fmt.Errorf("parameter %q schema is invalid: %v", parameter.Name, e)
|
||||
}
|
||||
|
||||
if (parameter.Schema == nil) == (parameter.Content == nil) {
|
||||
e := errors.New("parameter must contain exactly one of content and schema")
|
||||
return fmt.Errorf("parameter %q schema is invalid: %v", parameter.Name, e)
|
||||
}
|
||||
if schema := parameter.Schema; schema != nil {
|
||||
if err := schema.Validate(c); err != nil {
|
||||
return fmt.Errorf("parameter %q schema is invalid: %v", parameter.Name, err)
|
||||
}
|
||||
}
|
||||
if content := parameter.Content; content != nil {
|
||||
if err := content.Validate(c); err != nil {
|
||||
return fmt.Errorf("parameter %q content is invalid: %v", parameter.Name, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
126
vendor/github.com/getkin/kin-openapi/openapi3/path_item.go
generated
vendored
Normal file
126
vendor/github.com/getkin/kin-openapi/openapi3/path_item.go
generated
vendored
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
type PathItem struct {
|
||||
ExtensionProps
|
||||
Ref string `json:"$ref,omitempty" yaml:"$ref,omitempty"`
|
||||
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Connect *Operation `json:"connect,omitempty" yaml:"connect,omitempty"`
|
||||
Delete *Operation `json:"delete,omitempty" yaml:"delete,omitempty"`
|
||||
Get *Operation `json:"get,omitempty" yaml:"get,omitempty"`
|
||||
Head *Operation `json:"head,omitempty" yaml:"head,omitempty"`
|
||||
Options *Operation `json:"options,omitempty" yaml:"options,omitempty"`
|
||||
Patch *Operation `json:"patch,omitempty" yaml:"patch,omitempty"`
|
||||
Post *Operation `json:"post,omitempty" yaml:"post,omitempty"`
|
||||
Put *Operation `json:"put,omitempty" yaml:"put,omitempty"`
|
||||
Trace *Operation `json:"trace,omitempty" yaml:"trace,omitempty"`
|
||||
Servers Servers `json:"servers,omitempty" yaml:"servers,omitempty"`
|
||||
Parameters Parameters `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
}
|
||||
|
||||
func (pathItem *PathItem) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(pathItem)
|
||||
}
|
||||
|
||||
func (pathItem *PathItem) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, pathItem)
|
||||
}
|
||||
|
||||
func (pathItem *PathItem) Operations() map[string]*Operation {
|
||||
operations := make(map[string]*Operation, 4)
|
||||
if v := pathItem.Connect; v != nil {
|
||||
operations[http.MethodConnect] = v
|
||||
}
|
||||
if v := pathItem.Delete; v != nil {
|
||||
operations[http.MethodDelete] = v
|
||||
}
|
||||
if v := pathItem.Get; v != nil {
|
||||
operations[http.MethodGet] = v
|
||||
}
|
||||
if v := pathItem.Head; v != nil {
|
||||
operations[http.MethodHead] = v
|
||||
}
|
||||
if v := pathItem.Options; v != nil {
|
||||
operations[http.MethodOptions] = v
|
||||
}
|
||||
if v := pathItem.Patch; v != nil {
|
||||
operations[http.MethodPatch] = v
|
||||
}
|
||||
if v := pathItem.Post; v != nil {
|
||||
operations[http.MethodPost] = v
|
||||
}
|
||||
if v := pathItem.Put; v != nil {
|
||||
operations[http.MethodPut] = v
|
||||
}
|
||||
if v := pathItem.Trace; v != nil {
|
||||
operations[http.MethodTrace] = v
|
||||
}
|
||||
return operations
|
||||
}
|
||||
|
||||
func (pathItem *PathItem) GetOperation(method string) *Operation {
|
||||
switch method {
|
||||
case http.MethodConnect:
|
||||
return pathItem.Connect
|
||||
case http.MethodDelete:
|
||||
return pathItem.Delete
|
||||
case http.MethodGet:
|
||||
return pathItem.Get
|
||||
case http.MethodHead:
|
||||
return pathItem.Head
|
||||
case http.MethodOptions:
|
||||
return pathItem.Options
|
||||
case http.MethodPatch:
|
||||
return pathItem.Patch
|
||||
case http.MethodPost:
|
||||
return pathItem.Post
|
||||
case http.MethodPut:
|
||||
return pathItem.Put
|
||||
case http.MethodTrace:
|
||||
return pathItem.Trace
|
||||
default:
|
||||
panic(fmt.Errorf("Unsupported HTTP method '%s'", method))
|
||||
}
|
||||
}
|
||||
|
||||
func (pathItem *PathItem) SetOperation(method string, operation *Operation) {
|
||||
switch method {
|
||||
case http.MethodConnect:
|
||||
pathItem.Connect = operation
|
||||
case http.MethodDelete:
|
||||
pathItem.Delete = operation
|
||||
case http.MethodGet:
|
||||
pathItem.Get = operation
|
||||
case http.MethodHead:
|
||||
pathItem.Head = operation
|
||||
case http.MethodOptions:
|
||||
pathItem.Options = operation
|
||||
case http.MethodPatch:
|
||||
pathItem.Patch = operation
|
||||
case http.MethodPost:
|
||||
pathItem.Post = operation
|
||||
case http.MethodPut:
|
||||
pathItem.Put = operation
|
||||
case http.MethodTrace:
|
||||
pathItem.Trace = operation
|
||||
default:
|
||||
panic(fmt.Errorf("Unsupported HTTP method '%s'", method))
|
||||
}
|
||||
}
|
||||
|
||||
func (pathItem *PathItem) Validate(c context.Context) error {
|
||||
for _, operation := range pathItem.Operations() {
|
||||
if err := operation.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
122
vendor/github.com/getkin/kin-openapi/openapi3/paths.go
generated
vendored
Normal file
122
vendor/github.com/getkin/kin-openapi/openapi3/paths.go
generated
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Paths is specified by OpenAPI/Swagger standard version 3.0.
|
||||
type Paths map[string]*PathItem
|
||||
|
||||
func (paths Paths) Validate(c context.Context) error {
|
||||
normalizedPaths := make(map[string]string)
|
||||
for path, pathItem := range paths {
|
||||
if path == "" || path[0] != '/' {
|
||||
return fmt.Errorf("path %q does not start with a forward slash (/)", path)
|
||||
}
|
||||
|
||||
normalizedPath, pathParamsCount := normalizeTemplatedPath(path)
|
||||
if oldPath, ok := normalizedPaths[normalizedPath]; ok {
|
||||
return fmt.Errorf("conflicting paths %q and %q", path, oldPath)
|
||||
}
|
||||
normalizedPaths[path] = path
|
||||
|
||||
var globalCount uint
|
||||
for _, parameterRef := range pathItem.Parameters {
|
||||
if parameterRef != nil {
|
||||
if parameter := parameterRef.Value; parameter != nil && parameter.In == ParameterInPath {
|
||||
globalCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
for method, operation := range pathItem.Operations() {
|
||||
var count uint
|
||||
for _, parameterRef := range operation.Parameters {
|
||||
if parameterRef != nil {
|
||||
if parameter := parameterRef.Value; parameter != nil && parameter.In == ParameterInPath {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
if count+globalCount != pathParamsCount {
|
||||
return fmt.Errorf("operation %s %s must define exactly all path parameters", method, path)
|
||||
}
|
||||
}
|
||||
|
||||
if err := pathItem.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Find returns a path that matches the key.
|
||||
//
|
||||
// The method ignores differences in template variable names (except possible "*" suffix).
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// paths := openapi3.Paths {
|
||||
// "/person/{personName}": &openapi3.PathItem{},
|
||||
// }
|
||||
// pathItem := path.Find("/person/{name}")
|
||||
//
|
||||
// would return the correct path item.
|
||||
func (paths Paths) Find(key string) *PathItem {
|
||||
// Try directly access the map
|
||||
pathItem := paths[key]
|
||||
if pathItem != nil {
|
||||
return pathItem
|
||||
}
|
||||
|
||||
normalizedPath, expected := normalizeTemplatedPath(key)
|
||||
for path, pathItem := range paths {
|
||||
pathNormalized, got := normalizeTemplatedPath(path)
|
||||
if got == expected && pathNormalized == normalizedPath {
|
||||
return pathItem
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizeTemplatedPath(path string) (string, uint) {
|
||||
if strings.IndexByte(path, '{') < 0 {
|
||||
return path, 0
|
||||
}
|
||||
|
||||
var buf strings.Builder
|
||||
buf.Grow(len(path))
|
||||
|
||||
var (
|
||||
cc rune
|
||||
count uint
|
||||
isVariable bool
|
||||
)
|
||||
for i, c := range path {
|
||||
if isVariable {
|
||||
if c == '}' {
|
||||
// End path variables
|
||||
// First append possible '*' before this character
|
||||
// The character '}' will be appended
|
||||
if i > 0 && cc == '*' {
|
||||
buf.WriteRune(cc)
|
||||
}
|
||||
isVariable = false
|
||||
} else {
|
||||
// Skip this character
|
||||
continue
|
||||
}
|
||||
} else if c == '{' {
|
||||
// Begin path variable
|
||||
// The character '{' will be appended
|
||||
isVariable = true
|
||||
count++
|
||||
}
|
||||
|
||||
// Append the character
|
||||
buf.WriteRune(c)
|
||||
cc = c
|
||||
}
|
||||
return buf.String(), count
|
||||
}
|
||||
199
vendor/github.com/getkin/kin-openapi/openapi3/refs.go
generated
vendored
Normal file
199
vendor/github.com/getkin/kin-openapi/openapi3/refs.go
generated
vendored
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
type CallbackRef struct {
|
||||
Ref string
|
||||
Value *Callback
|
||||
}
|
||||
|
||||
func (value *CallbackRef) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalRef(value.Ref, value.Value)
|
||||
}
|
||||
|
||||
func (value *CallbackRef) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalRef(data, &value.Ref, &value.Value)
|
||||
}
|
||||
|
||||
func (value *CallbackRef) Validate(c context.Context) error {
|
||||
v := value.Value
|
||||
if v == nil {
|
||||
return foundUnresolvedRef(value.Ref)
|
||||
}
|
||||
return v.Validate(c)
|
||||
}
|
||||
|
||||
type ExampleRef struct {
|
||||
Ref string
|
||||
Value *Example
|
||||
}
|
||||
|
||||
func (value *ExampleRef) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalRef(value.Ref, value.Value)
|
||||
}
|
||||
|
||||
func (value *ExampleRef) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalRef(data, &value.Ref, &value.Value)
|
||||
}
|
||||
|
||||
func (value *ExampleRef) Validate(c context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type HeaderRef struct {
|
||||
Ref string
|
||||
Value *Header
|
||||
}
|
||||
|
||||
func (value *HeaderRef) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalRef(value.Ref, value.Value)
|
||||
}
|
||||
|
||||
func (value *HeaderRef) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalRef(data, &value.Ref, &value.Value)
|
||||
}
|
||||
|
||||
func (value *HeaderRef) Validate(c context.Context) error {
|
||||
v := value.Value
|
||||
if v == nil {
|
||||
return foundUnresolvedRef(value.Ref)
|
||||
}
|
||||
return v.Validate(c)
|
||||
}
|
||||
|
||||
type LinkRef struct {
|
||||
Ref string
|
||||
Value *Link
|
||||
}
|
||||
|
||||
func (value *LinkRef) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalRef(value.Ref, value.Value)
|
||||
}
|
||||
|
||||
func (value *LinkRef) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalRef(data, &value.Ref, &value.Value)
|
||||
}
|
||||
|
||||
func (value *LinkRef) Validate(c context.Context) error {
|
||||
v := value.Value
|
||||
if v == nil {
|
||||
return foundUnresolvedRef(value.Ref)
|
||||
}
|
||||
return v.Validate(c)
|
||||
}
|
||||
|
||||
type ParameterRef struct {
|
||||
Ref string
|
||||
Value *Parameter
|
||||
}
|
||||
|
||||
func (value *ParameterRef) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalRef(value.Ref, value.Value)
|
||||
}
|
||||
|
||||
func (value *ParameterRef) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalRef(data, &value.Ref, &value.Value)
|
||||
}
|
||||
|
||||
func (value *ParameterRef) Validate(c context.Context) error {
|
||||
v := value.Value
|
||||
if v == nil {
|
||||
return foundUnresolvedRef(value.Ref)
|
||||
}
|
||||
return v.Validate(c)
|
||||
}
|
||||
|
||||
type ResponseRef struct {
|
||||
Ref string
|
||||
Value *Response
|
||||
}
|
||||
|
||||
func (value *ResponseRef) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalRef(value.Ref, value.Value)
|
||||
}
|
||||
|
||||
func (value *ResponseRef) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalRef(data, &value.Ref, &value.Value)
|
||||
}
|
||||
|
||||
func (value *ResponseRef) Validate(c context.Context) error {
|
||||
v := value.Value
|
||||
if v == nil {
|
||||
return foundUnresolvedRef(value.Ref)
|
||||
}
|
||||
return v.Validate(c)
|
||||
}
|
||||
|
||||
type RequestBodyRef struct {
|
||||
Ref string
|
||||
Value *RequestBody
|
||||
}
|
||||
|
||||
func (value *RequestBodyRef) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalRef(value.Ref, value.Value)
|
||||
}
|
||||
|
||||
func (value *RequestBodyRef) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalRef(data, &value.Ref, &value.Value)
|
||||
}
|
||||
|
||||
func (value *RequestBodyRef) Validate(c context.Context) error {
|
||||
v := value.Value
|
||||
if v == nil {
|
||||
return foundUnresolvedRef(value.Ref)
|
||||
}
|
||||
return v.Validate(c)
|
||||
}
|
||||
|
||||
type SchemaRef struct {
|
||||
Ref string
|
||||
Value *Schema
|
||||
}
|
||||
|
||||
func NewSchemaRef(ref string, value *Schema) *SchemaRef {
|
||||
return &SchemaRef{
|
||||
Ref: ref,
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
||||
func (value *SchemaRef) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalRef(value.Ref, value.Value)
|
||||
}
|
||||
|
||||
func (value *SchemaRef) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalRef(data, &value.Ref, &value.Value)
|
||||
}
|
||||
|
||||
func (value *SchemaRef) Validate(c context.Context) error {
|
||||
v := value.Value
|
||||
if v == nil {
|
||||
return foundUnresolvedRef(value.Ref)
|
||||
}
|
||||
return v.Validate(c)
|
||||
}
|
||||
|
||||
type SecuritySchemeRef struct {
|
||||
Ref string
|
||||
Value *SecurityScheme
|
||||
}
|
||||
|
||||
func (value *SecuritySchemeRef) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalRef(value.Ref, value.Value)
|
||||
}
|
||||
|
||||
func (value *SecuritySchemeRef) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalRef(data, &value.Ref, &value.Value)
|
||||
}
|
||||
|
||||
func (value *SecuritySchemeRef) Validate(c context.Context) error {
|
||||
v := value.Value
|
||||
if v == nil {
|
||||
return foundUnresolvedRef(value.Ref)
|
||||
}
|
||||
return v.Validate(c)
|
||||
}
|
||||
69
vendor/github.com/getkin/kin-openapi/openapi3/request_body.go
generated
vendored
Normal file
69
vendor/github.com/getkin/kin-openapi/openapi3/request_body.go
generated
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// RequestBody is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type RequestBody struct {
|
||||
ExtensionProps
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Content Content `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
}
|
||||
|
||||
func NewRequestBody() *RequestBody {
|
||||
return &RequestBody{}
|
||||
}
|
||||
|
||||
func (requestBody *RequestBody) WithDescription(value string) *RequestBody {
|
||||
requestBody.Description = value
|
||||
return requestBody
|
||||
}
|
||||
|
||||
func (requestBody *RequestBody) WithRequired(value bool) *RequestBody {
|
||||
requestBody.Required = value
|
||||
return requestBody
|
||||
}
|
||||
|
||||
func (requestBody *RequestBody) WithContent(content Content) *RequestBody {
|
||||
requestBody.Content = content
|
||||
return requestBody
|
||||
}
|
||||
|
||||
func (requestBody *RequestBody) WithJSONSchemaRef(value *SchemaRef) *RequestBody {
|
||||
requestBody.Content = NewContentWithJSONSchemaRef(value)
|
||||
return requestBody
|
||||
}
|
||||
|
||||
func (requestBody *RequestBody) WithJSONSchema(value *Schema) *RequestBody {
|
||||
requestBody.Content = NewContentWithJSONSchema(value)
|
||||
return requestBody
|
||||
}
|
||||
|
||||
func (requestBody *RequestBody) GetMediaType(mediaType string) *MediaType {
|
||||
m := requestBody.Content
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
return m[mediaType]
|
||||
}
|
||||
|
||||
func (requestBody *RequestBody) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(requestBody)
|
||||
}
|
||||
|
||||
func (requestBody *RequestBody) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, requestBody)
|
||||
}
|
||||
|
||||
func (requestBody *RequestBody) Validate(c context.Context) error {
|
||||
if v := requestBody.Content; v != nil {
|
||||
if err := v.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
92
vendor/github.com/getkin/kin-openapi/openapi3/response.go
generated
vendored
Normal file
92
vendor/github.com/getkin/kin-openapi/openapi3/response.go
generated
vendored
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
// Responses is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type Responses map[string]*ResponseRef
|
||||
|
||||
func NewResponses() Responses {
|
||||
r := make(Responses)
|
||||
r["default"] = &ResponseRef{Value: NewResponse().WithDescription("")}
|
||||
return r
|
||||
}
|
||||
|
||||
func (responses Responses) Default() *ResponseRef {
|
||||
return responses["default"]
|
||||
}
|
||||
|
||||
func (responses Responses) Get(status int) *ResponseRef {
|
||||
return responses[strconv.FormatInt(int64(status), 10)]
|
||||
}
|
||||
|
||||
func (responses Responses) Validate(c context.Context) error {
|
||||
if len(responses) == 0 {
|
||||
return errors.New("the responses object MUST contain at least one response code")
|
||||
}
|
||||
for _, v := range responses {
|
||||
if err := v.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Response is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type Response struct {
|
||||
ExtensionProps
|
||||
Description *string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Headers map[string]*HeaderRef `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
Content Content `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
Links map[string]*LinkRef `json:"links,omitempty" yaml:"links,omitempty"`
|
||||
}
|
||||
|
||||
func NewResponse() *Response {
|
||||
return &Response{}
|
||||
}
|
||||
|
||||
func (response *Response) WithDescription(value string) *Response {
|
||||
response.Description = &value
|
||||
return response
|
||||
}
|
||||
|
||||
func (response *Response) WithContent(content Content) *Response {
|
||||
response.Content = content
|
||||
return response
|
||||
}
|
||||
|
||||
func (response *Response) WithJSONSchema(schema *Schema) *Response {
|
||||
response.Content = NewContentWithJSONSchema(schema)
|
||||
return response
|
||||
}
|
||||
|
||||
func (response *Response) WithJSONSchemaRef(schema *SchemaRef) *Response {
|
||||
response.Content = NewContentWithJSONSchemaRef(schema)
|
||||
return response
|
||||
}
|
||||
|
||||
func (response *Response) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(response)
|
||||
}
|
||||
|
||||
func (response *Response) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, response)
|
||||
}
|
||||
|
||||
func (response *Response) Validate(c context.Context) error {
|
||||
if response.Description == nil {
|
||||
return errors.New("a short description of the response is required")
|
||||
}
|
||||
|
||||
if content := response.Content; content != nil {
|
||||
if err := content.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
1235
vendor/github.com/getkin/kin-openapi/openapi3/schema.go
generated
vendored
Normal file
1235
vendor/github.com/getkin/kin-openapi/openapi3/schema.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
38
vendor/github.com/getkin/kin-openapi/openapi3/schema_formats.go
generated
vendored
Normal file
38
vendor/github.com/getkin/kin-openapi/openapi3/schema_formats.go
generated
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
const (
|
||||
// FormatOfStringForUUIDOfRFC4122 is an optional predefined format for UUID v1-v5 as specified by RFC4122
|
||||
FormatOfStringForUUIDOfRFC4122 = `^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`
|
||||
)
|
||||
|
||||
var SchemaStringFormats = make(map[string]*regexp.Regexp, 8)
|
||||
|
||||
func DefineStringFormat(name string, pattern string) {
|
||||
re, err := regexp.Compile(pattern)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Format '%v' has invalid pattern '%v': %v", name, pattern, err)
|
||||
panic(err)
|
||||
}
|
||||
SchemaStringFormats[name] = re
|
||||
}
|
||||
|
||||
func init() {
|
||||
// This pattern catches only some suspiciously wrong-looking email addresses.
|
||||
// Use DefineStringFormat(...) if you need something stricter.
|
||||
DefineStringFormat("email", `^[^@]+@[^@<>",\s]+$`)
|
||||
|
||||
// Base64
|
||||
// The pattern supports base64 and b./ase64url. Padding ('=') is supported.
|
||||
DefineStringFormat("byte", `(^$|^[a-zA-Z0-9+/\-_]*=*$)`)
|
||||
|
||||
// date
|
||||
DefineStringFormat("date", `^[0-9]{4}-(0[0-9]|10|11|12)-([0-2][0-9]|30|31)$`)
|
||||
|
||||
// date-time
|
||||
DefineStringFormat("date-time", `^[0-9]{4}-(0[0-9]|10|11|12)-([0-2][0-9]|30|31)T[0-9]{2}:[0-9]{2}:[0-9]{2}(.[0-9]+)?(Z|(\+|-)[0-9]{2}:[0-9]{2})?$`)
|
||||
}
|
||||
43
vendor/github.com/getkin/kin-openapi/openapi3/security_requirements.go
generated
vendored
Normal file
43
vendor/github.com/getkin/kin-openapi/openapi3/security_requirements.go
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type SecurityRequirements []SecurityRequirement
|
||||
|
||||
func NewSecurityRequirements() *SecurityRequirements {
|
||||
return &SecurityRequirements{}
|
||||
}
|
||||
|
||||
func (srs *SecurityRequirements) With(securityRequirement SecurityRequirement) *SecurityRequirements {
|
||||
*srs = append(*srs, securityRequirement)
|
||||
return srs
|
||||
}
|
||||
|
||||
func (srs SecurityRequirements) Validate(c context.Context) error {
|
||||
for _, item := range srs {
|
||||
if err := item.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SecurityRequirement map[string][]string
|
||||
|
||||
func NewSecurityRequirement() SecurityRequirement {
|
||||
return make(SecurityRequirement)
|
||||
}
|
||||
|
||||
func (security SecurityRequirement) Authenticate(provider string, scopes ...string) SecurityRequirement {
|
||||
if len(scopes) == 0 {
|
||||
scopes = []string{} // Forces the variable to be encoded as an array instead of null
|
||||
}
|
||||
security[provider] = scopes
|
||||
return security
|
||||
}
|
||||
|
||||
func (security SecurityRequirement) Validate(c context.Context) error {
|
||||
return nil
|
||||
}
|
||||
214
vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go
generated
vendored
Normal file
214
vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go
generated
vendored
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
type SecurityScheme struct {
|
||||
ExtensionProps
|
||||
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
In string `json:"in,omitempty" yaml:"in,omitempty"`
|
||||
Scheme string `json:"scheme,omitempty" yaml:"scheme,omitempty"`
|
||||
BearerFormat string `json:"bearerFormat,omitempty" yaml:"bearerFormat,omitempty"`
|
||||
Flows *OAuthFlows `json:"flows,omitempty" yaml:"flows,omitempty"`
|
||||
}
|
||||
|
||||
func NewSecurityScheme() *SecurityScheme {
|
||||
return &SecurityScheme{}
|
||||
}
|
||||
|
||||
func NewCSRFSecurityScheme() *SecurityScheme {
|
||||
return &SecurityScheme{
|
||||
Type: "apiKey",
|
||||
In: "header",
|
||||
Name: "X-XSRF-TOKEN",
|
||||
}
|
||||
}
|
||||
|
||||
func NewJWTSecurityScheme() *SecurityScheme {
|
||||
return &SecurityScheme{
|
||||
Type: "http",
|
||||
Scheme: "bearer",
|
||||
BearerFormat: "JWT",
|
||||
}
|
||||
}
|
||||
|
||||
func (ss *SecurityScheme) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(ss)
|
||||
}
|
||||
|
||||
func (ss *SecurityScheme) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, ss)
|
||||
}
|
||||
|
||||
func (ss *SecurityScheme) WithType(value string) *SecurityScheme {
|
||||
ss.Type = value
|
||||
return ss
|
||||
}
|
||||
|
||||
func (ss *SecurityScheme) WithDescription(value string) *SecurityScheme {
|
||||
ss.Description = value
|
||||
return ss
|
||||
}
|
||||
|
||||
func (ss *SecurityScheme) WithName(value string) *SecurityScheme {
|
||||
ss.Name = value
|
||||
return ss
|
||||
}
|
||||
|
||||
func (ss *SecurityScheme) WithIn(value string) *SecurityScheme {
|
||||
ss.In = value
|
||||
return ss
|
||||
}
|
||||
|
||||
func (ss *SecurityScheme) WithScheme(value string) *SecurityScheme {
|
||||
ss.Scheme = value
|
||||
return ss
|
||||
}
|
||||
|
||||
func (ss *SecurityScheme) WithBearerFormat(value string) *SecurityScheme {
|
||||
ss.BearerFormat = value
|
||||
return ss
|
||||
}
|
||||
|
||||
func (ss *SecurityScheme) Validate(c context.Context) error {
|
||||
hasIn := false
|
||||
hasBearerFormat := false
|
||||
hasFlow := false
|
||||
switch ss.Type {
|
||||
case "apiKey":
|
||||
hasIn = true
|
||||
case "http":
|
||||
scheme := ss.Scheme
|
||||
switch scheme {
|
||||
case "bearer":
|
||||
hasBearerFormat = true
|
||||
case "basic":
|
||||
default:
|
||||
return fmt.Errorf("Security scheme of type 'http' has invalid 'scheme' value '%s'", scheme)
|
||||
}
|
||||
case "oauth2":
|
||||
hasFlow = true
|
||||
case "openIdConnect":
|
||||
return fmt.Errorf("Support for security schemes with type '%v' has not been implemented", ss.Type)
|
||||
default:
|
||||
return fmt.Errorf("Security scheme 'type' can't be '%v'", ss.Type)
|
||||
}
|
||||
|
||||
// Validate "in" and "name"
|
||||
if hasIn {
|
||||
switch ss.In {
|
||||
case "query", "header", "cookie":
|
||||
default:
|
||||
return fmt.Errorf("Security scheme of type 'apiKey' should have 'in'. It can be 'query', 'header' or 'cookie', not '%s'", ss.In)
|
||||
}
|
||||
if ss.Name == "" {
|
||||
return errors.New("Security scheme of type 'apiKey' should have 'name'")
|
||||
}
|
||||
} else if len(ss.In) > 0 {
|
||||
return fmt.Errorf("Security scheme of type '%s' can't have 'in'", ss.Type)
|
||||
} else if len(ss.Name) > 0 {
|
||||
return errors.New("Security scheme of type 'apiKey' can't have 'name'")
|
||||
}
|
||||
|
||||
// Validate "format"
|
||||
// "bearerFormat" is an arbitrary string so we only check if the scheme supports it
|
||||
if !hasBearerFormat && len(ss.BearerFormat) > 0 {
|
||||
return fmt.Errorf("Security scheme of type '%v' can't have 'bearerFormat'", ss.Type)
|
||||
}
|
||||
|
||||
// Validate "flow"
|
||||
if hasFlow {
|
||||
flow := ss.Flows
|
||||
if flow == nil {
|
||||
return fmt.Errorf("Security scheme of type '%v' should have 'flows'", ss.Type)
|
||||
}
|
||||
if err := flow.Validate(c); err != nil {
|
||||
return fmt.Errorf("Security scheme 'flow' is invalid: %v", err)
|
||||
}
|
||||
} else if ss.Flows != nil {
|
||||
return fmt.Errorf("Security scheme of type '%s' can't have 'flows'", ss.Type)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type OAuthFlows struct {
|
||||
ExtensionProps
|
||||
Implicit *OAuthFlow `json:"implicit,omitempty" yaml:"implicit,omitempty"`
|
||||
Password *OAuthFlow `json:"password,omitempty" yaml:"password,omitempty"`
|
||||
ClientCredentials *OAuthFlow `json:"clientCredentials,omitempty" yaml:"clientCredentials,omitempty"`
|
||||
AuthorizationCode *OAuthFlow `json:"authorizationCode,omitempty" yaml:"authorizationCode,omitempty"`
|
||||
}
|
||||
|
||||
type oAuthFlowType int
|
||||
|
||||
const (
|
||||
oAuthFlowTypeImplicit oAuthFlowType = iota
|
||||
oAuthFlowTypePassword
|
||||
oAuthFlowTypeClientCredentials
|
||||
oAuthFlowAuthorizationCode
|
||||
)
|
||||
|
||||
func (flows *OAuthFlows) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(flows)
|
||||
}
|
||||
|
||||
func (flows *OAuthFlows) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, flows)
|
||||
}
|
||||
|
||||
func (flows *OAuthFlows) Validate(c context.Context) error {
|
||||
if v := flows.Implicit; v != nil {
|
||||
return v.Validate(c, oAuthFlowTypeImplicit)
|
||||
}
|
||||
if v := flows.Password; v != nil {
|
||||
return v.Validate(c, oAuthFlowTypePassword)
|
||||
}
|
||||
if v := flows.ClientCredentials; v != nil {
|
||||
return v.Validate(c, oAuthFlowTypeClientCredentials)
|
||||
}
|
||||
if v := flows.AuthorizationCode; v != nil {
|
||||
return v.Validate(c, oAuthFlowAuthorizationCode)
|
||||
}
|
||||
return errors.New("No OAuth flow is defined")
|
||||
}
|
||||
|
||||
type OAuthFlow struct {
|
||||
ExtensionProps
|
||||
AuthorizationURL string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"`
|
||||
TokenURL string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
|
||||
RefreshURL string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"`
|
||||
Scopes map[string]string `json:"scopes" yaml:"scopes"`
|
||||
}
|
||||
|
||||
func (flow *OAuthFlow) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(flow)
|
||||
}
|
||||
|
||||
func (flow *OAuthFlow) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, flow)
|
||||
}
|
||||
|
||||
func (flow *OAuthFlow) Validate(c context.Context, typ oAuthFlowType) error {
|
||||
if typ == oAuthFlowAuthorizationCode || typ == oAuthFlowTypeImplicit {
|
||||
if v := flow.AuthorizationURL; v == "" {
|
||||
return errors.New("An OAuth flow is missing 'authorizationUrl in authorizationCode or implicit '")
|
||||
}
|
||||
}
|
||||
if typ != oAuthFlowTypeImplicit {
|
||||
if v := flow.TokenURL; v == "" {
|
||||
return errors.New("An OAuth flow is missing 'tokenUrl in not implicit'")
|
||||
}
|
||||
}
|
||||
if v := flow.Scopes; v == nil {
|
||||
return errors.New("An OAuth flow is missing 'scopes'")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
17
vendor/github.com/getkin/kin-openapi/openapi3/serialization_method.go
generated
vendored
Normal file
17
vendor/github.com/getkin/kin-openapi/openapi3/serialization_method.go
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package openapi3
|
||||
|
||||
const (
|
||||
SerializationSimple = "simple"
|
||||
SerializationLabel = "label"
|
||||
SerializationMatrix = "matrix"
|
||||
SerializationForm = "form"
|
||||
SerializationSpaceDelimited = "spaceDelimited"
|
||||
SerializationPipeDelimited = "pipeDelimited"
|
||||
SerializationDeepObject = "deepObject"
|
||||
)
|
||||
|
||||
// SerializationMethod describes a serialization method of HTTP request's parameters and body.
|
||||
type SerializationMethod struct {
|
||||
Style string
|
||||
Explode bool
|
||||
}
|
||||
148
vendor/github.com/getkin/kin-openapi/openapi3/server.go
generated
vendored
Normal file
148
vendor/github.com/getkin/kin-openapi/openapi3/server.go
generated
vendored
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"math"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Servers is specified by OpenAPI/Swagger standard version 3.0.
|
||||
type Servers []*Server
|
||||
|
||||
func (servers Servers) Validate(c context.Context) error {
|
||||
for _, v := range servers {
|
||||
if err := v.Validate(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (servers Servers) MatchURL(parsedURL *url.URL) (*Server, []string, string) {
|
||||
rawURL := parsedURL.String()
|
||||
if i := strings.IndexByte(rawURL, '?'); i >= 0 {
|
||||
rawURL = rawURL[:i]
|
||||
}
|
||||
for _, server := range servers {
|
||||
pathParams, remaining, ok := server.MatchRawURL(rawURL)
|
||||
if ok {
|
||||
return server, pathParams, remaining
|
||||
}
|
||||
}
|
||||
return nil, nil, ""
|
||||
}
|
||||
|
||||
// Server is specified by OpenAPI/Swagger standard version 3.0.
|
||||
type Server struct {
|
||||
URL string `json:"url" yaml:"url"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Variables map[string]*ServerVariable `json:"variables,omitempty" yaml:"variables,omitempty"`
|
||||
}
|
||||
|
||||
func (server Server) ParameterNames() ([]string, error) {
|
||||
pattern := server.URL
|
||||
var params []string
|
||||
for len(pattern) > 0 {
|
||||
i := strings.IndexByte(pattern, '{')
|
||||
if i < 0 {
|
||||
break
|
||||
}
|
||||
pattern = pattern[i+1:]
|
||||
i = strings.IndexByte(pattern, '}')
|
||||
if i < 0 {
|
||||
return nil, errors.New("Missing '}'")
|
||||
}
|
||||
params = append(params, strings.TrimSpace(pattern[:i]))
|
||||
pattern = pattern[i+1:]
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (server Server) MatchRawURL(input string) ([]string, string, bool) {
|
||||
pattern := server.URL
|
||||
var params []string
|
||||
for len(pattern) > 0 {
|
||||
c := pattern[0]
|
||||
if len(pattern) == 1 && c == '/' {
|
||||
break
|
||||
}
|
||||
if c == '{' {
|
||||
// Find end of pattern
|
||||
i := strings.IndexByte(pattern, '}')
|
||||
if i < 0 {
|
||||
return nil, "", false
|
||||
}
|
||||
pattern = pattern[i+1:]
|
||||
|
||||
// Find next matching pattern character or next '/' whichever comes first
|
||||
np := -1
|
||||
if len(pattern) > 0 {
|
||||
np = strings.IndexByte(input, pattern[0])
|
||||
}
|
||||
ns := strings.IndexByte(input, '/')
|
||||
|
||||
if np < 0 {
|
||||
i = ns
|
||||
} else if ns < 0 {
|
||||
i = np
|
||||
} else {
|
||||
i = int(math.Min(float64(np), float64(ns)))
|
||||
}
|
||||
if i < 0 {
|
||||
i = len(input)
|
||||
}
|
||||
params = append(params, input[:i])
|
||||
input = input[i:]
|
||||
continue
|
||||
}
|
||||
if len(input) == 0 || input[0] != c {
|
||||
return nil, "", false
|
||||
}
|
||||
pattern = pattern[1:]
|
||||
input = input[1:]
|
||||
}
|
||||
if input == "" {
|
||||
input = "/"
|
||||
}
|
||||
if input[0] != '/' {
|
||||
return nil, "", false
|
||||
}
|
||||
return params, input, true
|
||||
}
|
||||
|
||||
func (server *Server) Validate(c context.Context) (err error) {
|
||||
if server.URL == "" {
|
||||
return errors.New("value of url must be a non-empty JSON string")
|
||||
}
|
||||
for _, v := range server.Variables {
|
||||
if err = v.Validate(c); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ServerVariable is specified by OpenAPI/Swagger standard version 3.0.
|
||||
type ServerVariable struct {
|
||||
Enum []interface{} `json:"enum,omitempty" yaml:"enum,omitempty"`
|
||||
Default interface{} `json:"default,omitempty" yaml:"default,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
}
|
||||
|
||||
func (serverVariable *ServerVariable) Validate(c context.Context) error {
|
||||
switch serverVariable.Default.(type) {
|
||||
case float64, string:
|
||||
default:
|
||||
return errors.New("value of default must be either JSON number or JSON string")
|
||||
}
|
||||
for _, item := range serverVariable.Enum {
|
||||
switch item.(type) {
|
||||
case float64, string:
|
||||
default:
|
||||
return errors.New("Every variable 'enum' item must be number of string")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
104
vendor/github.com/getkin/kin-openapi/openapi3/swagger.go
generated
vendored
Normal file
104
vendor/github.com/getkin/kin-openapi/openapi3/swagger.go
generated
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/getkin/kin-openapi/jsoninfo"
|
||||
)
|
||||
|
||||
type Swagger struct {
|
||||
ExtensionProps
|
||||
OpenAPI string `json:"openapi" yaml:"openapi"` // Required
|
||||
Components Components `json:"components,omitempty" yaml:"components,omitempty"`
|
||||
Info *Info `json:"info" yaml:"info"` // Required
|
||||
Paths Paths `json:"paths" yaml:"paths"` // Required
|
||||
Security SecurityRequirements `json:"security,omitempty" yaml:"security,omitempty"`
|
||||
Servers Servers `json:"servers,omitempty" yaml:"servers,omitempty"`
|
||||
Tags Tags `json:"tags,omitempty" yaml:"tags,omitempty"`
|
||||
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
}
|
||||
|
||||
func (swagger *Swagger) MarshalJSON() ([]byte, error) {
|
||||
return jsoninfo.MarshalStrictStruct(swagger)
|
||||
}
|
||||
|
||||
func (swagger *Swagger) UnmarshalJSON(data []byte) error {
|
||||
return jsoninfo.UnmarshalStrictStruct(data, swagger)
|
||||
}
|
||||
|
||||
func (swagger *Swagger) AddOperation(path string, method string, operation *Operation) {
|
||||
paths := swagger.Paths
|
||||
if paths == nil {
|
||||
paths = make(Paths)
|
||||
swagger.Paths = paths
|
||||
}
|
||||
pathItem := paths[path]
|
||||
if pathItem == nil {
|
||||
pathItem = &PathItem{}
|
||||
paths[path] = pathItem
|
||||
}
|
||||
pathItem.SetOperation(method, operation)
|
||||
}
|
||||
|
||||
func (swagger *Swagger) AddServer(server *Server) {
|
||||
swagger.Servers = append(swagger.Servers, server)
|
||||
}
|
||||
|
||||
func (swagger *Swagger) Validate(c context.Context) error {
|
||||
if swagger.OpenAPI == "" {
|
||||
return errors.New("value of openapi must be a non-empty JSON string")
|
||||
}
|
||||
|
||||
// NOTE: only mention info/components/paths/... key in this func's errors.
|
||||
|
||||
{
|
||||
wrap := func(e error) error { return fmt.Errorf("invalid components: %v", e) }
|
||||
if err := swagger.Components.Validate(c); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
wrap := func(e error) error { return fmt.Errorf("invalid info: %v", e) }
|
||||
if v := swagger.Info; v != nil {
|
||||
if err := v.Validate(c); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
} else {
|
||||
return wrap(errors.New("must be a JSON object"))
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
wrap := func(e error) error { return fmt.Errorf("invalid paths: %v", e) }
|
||||
if v := swagger.Paths; v != nil {
|
||||
if err := v.Validate(c); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
} else {
|
||||
return wrap(errors.New("must be a JSON object"))
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
wrap := func(e error) error { return fmt.Errorf("invalid security: %v", e) }
|
||||
if v := swagger.Security; v != nil {
|
||||
if err := v.Validate(c); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
wrap := func(e error) error { return fmt.Errorf("invalid servers: %v", e) }
|
||||
if v := swagger.Servers; v != nil {
|
||||
if err := v.Validate(c); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
887
vendor/github.com/getkin/kin-openapi/openapi3/swagger_loader.go
generated
vendored
Normal file
887
vendor/github.com/getkin/kin-openapi/openapi3/swagger_loader.go
generated
vendored
Normal file
|
|
@ -0,0 +1,887 @@
|
|||
package openapi3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
)
|
||||
|
||||
func foundUnresolvedRef(ref string) error {
|
||||
return fmt.Errorf("Found unresolved ref: '%s'", ref)
|
||||
}
|
||||
|
||||
func failedToResolveRefFragment(value string) error {
|
||||
return fmt.Errorf("Failed to resolve fragment in URI: '%s'", value)
|
||||
}
|
||||
|
||||
func failedToResolveRefFragmentPart(value string, what string) error {
|
||||
return fmt.Errorf("Failed to resolve '%s' in fragment in URI: '%s'", what, value)
|
||||
}
|
||||
|
||||
type SwaggerLoader struct {
|
||||
IsExternalRefsAllowed bool
|
||||
Context context.Context
|
||||
LoadSwaggerFromURIFunc func(loader *SwaggerLoader, url *url.URL) (*Swagger, error)
|
||||
visited map[interface{}]struct{}
|
||||
visitedFiles map[string]struct{}
|
||||
}
|
||||
|
||||
func NewSwaggerLoader() *SwaggerLoader {
|
||||
return &SwaggerLoader{}
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) reset() {
|
||||
swaggerLoader.visitedFiles = make(map[string]struct{})
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) LoadSwaggerFromURI(location *url.URL) (*Swagger, error) {
|
||||
swaggerLoader.reset()
|
||||
return swaggerLoader.loadSwaggerFromURIInternal(location)
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) loadSwaggerFromURIInternal(location *url.URL) (*Swagger, error) {
|
||||
f := swaggerLoader.LoadSwaggerFromURIFunc
|
||||
if f != nil {
|
||||
return f(swaggerLoader, location)
|
||||
}
|
||||
data, err := readURL(location)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return swaggerLoader.loadSwaggerFromDataWithPathInternal(data, location)
|
||||
}
|
||||
|
||||
// loadSingleElementFromURI read the data from ref and unmarshal to JSON to the
|
||||
// passed element.
|
||||
func (swaggerLoader *SwaggerLoader) loadSingleElementFromURI(ref string, rootPath *url.URL, element json.Unmarshaler) error {
|
||||
if !swaggerLoader.IsExternalRefsAllowed {
|
||||
return fmt.Errorf("encountered non-allowed external reference: '%s'", ref)
|
||||
}
|
||||
|
||||
parsedURL, err := url.Parse(ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if parsedURL.Fragment != "" {
|
||||
return errors.New("references to files which contain more than one element definition are not supported")
|
||||
}
|
||||
|
||||
resolvedPath, err := resolvePath(rootPath, parsedURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not resolve path: %v", err)
|
||||
}
|
||||
|
||||
data, err := readURL(resolvedPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := yaml.Unmarshal(data, element); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readURL(location *url.URL) ([]byte, error) {
|
||||
if location.Scheme != "" && location.Host != "" {
|
||||
resp, err := http.Get(location.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
if location.Scheme != "" || location.Host != "" || location.RawQuery != "" {
|
||||
return nil, fmt.Errorf("Unsupported URI: '%s'", location.String())
|
||||
}
|
||||
data, err := ioutil.ReadFile(location.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) LoadSwaggerFromFile(path string) (*Swagger, error) {
|
||||
swaggerLoader.reset()
|
||||
return swaggerLoader.loadSwaggerFromFileInternal(path)
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) loadSwaggerFromFileInternal(path string) (*Swagger, error) {
|
||||
f := swaggerLoader.LoadSwaggerFromURIFunc
|
||||
if f != nil {
|
||||
return f(swaggerLoader, &url.URL{
|
||||
Path: path,
|
||||
})
|
||||
}
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return swaggerLoader.loadSwaggerFromDataWithPathInternal(data, &url.URL{
|
||||
Path: path,
|
||||
})
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) LoadSwaggerFromData(data []byte) (*Swagger, error) {
|
||||
swaggerLoader.reset()
|
||||
return swaggerLoader.loadSwaggerFromDataInternal(data)
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) loadSwaggerFromDataInternal(data []byte) (*Swagger, error) {
|
||||
swagger := &Swagger{}
|
||||
if err := yaml.Unmarshal(data, swagger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return swagger, swaggerLoader.ResolveRefsIn(swagger, nil)
|
||||
}
|
||||
|
||||
// LoadSwaggerFromDataWithPath takes the OpenApi spec data in bytes and a path where the resolver can find referred
|
||||
// elements and returns a *Swagger with all resolved data or an error if unable to load data or resolve refs.
|
||||
func (swaggerLoader *SwaggerLoader) LoadSwaggerFromDataWithPath(data []byte, path *url.URL) (*Swagger, error) {
|
||||
swaggerLoader.reset()
|
||||
return swaggerLoader.loadSwaggerFromDataWithPathInternal(data, path)
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) loadSwaggerFromDataWithPathInternal(data []byte, path *url.URL) (*Swagger, error) {
|
||||
swagger := &Swagger{}
|
||||
if err := yaml.Unmarshal(data, swagger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return swagger, swaggerLoader.ResolveRefsIn(swagger, path)
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) ResolveRefsIn(swagger *Swagger, path *url.URL) (err error) {
|
||||
swaggerLoader.visited = make(map[interface{}]struct{})
|
||||
if swaggerLoader.visitedFiles == nil {
|
||||
swaggerLoader.visitedFiles = make(map[string]struct{})
|
||||
}
|
||||
|
||||
// Visit all components
|
||||
components := swagger.Components
|
||||
for _, component := range components.Headers {
|
||||
if err = swaggerLoader.resolveHeaderRef(swagger, component, path); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, component := range components.Parameters {
|
||||
if err = swaggerLoader.resolveParameterRef(swagger, component, path); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, component := range components.RequestBodies {
|
||||
if err = swaggerLoader.resolveRequestBodyRef(swagger, component, path); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, component := range components.Responses {
|
||||
if err = swaggerLoader.resolveResponseRef(swagger, component, path); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, component := range components.Schemas {
|
||||
if err = swaggerLoader.resolveSchemaRef(swagger, component, path); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, component := range components.SecuritySchemes {
|
||||
if err = swaggerLoader.resolveSecuritySchemeRef(swagger, component, path); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, component := range components.Examples {
|
||||
if err = swaggerLoader.resolveExampleRef(swagger, component, path); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Visit all operations
|
||||
for entrypoint, pathItem := range swagger.Paths {
|
||||
if pathItem == nil {
|
||||
continue
|
||||
}
|
||||
if err = swaggerLoader.resolvePathItemRef(swagger, entrypoint, pathItem, path); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func copyURL(basePath *url.URL) (*url.URL, error) {
|
||||
return url.Parse(basePath.String())
|
||||
}
|
||||
|
||||
func join(basePath *url.URL, relativePath *url.URL) (*url.URL, error) {
|
||||
if basePath == nil {
|
||||
return relativePath, nil
|
||||
}
|
||||
newPath, err := copyURL(basePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Can't copy path: '%s'", basePath.String())
|
||||
}
|
||||
newPath.Path = path.Join(path.Dir(newPath.Path), relativePath.Path)
|
||||
return newPath, nil
|
||||
}
|
||||
|
||||
func resolvePath(basePath *url.URL, componentPath *url.URL) (*url.URL, error) {
|
||||
if componentPath.Scheme == "" && componentPath.Host == "" {
|
||||
return join(basePath, componentPath)
|
||||
}
|
||||
return componentPath, nil
|
||||
}
|
||||
|
||||
func isSingleRefElement(ref string) bool {
|
||||
return !strings.Contains(ref, "#")
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) resolveComponent(swagger *Swagger, ref string, path *url.URL) (
|
||||
cursor interface{},
|
||||
componentPath *url.URL,
|
||||
err error,
|
||||
) {
|
||||
if swagger, ref, componentPath, err = swaggerLoader.resolveRefSwagger(swagger, ref, path); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
parsedURL, err := url.Parse(ref)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Can't parse reference: '%s': %v", ref, parsedURL)
|
||||
}
|
||||
fragment := parsedURL.Fragment
|
||||
if !strings.HasPrefix(fragment, "/") {
|
||||
err := fmt.Errorf("expected fragment prefix '#/' in URI '%s'", ref)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
cursor = swagger
|
||||
for _, pathPart := range strings.Split(fragment[1:], "/") {
|
||||
|
||||
pathPart = strings.Replace(pathPart, "~1", "/", -1)
|
||||
pathPart = strings.Replace(pathPart, "~0", "~", -1)
|
||||
|
||||
if cursor, err = drillIntoSwaggerField(cursor, pathPart); err != nil {
|
||||
return nil, nil, fmt.Errorf("Failed to resolve '%s' in fragment in URI: '%s': %v", ref, pathPart, err.Error())
|
||||
}
|
||||
if cursor == nil {
|
||||
return nil, nil, failedToResolveRefFragmentPart(ref, pathPart)
|
||||
}
|
||||
}
|
||||
|
||||
return cursor, componentPath, nil
|
||||
}
|
||||
|
||||
func drillIntoSwaggerField(cursor interface{}, fieldName string) (interface{}, error) {
|
||||
switch val := reflect.Indirect(reflect.ValueOf(cursor)); val.Kind() {
|
||||
case reflect.Map:
|
||||
elementValue := val.MapIndex(reflect.ValueOf(fieldName))
|
||||
if !elementValue.IsValid() {
|
||||
return nil, fmt.Errorf("Map key not found: %v", fieldName)
|
||||
}
|
||||
return elementValue.Interface(), nil
|
||||
|
||||
case reflect.Slice:
|
||||
i, err := strconv.ParseUint(fieldName, 10, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
index := int(i)
|
||||
if index >= val.Len() {
|
||||
return nil, errors.New("slice index out of bounds")
|
||||
}
|
||||
return val.Index(index).Interface(), nil
|
||||
|
||||
case reflect.Struct:
|
||||
for i := 0; i < val.NumField(); i++ {
|
||||
field := val.Type().Field(i)
|
||||
tagValue := field.Tag.Get("yaml")
|
||||
yamlKey := strings.Split(tagValue, ",")[0]
|
||||
if yamlKey == fieldName {
|
||||
return val.Field(i).Interface(), nil
|
||||
}
|
||||
}
|
||||
// if cursor if a "ref wrapper" struct (e.g. RequestBodyRef), try digging into its Value field
|
||||
_, ok := val.Type().FieldByName("Value")
|
||||
if ok {
|
||||
return drillIntoSwaggerField(val.FieldByName("Value").Interface(), fieldName) // recurse into .Value
|
||||
}
|
||||
// give up
|
||||
return nil, fmt.Errorf("Struct field not found: %v", fieldName)
|
||||
|
||||
default:
|
||||
return nil, errors.New("not a map, slice nor struct")
|
||||
}
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) resolveRefSwagger(swagger *Swagger, ref string, path *url.URL) (*Swagger, string, *url.URL, error) {
|
||||
componentPath := path
|
||||
if !strings.HasPrefix(ref, "#") {
|
||||
if !swaggerLoader.IsExternalRefsAllowed {
|
||||
return nil, "", nil, fmt.Errorf("Encountered non-allowed external reference: '%s'", ref)
|
||||
}
|
||||
parsedURL, err := url.Parse(ref)
|
||||
if err != nil {
|
||||
return nil, "", nil, fmt.Errorf("Can't parse reference: '%s': %v", ref, parsedURL)
|
||||
}
|
||||
fragment := parsedURL.Fragment
|
||||
parsedURL.Fragment = ""
|
||||
|
||||
resolvedPath, err := resolvePath(path, parsedURL)
|
||||
if err != nil {
|
||||
return nil, "", nil, fmt.Errorf("Error while resolving path: %v", err)
|
||||
}
|
||||
|
||||
if swagger, err = swaggerLoader.loadSwaggerFromURIInternal(resolvedPath); err != nil {
|
||||
return nil, "", nil, fmt.Errorf("Error while resolving reference '%s': %v", ref, err)
|
||||
}
|
||||
ref = fmt.Sprintf("#%s", fragment)
|
||||
componentPath = resolvedPath
|
||||
}
|
||||
return swagger, ref, componentPath, nil
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) resolveHeaderRef(swagger *Swagger, component *HeaderRef, path *url.URL) error {
|
||||
visited := swaggerLoader.visited
|
||||
if _, isVisited := visited[component]; isVisited {
|
||||
return nil
|
||||
}
|
||||
visited[component] = struct{}{}
|
||||
|
||||
const prefix = "#/components/headers/"
|
||||
if component == nil {
|
||||
return errors.New("invalid header: value MUST be a JSON object")
|
||||
}
|
||||
if ref := component.Ref; len(ref) > 0 {
|
||||
if isSingleRefElement(ref) {
|
||||
var header Header
|
||||
if err := swaggerLoader.loadSingleElementFromURI(ref, path, &header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
component.Value = &header
|
||||
} else {
|
||||
untypedResolved, componentPath, err := swaggerLoader.resolveComponent(swagger, ref, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resolved, ok := untypedResolved.(*HeaderRef)
|
||||
if !ok {
|
||||
return failedToResolveRefFragment(ref)
|
||||
}
|
||||
if err := swaggerLoader.resolveHeaderRef(swagger, resolved, componentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
}
|
||||
}
|
||||
value := component.Value
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
if schema := value.Schema; schema != nil {
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, schema, path); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) resolveParameterRef(swagger *Swagger, component *ParameterRef, documentPath *url.URL) error {
|
||||
visited := swaggerLoader.visited
|
||||
if _, isVisited := visited[component]; isVisited {
|
||||
return nil
|
||||
}
|
||||
visited[component] = struct{}{}
|
||||
|
||||
const prefix = "#/components/parameters/"
|
||||
if component == nil {
|
||||
return errors.New("invalid parameter: value MUST be a JSON object")
|
||||
}
|
||||
ref := component.Ref
|
||||
if len(ref) > 0 {
|
||||
if isSingleRefElement(ref) {
|
||||
var param Parameter
|
||||
if err := swaggerLoader.loadSingleElementFromURI(ref, documentPath, ¶m); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = ¶m
|
||||
} else {
|
||||
untypedResolved, componentPath, err := swaggerLoader.resolveComponent(swagger, ref, documentPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resolved, ok := untypedResolved.(*ParameterRef)
|
||||
if !ok {
|
||||
return failedToResolveRefFragment(ref)
|
||||
}
|
||||
if err := swaggerLoader.resolveParameterRef(swagger, resolved, componentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
}
|
||||
}
|
||||
value := component.Value
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
refDocumentPath, err := referencedDocumentPath(documentPath, ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if value.Content != nil && value.Schema != nil {
|
||||
return errors.New("Cannot contain both schema and content in a parameter")
|
||||
}
|
||||
for _, contentType := range value.Content {
|
||||
if schema := contentType.Schema; schema != nil {
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, schema, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if schema := value.Schema; schema != nil {
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, schema, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) resolveRequestBodyRef(swagger *Swagger, component *RequestBodyRef, path *url.URL) error {
|
||||
visited := swaggerLoader.visited
|
||||
if _, isVisited := visited[component]; isVisited {
|
||||
return nil
|
||||
}
|
||||
visited[component] = struct{}{}
|
||||
|
||||
const prefix = "#/components/requestBodies/"
|
||||
if component == nil {
|
||||
return errors.New("invalid requestBody: value MUST be a JSON object")
|
||||
}
|
||||
if ref := component.Ref; len(ref) > 0 {
|
||||
if isSingleRefElement(ref) {
|
||||
var requestBody RequestBody
|
||||
if err := swaggerLoader.loadSingleElementFromURI(ref, path, &requestBody); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
component.Value = &requestBody
|
||||
} else {
|
||||
untypedResolved, componentPath, err := swaggerLoader.resolveComponent(swagger, ref, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resolved, ok := untypedResolved.(*RequestBodyRef)
|
||||
if !ok {
|
||||
return failedToResolveRefFragment(ref)
|
||||
}
|
||||
if err = swaggerLoader.resolveRequestBodyRef(swagger, resolved, componentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
}
|
||||
}
|
||||
value := component.Value
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
for _, contentType := range value.Content {
|
||||
for name, example := range contentType.Examples {
|
||||
if err := swaggerLoader.resolveExampleRef(swagger, example, path); err != nil {
|
||||
return err
|
||||
}
|
||||
contentType.Examples[name] = example
|
||||
}
|
||||
if schema := contentType.Schema; schema != nil {
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, schema, path); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) resolveResponseRef(swagger *Swagger, component *ResponseRef, documentPath *url.URL) error {
|
||||
visited := swaggerLoader.visited
|
||||
if _, isVisited := visited[component]; isVisited {
|
||||
return nil
|
||||
}
|
||||
visited[component] = struct{}{}
|
||||
|
||||
const prefix = "#/components/responses/"
|
||||
if component == nil {
|
||||
return errors.New("invalid response: value MUST be a JSON object")
|
||||
}
|
||||
ref := component.Ref
|
||||
if len(ref) > 0 {
|
||||
|
||||
if isSingleRefElement(ref) {
|
||||
var resp Response
|
||||
if err := swaggerLoader.loadSingleElementFromURI(ref, documentPath, &resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
component.Value = &resp
|
||||
} else {
|
||||
untypedResolved, componentPath, err := swaggerLoader.resolveComponent(swagger, ref, documentPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resolved, ok := untypedResolved.(*ResponseRef)
|
||||
if !ok {
|
||||
return failedToResolveRefFragment(ref)
|
||||
}
|
||||
if err := swaggerLoader.resolveResponseRef(swagger, resolved, componentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
}
|
||||
}
|
||||
refDocumentPath, err := referencedDocumentPath(documentPath, ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value := component.Value
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
for _, header := range value.Headers {
|
||||
if err := swaggerLoader.resolveHeaderRef(swagger, header, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, contentType := range value.Content {
|
||||
if contentType == nil {
|
||||
continue
|
||||
}
|
||||
for name, example := range contentType.Examples {
|
||||
if err := swaggerLoader.resolveExampleRef(swagger, example, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
contentType.Examples[name] = example
|
||||
}
|
||||
if schema := contentType.Schema; schema != nil {
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, schema, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
contentType.Schema = schema
|
||||
}
|
||||
}
|
||||
for _, link := range value.Links {
|
||||
if err := swaggerLoader.resolveLinkRef(swagger, link, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) resolveSchemaRef(swagger *Swagger, component *SchemaRef, documentPath *url.URL) error {
|
||||
visited := swaggerLoader.visited
|
||||
if _, isVisited := visited[component]; isVisited {
|
||||
return nil
|
||||
}
|
||||
visited[component] = struct{}{}
|
||||
|
||||
const prefix = "#/components/schemas/"
|
||||
if component == nil {
|
||||
return errors.New("invalid schema: value MUST be a JSON object")
|
||||
}
|
||||
ref := component.Ref
|
||||
if len(ref) > 0 {
|
||||
if isSingleRefElement(ref) {
|
||||
var schema Schema
|
||||
if err := swaggerLoader.loadSingleElementFromURI(ref, documentPath, &schema); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = &schema
|
||||
} else {
|
||||
untypedResolved, componentPath, err := swaggerLoader.resolveComponent(swagger, ref, documentPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resolved, ok := untypedResolved.(*SchemaRef)
|
||||
if !ok {
|
||||
return failedToResolveRefFragment(ref)
|
||||
}
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, resolved, componentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
}
|
||||
}
|
||||
|
||||
refDocumentPath, err := referencedDocumentPath(documentPath, ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value := component.Value
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResolveRefs referred schemas
|
||||
if v := value.Items; v != nil {
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, v, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, v := range value.Properties {
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, v, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if v := value.AdditionalProperties; v != nil {
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, v, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if v := value.Not; v != nil {
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, v, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, v := range value.AllOf {
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, v, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, v := range value.AnyOf {
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, v, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, v := range value.OneOf {
|
||||
if err := swaggerLoader.resolveSchemaRef(swagger, v, refDocumentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) resolveSecuritySchemeRef(swagger *Swagger, component *SecuritySchemeRef, path *url.URL) error {
|
||||
visited := swaggerLoader.visited
|
||||
if _, isVisited := visited[component]; isVisited {
|
||||
return nil
|
||||
}
|
||||
visited[component] = struct{}{}
|
||||
|
||||
const prefix = "#/components/securitySchemes/"
|
||||
if component == nil {
|
||||
return errors.New("invalid securityScheme: value MUST be a JSON object")
|
||||
}
|
||||
if ref := component.Ref; len(ref) > 0 {
|
||||
if isSingleRefElement(ref) {
|
||||
var scheme SecurityScheme
|
||||
if err := swaggerLoader.loadSingleElementFromURI(ref, path, &scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
component.Value = &scheme
|
||||
} else {
|
||||
untypedResolved, componentPath, err := swaggerLoader.resolveComponent(swagger, ref, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resolved, ok := untypedResolved.(*SecuritySchemeRef)
|
||||
if !ok {
|
||||
return failedToResolveRefFragment(ref)
|
||||
}
|
||||
if err := swaggerLoader.resolveSecuritySchemeRef(swagger, resolved, componentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) resolveExampleRef(swagger *Swagger, component *ExampleRef, path *url.URL) error {
|
||||
visited := swaggerLoader.visited
|
||||
if _, isVisited := visited[component]; isVisited {
|
||||
return nil
|
||||
}
|
||||
visited[component] = struct{}{}
|
||||
|
||||
const prefix = "#/components/examples/"
|
||||
if component == nil {
|
||||
return errors.New("invalid example: value MUST be a JSON object")
|
||||
}
|
||||
if ref := component.Ref; len(ref) > 0 {
|
||||
if isSingleRefElement(ref) {
|
||||
var example Example
|
||||
if err := swaggerLoader.loadSingleElementFromURI(ref, path, &example); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
component.Value = &example
|
||||
} else {
|
||||
untypedResolved, componentPath, err := swaggerLoader.resolveComponent(swagger, ref, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resolved, ok := untypedResolved.(*ExampleRef)
|
||||
if !ok {
|
||||
return failedToResolveRefFragment(ref)
|
||||
}
|
||||
if err := swaggerLoader.resolveExampleRef(swagger, resolved, componentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) resolveLinkRef(swagger *Swagger, component *LinkRef, path *url.URL) error {
|
||||
visited := swaggerLoader.visited
|
||||
if _, isVisited := visited[component]; isVisited {
|
||||
return nil
|
||||
}
|
||||
visited[component] = struct{}{}
|
||||
|
||||
const prefix = "#/components/links/"
|
||||
if component == nil {
|
||||
return errors.New("invalid link: value MUST be a JSON object")
|
||||
}
|
||||
if ref := component.Ref; len(ref) > 0 {
|
||||
if isSingleRefElement(ref) {
|
||||
var link Link
|
||||
if err := swaggerLoader.loadSingleElementFromURI(ref, path, &link); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
component.Value = &link
|
||||
} else {
|
||||
untypedResolved, componentPath, err := swaggerLoader.resolveComponent(swagger, ref, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resolved, ok := untypedResolved.(*LinkRef)
|
||||
if !ok {
|
||||
return failedToResolveRefFragment(ref)
|
||||
}
|
||||
if err := swaggerLoader.resolveLinkRef(swagger, resolved, componentPath); err != nil {
|
||||
return err
|
||||
}
|
||||
component.Value = resolved.Value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (swaggerLoader *SwaggerLoader) resolvePathItemRef(swagger *Swagger, entrypoint string, pathItem *PathItem, documentPath *url.URL) (err error) {
|
||||
visited := swaggerLoader.visitedFiles
|
||||
key := "_"
|
||||
if documentPath != nil {
|
||||
key = documentPath.EscapedPath()
|
||||
}
|
||||
key += entrypoint
|
||||
if _, isVisited := visited[key]; isVisited {
|
||||
return nil
|
||||
}
|
||||
visited[key] = struct{}{}
|
||||
|
||||
const prefix = "#/paths/"
|
||||
if pathItem == nil {
|
||||
return errors.New("invalid path item: value MUST be a JSON object")
|
||||
}
|
||||
ref := pathItem.Ref
|
||||
if ref != "" {
|
||||
if isSingleRefElement(ref) {
|
||||
var p PathItem
|
||||
if err := swaggerLoader.loadSingleElementFromURI(ref, documentPath, &p); err != nil {
|
||||
return err
|
||||
}
|
||||
*pathItem = p
|
||||
} else {
|
||||
if swagger, ref, documentPath, err = swaggerLoader.resolveRefSwagger(swagger, ref, documentPath); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(ref, prefix) {
|
||||
err = fmt.Errorf("expected prefix '%s' in URI '%s'", prefix, ref)
|
||||
return
|
||||
}
|
||||
id := unescapeRefString(ref[len(prefix):])
|
||||
|
||||
definitions := swagger.Paths
|
||||
if definitions == nil {
|
||||
return failedToResolveRefFragmentPart(ref, "paths")
|
||||
}
|
||||
resolved := definitions[id]
|
||||
if resolved == nil {
|
||||
return failedToResolveRefFragmentPart(ref, id)
|
||||
}
|
||||
|
||||
*pathItem = *resolved
|
||||
}
|
||||
}
|
||||
|
||||
refDocumentPath, err := referencedDocumentPath(documentPath, ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, parameter := range pathItem.Parameters {
|
||||
if err = swaggerLoader.resolveParameterRef(swagger, parameter, refDocumentPath); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, operation := range pathItem.Operations() {
|
||||
for _, parameter := range operation.Parameters {
|
||||
if err = swaggerLoader.resolveParameterRef(swagger, parameter, refDocumentPath); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if requestBody := operation.RequestBody; requestBody != nil {
|
||||
if err = swaggerLoader.resolveRequestBodyRef(swagger, requestBody, refDocumentPath); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, response := range operation.Responses {
|
||||
if err = swaggerLoader.resolveResponseRef(swagger, response, refDocumentPath); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func unescapeRefString(ref string) string {
|
||||
return strings.Replace(strings.Replace(ref, "~1", "/", -1), "~0", "~", -1)
|
||||
}
|
||||
|
||||
func referencedDocumentPath(documentPath *url.URL, ref string) (*url.URL, error) {
|
||||
newDocumentPath := documentPath
|
||||
if documentPath != nil {
|
||||
refDirectory, err := url.Parse(path.Dir(ref))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
joinedDirectory := path.Join(path.Dir(documentPath.String()), refDirectory.String())
|
||||
if newDocumentPath, err = url.Parse(joinedDirectory + "/"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return newDocumentPath, nil
|
||||
}
|
||||
20
vendor/github.com/getkin/kin-openapi/openapi3/tag.go
generated
vendored
Normal file
20
vendor/github.com/getkin/kin-openapi/openapi3/tag.go
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package openapi3
|
||||
|
||||
// Tags is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type Tags []*Tag
|
||||
|
||||
func (tags Tags) Get(name string) *Tag {
|
||||
for _, tag := range tags {
|
||||
if tag.Name == name {
|
||||
return tag
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Tag is specified by OpenAPI/Swagger 3.0 standard.
|
||||
type Tag struct {
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
}
|
||||
20
vendor/github.com/ghodss/yaml/.gitignore
generated
vendored
Normal file
20
vendor/github.com/ghodss/yaml/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# OSX leaves these everywhere on SMB shares
|
||||
._*
|
||||
|
||||
# Eclipse files
|
||||
.classpath
|
||||
.project
|
||||
.settings/**
|
||||
|
||||
# Emacs save files
|
||||
*~
|
||||
|
||||
# Vim-related files
|
||||
[._]*.s[a-w][a-z]
|
||||
[._]s[a-w][a-z]
|
||||
*.un~
|
||||
Session.vim
|
||||
.netrwhist
|
||||
|
||||
# Go test binaries
|
||||
*.test
|
||||
7
vendor/github.com/ghodss/yaml/.travis.yml
generated
vendored
Normal file
7
vendor/github.com/ghodss/yaml/.travis.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
language: go
|
||||
go:
|
||||
- 1.3
|
||||
- 1.4
|
||||
script:
|
||||
- go test
|
||||
- go build
|
||||
50
vendor/github.com/ghodss/yaml/LICENSE
generated
vendored
Normal file
50
vendor/github.com/ghodss/yaml/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Sam Ghods
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
121
vendor/github.com/ghodss/yaml/README.md
generated
vendored
Normal file
121
vendor/github.com/ghodss/yaml/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
# YAML marshaling and unmarshaling support for Go
|
||||
|
||||
[](https://travis-ci.org/ghodss/yaml)
|
||||
|
||||
## Introduction
|
||||
|
||||
A wrapper around [go-yaml](https://github.com/go-yaml/yaml) designed to enable a better way of handling YAML when marshaling to and from structs.
|
||||
|
||||
In short, this library first converts YAML to JSON using go-yaml and then uses `json.Marshal` and `json.Unmarshal` to convert to or from the struct. This means that it effectively reuses the JSON struct tags as well as the custom JSON methods `MarshalJSON` and `UnmarshalJSON` unlike go-yaml. For a detailed overview of the rationale behind this method, [see this blog post](http://ghodss.com/2014/the-right-way-to-handle-yaml-in-golang/).
|
||||
|
||||
## Compatibility
|
||||
|
||||
This package uses [go-yaml](https://github.com/go-yaml/yaml) and therefore supports [everything go-yaml supports](https://github.com/go-yaml/yaml#compatibility).
|
||||
|
||||
## Caveats
|
||||
|
||||
**Caveat #1:** When using `yaml.Marshal` and `yaml.Unmarshal`, binary data should NOT be preceded with the `!!binary` YAML tag. If you do, go-yaml will convert the binary data from base64 to native binary data, which is not compatible with JSON. You can still use binary in your YAML files though - just store them without the `!!binary` tag and decode the base64 in your code (e.g. in the custom JSON methods `MarshalJSON` and `UnmarshalJSON`). This also has the benefit that your YAML and your JSON binary data will be decoded exactly the same way. As an example:
|
||||
|
||||
```
|
||||
BAD:
|
||||
exampleKey: !!binary gIGC
|
||||
|
||||
GOOD:
|
||||
exampleKey: gIGC
|
||||
... and decode the base64 data in your code.
|
||||
```
|
||||
|
||||
**Caveat #2:** When using `YAMLToJSON` directly, maps with keys that are maps will result in an error since this is not supported by JSON. This error will occur in `Unmarshal` as well since you can't unmarshal map keys anyways since struct fields can't be keys.
|
||||
|
||||
## Installation and usage
|
||||
|
||||
To install, run:
|
||||
|
||||
```
|
||||
$ go get github.com/ghodss/yaml
|
||||
```
|
||||
|
||||
And import using:
|
||||
|
||||
```
|
||||
import "github.com/ghodss/yaml"
|
||||
```
|
||||
|
||||
Usage is very similar to the JSON library:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
)
|
||||
|
||||
type Person struct {
|
||||
Name string `json:"name"` // Affects YAML field names too.
|
||||
Age int `json:"age"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Marshal a Person struct to YAML.
|
||||
p := Person{"John", 30}
|
||||
y, err := yaml.Marshal(p)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(y))
|
||||
/* Output:
|
||||
age: 30
|
||||
name: John
|
||||
*/
|
||||
|
||||
// Unmarshal the YAML back into a Person struct.
|
||||
var p2 Person
|
||||
err = yaml.Unmarshal(y, &p2)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(p2)
|
||||
/* Output:
|
||||
{John 30}
|
||||
*/
|
||||
}
|
||||
```
|
||||
|
||||
`yaml.YAMLToJSON` and `yaml.JSONToYAML` methods are also available:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
)
|
||||
|
||||
func main() {
|
||||
j := []byte(`{"name": "John", "age": 30}`)
|
||||
y, err := yaml.JSONToYAML(j)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(y))
|
||||
/* Output:
|
||||
name: John
|
||||
age: 30
|
||||
*/
|
||||
j2, err := yaml.YAMLToJSON(y)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(j2))
|
||||
/* Output:
|
||||
{"age":30,"name":"John"}
|
||||
*/
|
||||
}
|
||||
```
|
||||
501
vendor/github.com/ghodss/yaml/fields.go
generated
vendored
Normal file
501
vendor/github.com/ghodss/yaml/fields.go
generated
vendored
Normal file
|
|
@ -0,0 +1,501 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// indirect walks down v allocating pointers as needed,
|
||||
// until it gets to a non-pointer.
|
||||
// if it encounters an Unmarshaler, indirect stops and returns that.
|
||||
// if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
|
||||
func indirect(v reflect.Value, decodingNull bool) (json.Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
|
||||
// If v is a named type and is addressable,
|
||||
// start with its address, so that if the type has pointer methods,
|
||||
// we find them.
|
||||
if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
|
||||
v = v.Addr()
|
||||
}
|
||||
for {
|
||||
// Load value from interface, but only if the result will be
|
||||
// usefully addressable.
|
||||
if v.Kind() == reflect.Interface && !v.IsNil() {
|
||||
e := v.Elem()
|
||||
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
|
||||
v = e
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if v.Kind() != reflect.Ptr {
|
||||
break
|
||||
}
|
||||
|
||||
if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
|
||||
break
|
||||
}
|
||||
if v.IsNil() {
|
||||
if v.CanSet() {
|
||||
v.Set(reflect.New(v.Type().Elem()))
|
||||
} else {
|
||||
v = reflect.New(v.Type().Elem())
|
||||
}
|
||||
}
|
||||
if v.Type().NumMethod() > 0 {
|
||||
if u, ok := v.Interface().(json.Unmarshaler); ok {
|
||||
return u, nil, reflect.Value{}
|
||||
}
|
||||
if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
|
||||
return nil, u, reflect.Value{}
|
||||
}
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
return nil, nil, v
|
||||
}
|
||||
|
||||
// A field represents a single field found in a struct.
|
||||
type field struct {
|
||||
name string
|
||||
nameBytes []byte // []byte(name)
|
||||
equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent
|
||||
|
||||
tag bool
|
||||
index []int
|
||||
typ reflect.Type
|
||||
omitEmpty bool
|
||||
quoted bool
|
||||
}
|
||||
|
||||
func fillField(f field) field {
|
||||
f.nameBytes = []byte(f.name)
|
||||
f.equalFold = foldFunc(f.nameBytes)
|
||||
return f
|
||||
}
|
||||
|
||||
// byName sorts field by name, breaking ties with depth,
|
||||
// then breaking ties with "name came from json tag", then
|
||||
// breaking ties with index sequence.
|
||||
type byName []field
|
||||
|
||||
func (x byName) Len() int { return len(x) }
|
||||
|
||||
func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
|
||||
func (x byName) Less(i, j int) bool {
|
||||
if x[i].name != x[j].name {
|
||||
return x[i].name < x[j].name
|
||||
}
|
||||
if len(x[i].index) != len(x[j].index) {
|
||||
return len(x[i].index) < len(x[j].index)
|
||||
}
|
||||
if x[i].tag != x[j].tag {
|
||||
return x[i].tag
|
||||
}
|
||||
return byIndex(x).Less(i, j)
|
||||
}
|
||||
|
||||
// byIndex sorts field by index sequence.
|
||||
type byIndex []field
|
||||
|
||||
func (x byIndex) Len() int { return len(x) }
|
||||
|
||||
func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
|
||||
func (x byIndex) Less(i, j int) bool {
|
||||
for k, xik := range x[i].index {
|
||||
if k >= len(x[j].index) {
|
||||
return false
|
||||
}
|
||||
if xik != x[j].index[k] {
|
||||
return xik < x[j].index[k]
|
||||
}
|
||||
}
|
||||
return len(x[i].index) < len(x[j].index)
|
||||
}
|
||||
|
||||
// typeFields returns a list of fields that JSON should recognize for the given type.
|
||||
// The algorithm is breadth-first search over the set of structs to include - the top struct
|
||||
// and then any reachable anonymous structs.
|
||||
func typeFields(t reflect.Type) []field {
|
||||
// Anonymous fields to explore at the current level and the next.
|
||||
current := []field{}
|
||||
next := []field{{typ: t}}
|
||||
|
||||
// Count of queued names for current level and the next.
|
||||
count := map[reflect.Type]int{}
|
||||
nextCount := map[reflect.Type]int{}
|
||||
|
||||
// Types already visited at an earlier level.
|
||||
visited := map[reflect.Type]bool{}
|
||||
|
||||
// Fields found.
|
||||
var fields []field
|
||||
|
||||
for len(next) > 0 {
|
||||
current, next = next, current[:0]
|
||||
count, nextCount = nextCount, map[reflect.Type]int{}
|
||||
|
||||
for _, f := range current {
|
||||
if visited[f.typ] {
|
||||
continue
|
||||
}
|
||||
visited[f.typ] = true
|
||||
|
||||
// Scan f.typ for fields to include.
|
||||
for i := 0; i < f.typ.NumField(); i++ {
|
||||
sf := f.typ.Field(i)
|
||||
if sf.PkgPath != "" { // unexported
|
||||
continue
|
||||
}
|
||||
tag := sf.Tag.Get("json")
|
||||
if tag == "-" {
|
||||
continue
|
||||
}
|
||||
name, opts := parseTag(tag)
|
||||
if !isValidTag(name) {
|
||||
name = ""
|
||||
}
|
||||
index := make([]int, len(f.index)+1)
|
||||
copy(index, f.index)
|
||||
index[len(f.index)] = i
|
||||
|
||||
ft := sf.Type
|
||||
if ft.Name() == "" && ft.Kind() == reflect.Ptr {
|
||||
// Follow pointer.
|
||||
ft = ft.Elem()
|
||||
}
|
||||
|
||||
// Record found field and index sequence.
|
||||
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
||||
tagged := name != ""
|
||||
if name == "" {
|
||||
name = sf.Name
|
||||
}
|
||||
fields = append(fields, fillField(field{
|
||||
name: name,
|
||||
tag: tagged,
|
||||
index: index,
|
||||
typ: ft,
|
||||
omitEmpty: opts.Contains("omitempty"),
|
||||
quoted: opts.Contains("string"),
|
||||
}))
|
||||
if count[f.typ] > 1 {
|
||||
// If there were multiple instances, add a second,
|
||||
// so that the annihilation code will see a duplicate.
|
||||
// It only cares about the distinction between 1 or 2,
|
||||
// so don't bother generating any more copies.
|
||||
fields = append(fields, fields[len(fields)-1])
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Record new anonymous struct to explore in next round.
|
||||
nextCount[ft]++
|
||||
if nextCount[ft] == 1 {
|
||||
next = append(next, fillField(field{name: ft.Name(), index: index, typ: ft}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort.Sort(byName(fields))
|
||||
|
||||
// Delete all fields that are hidden by the Go rules for embedded fields,
|
||||
// except that fields with JSON tags are promoted.
|
||||
|
||||
// The fields are sorted in primary order of name, secondary order
|
||||
// of field index length. Loop over names; for each name, delete
|
||||
// hidden fields by choosing the one dominant field that survives.
|
||||
out := fields[:0]
|
||||
for advance, i := 0, 0; i < len(fields); i += advance {
|
||||
// One iteration per name.
|
||||
// Find the sequence of fields with the name of this first field.
|
||||
fi := fields[i]
|
||||
name := fi.name
|
||||
for advance = 1; i+advance < len(fields); advance++ {
|
||||
fj := fields[i+advance]
|
||||
if fj.name != name {
|
||||
break
|
||||
}
|
||||
}
|
||||
if advance == 1 { // Only one field with this name
|
||||
out = append(out, fi)
|
||||
continue
|
||||
}
|
||||
dominant, ok := dominantField(fields[i : i+advance])
|
||||
if ok {
|
||||
out = append(out, dominant)
|
||||
}
|
||||
}
|
||||
|
||||
fields = out
|
||||
sort.Sort(byIndex(fields))
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
// dominantField looks through the fields, all of which are known to
|
||||
// have the same name, to find the single field that dominates the
|
||||
// others using Go's embedding rules, modified by the presence of
|
||||
// JSON tags. If there are multiple top-level fields, the boolean
|
||||
// will be false: This condition is an error in Go and we skip all
|
||||
// the fields.
|
||||
func dominantField(fields []field) (field, bool) {
|
||||
// The fields are sorted in increasing index-length order. The winner
|
||||
// must therefore be one with the shortest index length. Drop all
|
||||
// longer entries, which is easy: just truncate the slice.
|
||||
length := len(fields[0].index)
|
||||
tagged := -1 // Index of first tagged field.
|
||||
for i, f := range fields {
|
||||
if len(f.index) > length {
|
||||
fields = fields[:i]
|
||||
break
|
||||
}
|
||||
if f.tag {
|
||||
if tagged >= 0 {
|
||||
// Multiple tagged fields at the same level: conflict.
|
||||
// Return no field.
|
||||
return field{}, false
|
||||
}
|
||||
tagged = i
|
||||
}
|
||||
}
|
||||
if tagged >= 0 {
|
||||
return fields[tagged], true
|
||||
}
|
||||
// All remaining fields have the same length. If there's more than one,
|
||||
// we have a conflict (two fields named "X" at the same level) and we
|
||||
// return no field.
|
||||
if len(fields) > 1 {
|
||||
return field{}, false
|
||||
}
|
||||
return fields[0], true
|
||||
}
|
||||
|
||||
var fieldCache struct {
|
||||
sync.RWMutex
|
||||
m map[reflect.Type][]field
|
||||
}
|
||||
|
||||
// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
|
||||
func cachedTypeFields(t reflect.Type) []field {
|
||||
fieldCache.RLock()
|
||||
f := fieldCache.m[t]
|
||||
fieldCache.RUnlock()
|
||||
if f != nil {
|
||||
return f
|
||||
}
|
||||
|
||||
// Compute fields without lock.
|
||||
// Might duplicate effort but won't hold other computations back.
|
||||
f = typeFields(t)
|
||||
if f == nil {
|
||||
f = []field{}
|
||||
}
|
||||
|
||||
fieldCache.Lock()
|
||||
if fieldCache.m == nil {
|
||||
fieldCache.m = map[reflect.Type][]field{}
|
||||
}
|
||||
fieldCache.m[t] = f
|
||||
fieldCache.Unlock()
|
||||
return f
|
||||
}
|
||||
|
||||
func isValidTag(s string) bool {
|
||||
if s == "" {
|
||||
return false
|
||||
}
|
||||
for _, c := range s {
|
||||
switch {
|
||||
case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
|
||||
// Backslash and quote chars are reserved, but
|
||||
// otherwise any punctuation chars are allowed
|
||||
// in a tag name.
|
||||
default:
|
||||
if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const (
|
||||
caseMask = ^byte(0x20) // Mask to ignore case in ASCII.
|
||||
kelvin = '\u212a'
|
||||
smallLongEss = '\u017f'
|
||||
)
|
||||
|
||||
// foldFunc returns one of four different case folding equivalence
|
||||
// functions, from most general (and slow) to fastest:
|
||||
//
|
||||
// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
|
||||
// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
|
||||
// 3) asciiEqualFold, no special, but includes non-letters (including _)
|
||||
// 4) simpleLetterEqualFold, no specials, no non-letters.
|
||||
//
|
||||
// The letters S and K are special because they map to 3 runes, not just 2:
|
||||
// * S maps to s and to U+017F 'ſ' Latin small letter long s
|
||||
// * k maps to K and to U+212A 'K' Kelvin sign
|
||||
// See http://play.golang.org/p/tTxjOc0OGo
|
||||
//
|
||||
// The returned function is specialized for matching against s and
|
||||
// should only be given s. It's not curried for performance reasons.
|
||||
func foldFunc(s []byte) func(s, t []byte) bool {
|
||||
nonLetter := false
|
||||
special := false // special letter
|
||||
for _, b := range s {
|
||||
if b >= utf8.RuneSelf {
|
||||
return bytes.EqualFold
|
||||
}
|
||||
upper := b & caseMask
|
||||
if upper < 'A' || upper > 'Z' {
|
||||
nonLetter = true
|
||||
} else if upper == 'K' || upper == 'S' {
|
||||
// See above for why these letters are special.
|
||||
special = true
|
||||
}
|
||||
}
|
||||
if special {
|
||||
return equalFoldRight
|
||||
}
|
||||
if nonLetter {
|
||||
return asciiEqualFold
|
||||
}
|
||||
return simpleLetterEqualFold
|
||||
}
|
||||
|
||||
// equalFoldRight is a specialization of bytes.EqualFold when s is
|
||||
// known to be all ASCII (including punctuation), but contains an 's',
|
||||
// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
|
||||
// See comments on foldFunc.
|
||||
func equalFoldRight(s, t []byte) bool {
|
||||
for _, sb := range s {
|
||||
if len(t) == 0 {
|
||||
return false
|
||||
}
|
||||
tb := t[0]
|
||||
if tb < utf8.RuneSelf {
|
||||
if sb != tb {
|
||||
sbUpper := sb & caseMask
|
||||
if 'A' <= sbUpper && sbUpper <= 'Z' {
|
||||
if sbUpper != tb&caseMask {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
t = t[1:]
|
||||
continue
|
||||
}
|
||||
// sb is ASCII and t is not. t must be either kelvin
|
||||
// sign or long s; sb must be s, S, k, or K.
|
||||
tr, size := utf8.DecodeRune(t)
|
||||
switch sb {
|
||||
case 's', 'S':
|
||||
if tr != smallLongEss {
|
||||
return false
|
||||
}
|
||||
case 'k', 'K':
|
||||
if tr != kelvin {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
t = t[size:]
|
||||
|
||||
}
|
||||
if len(t) > 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// asciiEqualFold is a specialization of bytes.EqualFold for use when
|
||||
// s is all ASCII (but may contain non-letters) and contains no
|
||||
// special-folding letters.
|
||||
// See comments on foldFunc.
|
||||
func asciiEqualFold(s, t []byte) bool {
|
||||
if len(s) != len(t) {
|
||||
return false
|
||||
}
|
||||
for i, sb := range s {
|
||||
tb := t[i]
|
||||
if sb == tb {
|
||||
continue
|
||||
}
|
||||
if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
|
||||
if sb&caseMask != tb&caseMask {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// simpleLetterEqualFold is a specialization of bytes.EqualFold for
|
||||
// use when s is all ASCII letters (no underscores, etc) and also
|
||||
// doesn't contain 'k', 'K', 's', or 'S'.
|
||||
// See comments on foldFunc.
|
||||
func simpleLetterEqualFold(s, t []byte) bool {
|
||||
if len(s) != len(t) {
|
||||
return false
|
||||
}
|
||||
for i, b := range s {
|
||||
if b&caseMask != t[i]&caseMask {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// tagOptions is the string following a comma in a struct field's "json"
|
||||
// tag, or the empty string. It does not include the leading comma.
|
||||
type tagOptions string
|
||||
|
||||
// parseTag splits a struct field's json tag into its name and
|
||||
// comma-separated options.
|
||||
func parseTag(tag string) (string, tagOptions) {
|
||||
if idx := strings.Index(tag, ","); idx != -1 {
|
||||
return tag[:idx], tagOptions(tag[idx+1:])
|
||||
}
|
||||
return tag, tagOptions("")
|
||||
}
|
||||
|
||||
// Contains reports whether a comma-separated list of options
|
||||
// contains a particular substr flag. substr must be surrounded by a
|
||||
// string boundary or commas.
|
||||
func (o tagOptions) Contains(optionName string) bool {
|
||||
if len(o) == 0 {
|
||||
return false
|
||||
}
|
||||
s := string(o)
|
||||
for s != "" {
|
||||
var next string
|
||||
i := strings.Index(s, ",")
|
||||
if i >= 0 {
|
||||
s, next = s[:i], s[i+1:]
|
||||
}
|
||||
if s == optionName {
|
||||
return true
|
||||
}
|
||||
s = next
|
||||
}
|
||||
return false
|
||||
}
|
||||
277
vendor/github.com/ghodss/yaml/yaml.go
generated
vendored
Normal file
277
vendor/github.com/ghodss/yaml/yaml.go
generated
vendored
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Marshals the object into JSON then converts JSON to YAML and returns the
|
||||
// YAML.
|
||||
func Marshal(o interface{}) ([]byte, error) {
|
||||
j, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling into JSON: %v", err)
|
||||
}
|
||||
|
||||
y, err := JSONToYAML(j)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error converting JSON to YAML: %v", err)
|
||||
}
|
||||
|
||||
return y, nil
|
||||
}
|
||||
|
||||
// Converts YAML to JSON then uses JSON to unmarshal into an object.
|
||||
func Unmarshal(y []byte, o interface{}) error {
|
||||
vo := reflect.ValueOf(o)
|
||||
j, err := yamlToJSON(y, &vo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error converting YAML to JSON: %v", err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(j, o)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error unmarshaling JSON: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert JSON to YAML.
|
||||
func JSONToYAML(j []byte) ([]byte, error) {
|
||||
// Convert the JSON to an object.
|
||||
var jsonObj interface{}
|
||||
// We are using yaml.Unmarshal here (instead of json.Unmarshal) because the
|
||||
// Go JSON library doesn't try to pick the right number type (int, float,
|
||||
// etc.) when unmarshalling to interface{}, it just picks float64
|
||||
// universally. go-yaml does go through the effort of picking the right
|
||||
// number type, so we can preserve number type throughout this process.
|
||||
err := yaml.Unmarshal(j, &jsonObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Marshal this object into YAML.
|
||||
return yaml.Marshal(jsonObj)
|
||||
}
|
||||
|
||||
// Convert YAML to JSON. Since JSON is a subset of YAML, passing JSON through
|
||||
// this method should be a no-op.
|
||||
//
|
||||
// Things YAML can do that are not supported by JSON:
|
||||
// * In YAML you can have binary and null keys in your maps. These are invalid
|
||||
// in JSON. (int and float keys are converted to strings.)
|
||||
// * Binary data in YAML with the !!binary tag is not supported. If you want to
|
||||
// use binary data with this library, encode the data as base64 as usual but do
|
||||
// not use the !!binary tag in your YAML. This will ensure the original base64
|
||||
// encoded data makes it all the way through to the JSON.
|
||||
func YAMLToJSON(y []byte) ([]byte, error) {
|
||||
return yamlToJSON(y, nil)
|
||||
}
|
||||
|
||||
func yamlToJSON(y []byte, jsonTarget *reflect.Value) ([]byte, error) {
|
||||
// Convert the YAML to an object.
|
||||
var yamlObj interface{}
|
||||
err := yaml.Unmarshal(y, &yamlObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// YAML objects are not completely compatible with JSON objects (e.g. you
|
||||
// can have non-string keys in YAML). So, convert the YAML-compatible object
|
||||
// to a JSON-compatible object, failing with an error if irrecoverable
|
||||
// incompatibilties happen along the way.
|
||||
jsonObj, err := convertToJSONableObject(yamlObj, jsonTarget)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert this object to JSON and return the data.
|
||||
return json.Marshal(jsonObj)
|
||||
}
|
||||
|
||||
func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (interface{}, error) {
|
||||
var err error
|
||||
|
||||
// Resolve jsonTarget to a concrete value (i.e. not a pointer or an
|
||||
// interface). We pass decodingNull as false because we're not actually
|
||||
// decoding into the value, we're just checking if the ultimate target is a
|
||||
// string.
|
||||
if jsonTarget != nil {
|
||||
ju, tu, pv := indirect(*jsonTarget, false)
|
||||
// We have a JSON or Text Umarshaler at this level, so we can't be trying
|
||||
// to decode into a string.
|
||||
if ju != nil || tu != nil {
|
||||
jsonTarget = nil
|
||||
} else {
|
||||
jsonTarget = &pv
|
||||
}
|
||||
}
|
||||
|
||||
// If yamlObj is a number or a boolean, check if jsonTarget is a string -
|
||||
// if so, coerce. Else return normal.
|
||||
// If yamlObj is a map or array, find the field that each key is
|
||||
// unmarshaling to, and when you recurse pass the reflect.Value for that
|
||||
// field back into this function.
|
||||
switch typedYAMLObj := yamlObj.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
// JSON does not support arbitrary keys in a map, so we must convert
|
||||
// these keys to strings.
|
||||
//
|
||||
// From my reading of go-yaml v2 (specifically the resolve function),
|
||||
// keys can only have the types string, int, int64, float64, binary
|
||||
// (unsupported), or null (unsupported).
|
||||
strMap := make(map[string]interface{})
|
||||
for k, v := range typedYAMLObj {
|
||||
// Resolve the key to a string first.
|
||||
var keyString string
|
||||
switch typedKey := k.(type) {
|
||||
case string:
|
||||
keyString = typedKey
|
||||
case int:
|
||||
keyString = strconv.Itoa(typedKey)
|
||||
case int64:
|
||||
// go-yaml will only return an int64 as a key if the system
|
||||
// architecture is 32-bit and the key's value is between 32-bit
|
||||
// and 64-bit. Otherwise the key type will simply be int.
|
||||
keyString = strconv.FormatInt(typedKey, 10)
|
||||
case float64:
|
||||
// Stolen from go-yaml to use the same conversion to string as
|
||||
// the go-yaml library uses to convert float to string when
|
||||
// Marshaling.
|
||||
s := strconv.FormatFloat(typedKey, 'g', -1, 32)
|
||||
switch s {
|
||||
case "+Inf":
|
||||
s = ".inf"
|
||||
case "-Inf":
|
||||
s = "-.inf"
|
||||
case "NaN":
|
||||
s = ".nan"
|
||||
}
|
||||
keyString = s
|
||||
case bool:
|
||||
if typedKey {
|
||||
keyString = "true"
|
||||
} else {
|
||||
keyString = "false"
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("Unsupported map key of type: %s, key: %+#v, value: %+#v",
|
||||
reflect.TypeOf(k), k, v)
|
||||
}
|
||||
|
||||
// jsonTarget should be a struct or a map. If it's a struct, find
|
||||
// the field it's going to map to and pass its reflect.Value. If
|
||||
// it's a map, find the element type of the map and pass the
|
||||
// reflect.Value created from that type. If it's neither, just pass
|
||||
// nil - JSON conversion will error for us if it's a real issue.
|
||||
if jsonTarget != nil {
|
||||
t := *jsonTarget
|
||||
if t.Kind() == reflect.Struct {
|
||||
keyBytes := []byte(keyString)
|
||||
// Find the field that the JSON library would use.
|
||||
var f *field
|
||||
fields := cachedTypeFields(t.Type())
|
||||
for i := range fields {
|
||||
ff := &fields[i]
|
||||
if bytes.Equal(ff.nameBytes, keyBytes) {
|
||||
f = ff
|
||||
break
|
||||
}
|
||||
// Do case-insensitive comparison.
|
||||
if f == nil && ff.equalFold(ff.nameBytes, keyBytes) {
|
||||
f = ff
|
||||
}
|
||||
}
|
||||
if f != nil {
|
||||
// Find the reflect.Value of the most preferential
|
||||
// struct field.
|
||||
jtf := t.Field(f.index[0])
|
||||
strMap[keyString], err = convertToJSONableObject(v, &jtf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
} else if t.Kind() == reflect.Map {
|
||||
// Create a zero value of the map's element type to use as
|
||||
// the JSON target.
|
||||
jtv := reflect.Zero(t.Type().Elem())
|
||||
strMap[keyString], err = convertToJSONableObject(v, &jtv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
strMap[keyString], err = convertToJSONableObject(v, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return strMap, nil
|
||||
case []interface{}:
|
||||
// We need to recurse into arrays in case there are any
|
||||
// map[interface{}]interface{}'s inside and to convert any
|
||||
// numbers to strings.
|
||||
|
||||
// If jsonTarget is a slice (which it really should be), find the
|
||||
// thing it's going to map to. If it's not a slice, just pass nil
|
||||
// - JSON conversion will error for us if it's a real issue.
|
||||
var jsonSliceElemValue *reflect.Value
|
||||
if jsonTarget != nil {
|
||||
t := *jsonTarget
|
||||
if t.Kind() == reflect.Slice {
|
||||
// By default slices point to nil, but we need a reflect.Value
|
||||
// pointing to a value of the slice type, so we create one here.
|
||||
ev := reflect.Indirect(reflect.New(t.Type().Elem()))
|
||||
jsonSliceElemValue = &ev
|
||||
}
|
||||
}
|
||||
|
||||
// Make and use a new array.
|
||||
arr := make([]interface{}, len(typedYAMLObj))
|
||||
for i, v := range typedYAMLObj {
|
||||
arr[i], err = convertToJSONableObject(v, jsonSliceElemValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return arr, nil
|
||||
default:
|
||||
// If the target type is a string and the YAML type is a number,
|
||||
// convert the YAML type to a string.
|
||||
if jsonTarget != nil && (*jsonTarget).Kind() == reflect.String {
|
||||
// Based on my reading of go-yaml, it may return int, int64,
|
||||
// float64, or uint64.
|
||||
var s string
|
||||
switch typedVal := typedYAMLObj.(type) {
|
||||
case int:
|
||||
s = strconv.FormatInt(int64(typedVal), 10)
|
||||
case int64:
|
||||
s = strconv.FormatInt(typedVal, 10)
|
||||
case float64:
|
||||
s = strconv.FormatFloat(typedVal, 'g', -1, 32)
|
||||
case uint64:
|
||||
s = strconv.FormatUint(typedVal, 10)
|
||||
case bool:
|
||||
if typedVal {
|
||||
s = "true"
|
||||
} else {
|
||||
s = "false"
|
||||
}
|
||||
}
|
||||
if len(s) > 0 {
|
||||
yamlObj = interface{}(s)
|
||||
}
|
||||
}
|
||||
return yamlObj, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
9
vendor/modules.txt
vendored
9
vendor/modules.txt
vendored
|
|
@ -78,12 +78,21 @@ github.com/coreos/go-systemd/activation
|
|||
# github.com/davecgh/go-spew v1.1.1
|
||||
github.com/davecgh/go-spew/spew
|
||||
# github.com/deepmap/oapi-codegen v1.3.12
|
||||
github.com/deepmap/oapi-codegen/cmd/oapi-codegen
|
||||
github.com/deepmap/oapi-codegen/pkg/codegen
|
||||
github.com/deepmap/oapi-codegen/pkg/codegen/templates
|
||||
github.com/deepmap/oapi-codegen/pkg/runtime
|
||||
github.com/deepmap/oapi-codegen/pkg/types
|
||||
github.com/deepmap/oapi-codegen/pkg/util
|
||||
# github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/dgrijalva/jwt-go
|
||||
# github.com/dimchansky/utfbom v1.1.0
|
||||
github.com/dimchansky/utfbom
|
||||
# github.com/getkin/kin-openapi v0.13.0
|
||||
github.com/getkin/kin-openapi/jsoninfo
|
||||
github.com/getkin/kin-openapi/openapi3
|
||||
# github.com/ghodss/yaml v1.0.0
|
||||
github.com/ghodss/yaml
|
||||
# github.com/go-chi/chi v4.0.2+incompatible
|
||||
github.com/go-chi/chi
|
||||
# github.com/gobwas/glob v0.2.3
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue