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
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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue