diff --git a/.gitignore b/.gitignore index f0b76c07e..c56fb65bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ .idea .DS_Store -.vscode/ \ No newline at end of file +.vscode/ +coverage-all.out +coverage.out +test-coverage.html +test-results.out diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 000000000..b5f9e4abd --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,11 @@ +linters: + enable-all: false + presets: + - bugs + - complexity + - unused + disable-all: false + disable: + - gochecknoinits + - dupl + - gochecknoglobals diff --git a/Makefile b/Makefile index dde643ba9..41096c461 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,81 @@ -help: - @echo "This is a helper makefile for oapi-codegen" - @echo "Targets:" - @echo " generate: regenerate all generated files" - @echo " test: run all tests" +# +# Makefile to build the Blue Secrets Service (Certificate Manager) +# +.PHONY: all lint test +.PHONY: debug-build debug +.PHONY: semver clean deps +.PHONY: int-test +# +# Constants and runtime variables +# +PACKAGE = oapi-codegen +PACKAGE_PATH = gitswarm.f5net.com/indigo/product/controller-thirdparty +FULL_PACKAGE = $(PACKAGE_PATH)/$(PACKAGE) +GO_PKGS = $(shell go list ./... | grep -v test) +GO_PKGS_PATH = $(shell go list -f '{{.Dir}}' ./... | grep -v test) +DOCKER_TAG ?= latest +OUT_DIR ?= build +DEBUG_PACKAGE = $(PACKAGE)-debug + + +MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) +MKFILE_DIR := $(dir $(MKFILE_PATH)) +INTEGRATION_DIR = "$(MKFILE_DIR)/test/integration" + +TEST_TOOL_NAME = "test_tool.sh" +TEST_TOOL = "$(INTEGRATION_DIR)/$(TEST_TOOL_NAME)" + +# +# Targets used for local development +# +all: test lint + +export OUT_DIR + +clean: + rm -rf ./build_version coverage* test-coverage.html ./deploy test-results.out \ + unit_tests.xml full-lint-report.xml $(OUT_DIR) + +# +# Generate the template inline files and *.gen.go files +# generate: go generate ./pkg/... go generate ./... + goimports -w ./ + +# +# Run all tests and aggregate results into single coverage output. +# TODO: want to include -race flag with go test. +# +ifdef VERBOSE +test: generate + @echo "mode: set" > coverage-all.out + + @go test -v -timeout 30s -tags unit -coverprofile=coverage.out -race ./... | \ + tee -a test-results.out || exit 1 \ + tail -n +2 coverage.out >> coverage-all.out || exit 1 + @go tool cover -func=coverage-all.out && \ + go tool cover -html=coverage-all.out -o test-coverage.html +else +test: generate + @echo "mode: set" > coverage-all.out + + @go test -timeout 30s -tags unit -coverprofile=coverage.out -race ./... | \ + tee -a test-results.out || exit 1;\ + tail -n +2 coverage.out >> coverage-all.out || exit 1 + @go tool cover -html=coverage-all.out -o test-coverage.html +endif + +# +# Utilities targets +# +# run: +# $(OUT_DIR)/$(PACKAGE) +# +# Lint go code non-critical checks +# +lint: + echo "ignoring lint on this project" -test: - go test -cover ./... diff --git a/README.md b/README.md index a260248db..14261392b 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ write a lot of boilerplate code to perform all the marshalling and unmarshalling into objects which match the OpenAPI 3.0 definition. The code generator in this directory does a lot of that for you. You would run it like so: - go get github.com/deepmap/oapi-codegen/cmd/oapi-codegen + go get github.com/weberr13/oapi-codegen/cmd/oapi-codegen oapi-codegen petstore-expanded.yaml > petstore.gen.go Let's go through that `petstore.gen.go` file to show you everything which was @@ -454,4 +454,4 @@ Go file. Afterwards you should run `go generate ./...`, and the templates will be updated accordingly. - +> diff --git a/cmd/oapi-codegen/oapi-codegen.go b/cmd/oapi-codegen/oapi-codegen.go index 1a1b080aa..d59947c16 100644 --- a/cmd/oapi-codegen/oapi-codegen.go +++ b/cmd/oapi-codegen/oapi-codegen.go @@ -17,12 +17,13 @@ import ( "flag" "fmt" "io/ioutil" + "net/url" "os" "path/filepath" "strings" - "github.com/deepmap/oapi-codegen/pkg/codegen" - "github.com/deepmap/oapi-codegen/pkg/util" + "github.com/weberr13/oapi-codegen/pkg/codegen" + "github.com/weberr13/oapi-codegen/pkg/util" ) func errExit(format string, args ...interface{}) { @@ -30,6 +31,38 @@ func errExit(format string, args ...interface{}) { os.Exit(1) } +func usageErr(format string, args ...interface{}) { + _, _ = fmt.Fprintf(os.Stderr, format, args...) + flag.PrintDefaults() + os.Exit(1) +} + +// TODO define a type to allow recording of Type -> Import Path as args +// TODO this is temporary until we sort the config question +type refImports []string + +func (ri *refImports) String() string { + return "Reference Import arg" +} + +func (ri *refImports) Set(r string) error { + *ri = append(*ri, r) + return nil +} + +// TODO define a type to allow recording of package -> Import Path as args +// TODO this is temporary until we sort the config question +type pkgImports []string + +func (pi *pkgImports) String() string { + return "Pkg Import arg" +} + +func (pi *pkgImports) Set(r string) error { + *pi = append(*pi, r) + return nil +} + func main() { var ( packageName string @@ -37,13 +70,21 @@ func main() { outputFile string includeTags string excludeTags string + refImports refImports + pkgImports pkgImports + allowRefs bool + insecure bool ) + flag.StringVar(&packageName, "package", "", "The package name for generated code") flag.StringVar(&generate, "generate", "types,client,server,spec", `Comma-separated list of code to generate; valid options: "types", "client", "chi-server", "server", "skip-fmt", "spec"`) flag.StringVar(&outputFile, "o", "", "Where to output generated code, stdout is default") flag.StringVar(&includeTags, "include-tags", "", "Only include operations with the given tags. Comma-separated list of tags.") - flag.StringVar(&excludeTags, "exclude-tags", "", "Exclude operations that are tagged with the given tags. Comma-separated list of tags.") + flag.Var(&refImports, "ri", "Repeated reference import statements of the form Type=<[package:]import path>") + flag.Var(&pkgImports, "pi", "Repeated package import statements of the form =<[package:]import path>") + flag.BoolVar(&allowRefs, "extrefs", false, "Allow resolving external references") + flag.BoolVar(&insecure, "insecure", false, "Allow resolving remote URL's that have bad SSL/TLS") flag.Parse() if flag.NArg() < 1 { @@ -76,10 +117,12 @@ func main() { opts.EmbedSpec = true case "skip-fmt": opts.SkipFmt = true + case "resolved-spec": + opts.ClearRefsSpec = true + opts.EmbedSpec = true default: - fmt.Printf("unknown generate option %s\n", g) - flag.PrintDefaults() - os.Exit(1) + // never returns + usageErr("unknown generate option %s\n", g) } } @@ -90,9 +133,21 @@ func main() { errExit("can not specify both server and chi-server targets simultaneously") } - swagger, err := util.LoadSwagger(flag.Arg(0)) + if opts.ClearRefsSpec && (opts.GenerateClient || opts.GenerateServer || opts.GenerateTypes) { + // never returns + usageErr("resolved-spec option is only valid when specified on its own") + } + + // Add user defined type -> import mapping + opts.ImportedTypes = importPackages(pkgImports, allowRefs, insecure) + // override with specific imports if so indicated + for k, v := range importTypes(refImports) { + opts.ImportedTypes[k] = v + } + + swagger, err := util.LoadSwagger(flag.Arg(0), allowRefs, insecure, opts.ClearRefsSpec) if err != nil { - errExit("error loading swagger spec\n: %s", err) + errExit("error loading swagger spec:\n%s\n", err) } code, err := codegen.Generate(swagger, packageName, opts) @@ -103,7 +158,7 @@ func main() { if outputFile != "" { err = ioutil.WriteFile(outputFile, []byte(code), 0644) if err != nil { - errExit("error writing generated code to file: %s", err) + errExit("error writing generated code to file: %s\n", err) } } else { fmt.Println(code) @@ -125,3 +180,75 @@ func splitCSVArg(input string) []string { } return args } + +func mapArgSlice(as []string, an string) map[string]string { + m := map[string]string{} + for _, ri := range as { + parts := strings.Split(ri, "=") + if len(parts) != 2 { + fmt.Printf("invalid %s arg. %s\n", an, ri) + flag.PrintDefaults() + os.Exit(1) + } + m[parts[0]] = parts[1] + } + return m +} + +func importPackages(imports pkgImports, allowRefs, insecure bool) map[string]codegen.TypeImportSpec { + importedTypes := map[string]codegen.TypeImportSpec{} + pi := mapArgSlice(imports, "package import") + + for sr, p := range pi { + var u *url.URL + var err error + + if u, err = url.Parse(sr); err != nil { + errExit("package import: specified schema ref is not a URL:\n%s\n", err) + } + swagger, err := util.LoadSwaggerFromURL(u, allowRefs, insecure) + if err != nil { + errExit("package import: error loading swagger spec:\n%s\n", err) + } + + // iterate over model to find schema names - extract only top level names + for n := range swagger.Components.Schemas { + if _, ok := importedTypes[n]; !ok { + importedTypes[n] = getImportedType(n, p) + } + } + } + return importedTypes +} + +func importTypes(typeImports refImports) map[string]codegen.TypeImportSpec { + importedTypes := map[string]codegen.TypeImportSpec{} + pi := mapArgSlice(typeImports, "type imports") + + for t, p := range pi { + importedTypes[t] = getImportedType(t, p) + } + return importedTypes +} + +func getImportedType(typeName, pkgImport string) codegen.TypeImportSpec { + var pkgName string + var impPath string + + // if a package name was specified in the form pkg:, use that, otherwise use last part of import path + parts := strings.Split(pkgImport, ":") + if len(parts) > 2 { + errExit("Parsing type import: too many fragments. At most one ':' expected (type:%s, import:%s)", typeName, pkgImport) + } + + if len(parts) == 2 { + pkgName = parts[0] + impPath = parts[1] + } else { + parts = strings.Split(pkgImport, "/") + pkgName = parts[len(parts)-1] + impPath = pkgImport + } + + return codegen.NewTypeImportSpec(typeName, pkgName, impPath) +} diff --git a/examples/petstore-expanded/chi/api/petstore.gen.go b/examples/petstore-expanded/chi/api/petstore.gen.go index 01b6d782b..a20881409 100644 --- a/examples/petstore-expanded/chi/api/petstore.gen.go +++ b/examples/petstore-expanded/chi/api/petstore.gen.go @@ -18,22 +18,14 @@ import ( // Error defines model for Error. type Error struct { - - // Error code - Code int32 `json:"code"` - - // Error message + Code int32 `json:"code"` Message string `json:"message"` } // NewPet defines model for NewPet. type NewPet struct { - - // Name of the pet - Name string `json:"name"` - - // Type of the pet - Tag *string `json:"tag,omitempty"` + Name string `json:"name"` + Tag *string `json:"tag,omitempty"` } // Pet defines model for Pet. @@ -41,8 +33,6 @@ type Pet struct { // Embedded struct due to allOf(#/components/schemas/NewPet) NewPet // Embedded fields due to inline allOf schema - - // Unique id of the pet Id int64 `json:"id"` } @@ -175,7 +165,7 @@ func Handler(si ServerInterface) http.Handler { } // HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux. -func HandlerFromMux(si ServerInterface, r chi.Router) http.Handler { +func HandlerFromMux(si ServerInterface, r *chi.Mux) http.Handler { r.Group(func(r chi.Router) { r.Use(FindPetsCtx) r.Get("/pets", si.FindPets) diff --git a/examples/petstore-expanded/echo/api/petstore-server.gen.go b/examples/petstore-expanded/echo/api/petstore-server.gen.go index 998cc552f..0ba521da7 100644 --- a/examples/petstore-expanded/echo/api/petstore-server.gen.go +++ b/examples/petstore-expanded/echo/api/petstore-server.gen.go @@ -17,17 +17,13 @@ import ( // ServerInterface represents all server handlers. type ServerInterface interface { - // Returns all pets - // (GET /pets) + // Returns all pets// (GET /pets) FindPets(ctx echo.Context, params FindPetsParams) error - // Creates a new pet - // (POST /pets) + // Creates a new pet// (POST /pets) AddPet(ctx echo.Context) error - // Deletes a pet by ID - // (DELETE /pets/{id}) + // Deletes a pet by ID// (DELETE /pets/{id}) DeletePet(ctx echo.Context, id int64) error - // Returns a pet by ID - // (GET /pets/{id}) + // Returns a pet by ID// (GET /pets/{id}) FindPetById(ctx echo.Context, id int64) error } diff --git a/examples/petstore-expanded/echo/api/petstore-types.gen.go b/examples/petstore-expanded/echo/api/petstore-types.gen.go index 652b41e34..79c6a2f25 100644 --- a/examples/petstore-expanded/echo/api/petstore-types.gen.go +++ b/examples/petstore-expanded/echo/api/petstore-types.gen.go @@ -5,22 +5,14 @@ package api // Error defines model for Error. type Error struct { - - // Error code - Code int32 `json:"code"` - - // Error message + Code int32 `json:"code"` Message string `json:"message"` } // NewPet defines model for NewPet. type NewPet struct { - - // Name of the pet - Name string `json:"name"` - - // Type of the pet - Tag *string `json:"tag,omitempty"` + Name string `json:"name"` + Tag *string `json:"tag,omitempty"` } // Pet defines model for Pet. @@ -28,8 +20,6 @@ type Pet struct { // Embedded struct due to allOf(#/components/schemas/NewPet) NewPet // Embedded fields due to inline allOf schema - - // Unique id of the pet Id int64 `json:"id"` } diff --git a/examples/petstore-expanded/echo/petstore.go b/examples/petstore-expanded/echo/petstore.go index af0ae8310..e41f3104f 100644 --- a/examples/petstore-expanded/echo/petstore.go +++ b/examples/petstore-expanded/echo/petstore.go @@ -11,9 +11,10 @@ import ( "os" "github.com/deepmap/oapi-codegen/examples/petstore-expanded/echo/api" - "github.com/deepmap/oapi-codegen/pkg/middleware" "github.com/labstack/echo/v4" echomiddleware "github.com/labstack/echo/v4/middleware" + "github.com/weberr13/oapi-codegen/examples/petstore-expanded/api" + "github.com/weberr13/oapi-codegen/pkg/middleware" ) func main() { diff --git a/examples/petstore-expanded/echo/petstore_test.go b/examples/petstore-expanded/echo/petstore_test.go index 17e6f3a20..bba72afc8 100644 --- a/examples/petstore-expanded/echo/petstore_test.go +++ b/examples/petstore-expanded/echo/petstore_test.go @@ -27,6 +27,9 @@ import ( "github.com/deepmap/oapi-codegen/examples/petstore-expanded/echo/api" "github.com/deepmap/oapi-codegen/pkg/middleware" "github.com/deepmap/oapi-codegen/pkg/testutil" + "github.com/weberr13/oapi-codegen/examples/petstore-expanded/api" + "github.com/weberr13/oapi-codegen/pkg/middleware" + "github.com/weberr13/oapi-codegen/pkg/testutil" ) func TestPetStore(t *testing.T) { diff --git a/examples/petstore-expanded/internal/doc.go b/examples/petstore-expanded/internal/doc.go index ac961b701..a7108816c 100644 --- a/examples/petstore-expanded/internal/doc.go +++ b/examples/petstore-expanded/internal/doc.go @@ -17,4 +17,7 @@ package internal // server. The file petstore.gen.go is automatically generated from the schema // Run oapi-codegen to regenerate the petstore boilerplate -//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --package=petstore --generate types,client -o ../petstore-client.gen.go ../petstore-expanded.yaml + +//go:generate go run github.com/weberr13/oapi-codegen/cmd/oapi-codegen --package=api --generate types -o ../petstore-types.gen.go ../petstore-expanded.yaml +//go:generate go run github.com/weberr13/oapi-codegen/cmd/oapi-codegen --package=api --generate server,spec -o ../petstore-server.gen.go ../petstore-expanded.yaml +//go:generate go run github.com/weberr13/oapi-codegen/cmd/oapi-codegen --package=api --generate client -o ../petstore-client.gen.go ../petstore-expanded.yaml diff --git a/examples/petstore-expanded/petstore-client.gen.go b/examples/petstore-expanded/petstore-client.gen.go index ea6050c1e..41bfa65bc 100644 --- a/examples/petstore-expanded/petstore-client.gen.go +++ b/examples/petstore-expanded/petstore-client.gen.go @@ -8,32 +8,25 @@ import ( "context" "encoding/json" "fmt" - "github.com/deepmap/oapi-codegen/pkg/runtime" "io" "io/ioutil" "net/http" "net/url" "strings" + + "github.com/deepmap/oapi-codegen/pkg/runtime" ) // Error defines model for Error. type Error struct { - - // Error code - Code int32 `json:"code"` - - // Error message + Code int32 `json:"code"` Message string `json:"message"` } // NewPet defines model for NewPet. type NewPet struct { - - // Name of the pet - Name string `json:"name"` - - // Type of the pet - Tag *string `json:"tag,omitempty"` + Name string `json:"name"` + Tag *string `json:"tag,omitempty"` } // Pet defines model for Pet. @@ -41,8 +34,6 @@ type Pet struct { // Embedded struct due to allOf(#/components/schemas/NewPet) NewPet // Embedded fields due to inline allOf schema - - // Unique id of the pet Id int64 `json:"id"` } diff --git a/go.mod b/go.mod index 9b3a89a3c..e3f81d694 100644 --- a/go.mod +++ b/go.mod @@ -1,23 +1,20 @@ -module github.com/deepmap/oapi-codegen +module github.com/weberr13/oapi-codegen require ( github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c + github.com/deepmap/oapi-codegen v1.3.4 github.com/getkin/kin-openapi v0.2.0 github.com/go-chi/chi v4.0.2+incompatible github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219 + github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365 github.com/labstack/echo/v4 v4.1.11 github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd - github.com/mattn/go-colorable v0.1.4 // indirect - github.com/mattn/go-isatty v0.0.10 // indirect + github.com/onsi/gomega v1.7.0 github.com/pkg/errors v0.8.1 github.com/stretchr/testify v1.4.0 - github.com/valyala/fasttemplate v1.1.0 // indirect - golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708 // indirect - golang.org/x/net v0.0.0-20191112182307-2180aed22343 // indirect - golang.org/x/sys v0.0.0-20191115151921-52ab43148777 // indirect - golang.org/x/text v0.3.2 // indirect - golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f // indirect - gopkg.in/yaml.v2 v2.2.5 // indirect + golang.org/x/tools v0.0.0-20200203222849-174f5c63c9f5 // indirect ) go 1.13 + +replace github.com/getkin/kin-openapi => github.com/weberr13/kin-openapi v0.2.6 diff --git a/go.sum b/go.sum index eaf971195..72d622830 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,27 @@ github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c h1:/ovYnF02fwL0kvspmy9AuyKg1JhdTRUgPw4nUxd9oZM= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deepmap/oapi-codegen v1.3.4 h1:T0wShRuw+Z4sdz5ETVojylZT9lEND/P28LZeps8xBac= +github.com/deepmap/oapi-codegen v1.3.4/go.mod h1:aBozjEveG+33xPiP55Iw/XbVkhtZHEGLq3nxlX0+hfU= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/getkin/kin-openapi v0.2.0 h1:PbHHtYZpjKwZtGlIyELgA2DploRrsaXztoNNx9HjwNY= -github.com/getkin/kin-openapi v0.2.0/go.mod h1:V1z9xl9oF5Wt7v32ne4FmiF1alpS4dM6mNzoywPOXlk= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs= github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219 h1:utua3L2IbQJmauC5IXdEA547bcoU5dozgQAfc8Onsg4= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365 h1:ECW73yc9MY7935nNYXUkK7Dz17YuSUI9yqRqYS8aBww= +github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= @@ -35,6 +43,15 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -56,33 +73,59 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49N golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708 h1:pXVtWnwHkrWD9ru3sDxY/qFK/bfc0egRovX91EjWjf4= golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +github.com/weberr13/kin-openapi v0.2.6 h1:8Oc6obWkJaWPe1fbWYtUGhQWjQw/Wfg3FlXt4GfebK0= +github.com/weberr13/kin-openapi v0.2.6/go.mod h1:V1z9xl9oF5Wt7v32ne4FmiF1alpS4dM6mNzoywPOXlk= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708 h1:pXVtWnwHkrWD9ru3sDxY/qFK/bfc0egRovX91EjWjf4= +golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191112182307-2180aed22343 h1:00ohfJ4K98s3m6BGUoBd8nyfp4Yl0GoIKvw5abItTjI= golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777 h1:wejkGHRTr38uaKRqECZlsCsJ1/TGxIyFbH32x5zUdu4= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f h1:kDxGY2VmgABOe55qheT/TFqUMtcTHnomIPS1iv3G4Ms= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +golang.org/x/tools v0.0.0-20200203222849-174f5c63c9f5 h1:b+tBIZFU87VKnTk6WXPq8InZqKyHmh/Q3dSYjCs7dhg= +golang.org/x/tools v0.0.0-20200203222849-174f5c63c9f5/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= diff --git a/internal/test/client/client.gen.go b/internal/test/client/client.gen.go deleted file mode 100644 index 5965965b8..000000000 --- a/internal/test/client/client.gen.go +++ /dev/null @@ -1,989 +0,0 @@ -// Package client provides primitives to interact the openapi HTTP API. -// -// Code generated by github.com/deepmap/oapi-codegen DO NOT EDIT. -package client - -import ( - "bytes" - "compress/gzip" - "context" - "encoding/base64" - "encoding/json" - "fmt" - "github.com/getkin/kin-openapi/openapi3" - "github.com/labstack/echo/v4" - "io" - "io/ioutil" - "net/http" - "net/url" - "strings" -) - -// SchemaObject defines model for SchemaObject. -type SchemaObject struct { - FirstName string `json:"firstName"` - Role string `json:"role"` -} - -// PostBothJSONBody defines parameters for PostBoth. -type PostBothJSONBody SchemaObject - -// PostJsonJSONBody defines parameters for PostJson. -type PostJsonJSONBody SchemaObject - -// PostBothRequestBody defines body for PostBoth for application/json ContentType. -type PostBothJSONRequestBody PostBothJSONBody - -// PostJsonRequestBody defines body for PostJson for application/json ContentType. -type PostJsonJSONRequestBody PostJsonJSONBody - -// RequestEditorFn is the function signature for the RequestEditor callback function -type RequestEditorFn func(req *http.Request, ctx context.Context) 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 - } - } - // 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 { - // PostBoth request with any body - PostBothWithBody(ctx context.Context, contentType string, body io.Reader) (*http.Response, error) - - PostBoth(ctx context.Context, body PostBothJSONRequestBody) (*http.Response, error) - - // GetBoth request - GetBoth(ctx context.Context) (*http.Response, error) - - // PostJson request with any body - PostJsonWithBody(ctx context.Context, contentType string, body io.Reader) (*http.Response, error) - - PostJson(ctx context.Context, body PostJsonJSONRequestBody) (*http.Response, error) - - // GetJson request - GetJson(ctx context.Context) (*http.Response, error) - - // PostOther request with any body - PostOtherWithBody(ctx context.Context, contentType string, body io.Reader) (*http.Response, error) - - // GetOther request - GetOther(ctx context.Context) (*http.Response, error) - - // GetJsonWithTrailingSlash request - GetJsonWithTrailingSlash(ctx context.Context) (*http.Response, error) -} - -func (c *Client) PostBothWithBody(ctx context.Context, contentType string, body io.Reader) (*http.Response, error) { - req, err := NewPostBothRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) PostBoth(ctx context.Context, body PostBothJSONRequestBody) (*http.Response, error) { - req, err := NewPostBothRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetBoth(ctx context.Context) (*http.Response, error) { - req, err := NewGetBothRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) PostJsonWithBody(ctx context.Context, contentType string, body io.Reader) (*http.Response, error) { - req, err := NewPostJsonRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) PostJson(ctx context.Context, body PostJsonJSONRequestBody) (*http.Response, error) { - req, err := NewPostJsonRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetJson(ctx context.Context) (*http.Response, error) { - req, err := NewGetJsonRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) PostOtherWithBody(ctx context.Context, contentType string, body io.Reader) (*http.Response, error) { - req, err := NewPostOtherRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetOther(ctx context.Context) (*http.Response, error) { - req, err := NewGetOtherRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetJsonWithTrailingSlash(ctx context.Context) (*http.Response, error) { - req, err := NewGetJsonWithTrailingSlashRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -// NewPostBothRequest calls the generic PostBoth builder with application/json body -func NewPostBothRequest(server string, body PostBothJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostBothRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostBothRequestWithBody generates requests for PostBoth with any type of body -func NewPostBothRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/with_both_bodies")) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryUrl.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - return req, nil -} - -// NewGetBothRequest generates requests for GetBoth -func NewGetBothRequest(server string) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/with_both_responses")) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewPostJsonRequest calls the generic PostJson builder with application/json body -func NewPostJsonRequest(server string, body PostJsonJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostJsonRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostJsonRequestWithBody generates requests for PostJson with any type of body -func NewPostJsonRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/with_json_body")) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryUrl.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - return req, nil -} - -// NewGetJsonRequest generates requests for GetJson -func NewGetJsonRequest(server string) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/with_json_response")) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewPostOtherRequestWithBody generates requests for PostOther with any type of body -func NewPostOtherRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/with_other_body")) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryUrl.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - return req, nil -} - -// NewGetOtherRequest generates requests for GetOther -func NewGetOtherRequest(server string) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/with_other_response")) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetJsonWithTrailingSlashRequest generates requests for GetJsonWithTrailingSlash -func NewGetJsonWithTrailingSlashRequest(server string) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/with_trailing_slash/")) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// 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 { - if !strings.HasSuffix(baseURL, "/") { - baseURL += "/" - } - newBaseURL, err := url.Parse(baseURL) - if err != nil { - return err - } - c.Server = newBaseURL.String() - return nil - } -} - -type postBothResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r postBothResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r postBothResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getBothResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getBothResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getBothResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type postJsonResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r postJsonResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r postJsonResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getJsonResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getJsonResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getJsonResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type postOtherResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r postOtherResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r postOtherResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getOtherResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getOtherResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getOtherResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getJsonWithTrailingSlashResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getJsonWithTrailingSlashResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getJsonWithTrailingSlashResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// PostBothWithBodyWithResponse request with arbitrary body returning *PostBothResponse -func (c *ClientWithResponses) PostBothWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader) (*postBothResponse, error) { - rsp, err := c.PostBothWithBody(ctx, contentType, body) - if err != nil { - return nil, err - } - return ParsePostBothResponse(rsp) -} - -func (c *ClientWithResponses) PostBothWithResponse(ctx context.Context, body PostBothJSONRequestBody) (*postBothResponse, error) { - rsp, err := c.PostBoth(ctx, body) - if err != nil { - return nil, err - } - return ParsePostBothResponse(rsp) -} - -// GetBothWithResponse request returning *GetBothResponse -func (c *ClientWithResponses) GetBothWithResponse(ctx context.Context) (*getBothResponse, error) { - rsp, err := c.GetBoth(ctx) - if err != nil { - return nil, err - } - return ParseGetBothResponse(rsp) -} - -// PostJsonWithBodyWithResponse request with arbitrary body returning *PostJsonResponse -func (c *ClientWithResponses) PostJsonWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader) (*postJsonResponse, error) { - rsp, err := c.PostJsonWithBody(ctx, contentType, body) - if err != nil { - return nil, err - } - return ParsePostJsonResponse(rsp) -} - -func (c *ClientWithResponses) PostJsonWithResponse(ctx context.Context, body PostJsonJSONRequestBody) (*postJsonResponse, error) { - rsp, err := c.PostJson(ctx, body) - if err != nil { - return nil, err - } - return ParsePostJsonResponse(rsp) -} - -// GetJsonWithResponse request returning *GetJsonResponse -func (c *ClientWithResponses) GetJsonWithResponse(ctx context.Context) (*getJsonResponse, error) { - rsp, err := c.GetJson(ctx) - if err != nil { - return nil, err - } - return ParseGetJsonResponse(rsp) -} - -// PostOtherWithBodyWithResponse request with arbitrary body returning *PostOtherResponse -func (c *ClientWithResponses) PostOtherWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader) (*postOtherResponse, error) { - rsp, err := c.PostOtherWithBody(ctx, contentType, body) - if err != nil { - return nil, err - } - return ParsePostOtherResponse(rsp) -} - -// GetOtherWithResponse request returning *GetOtherResponse -func (c *ClientWithResponses) GetOtherWithResponse(ctx context.Context) (*getOtherResponse, error) { - rsp, err := c.GetOther(ctx) - if err != nil { - return nil, err - } - return ParseGetOtherResponse(rsp) -} - -// GetJsonWithTrailingSlashWithResponse request returning *GetJsonWithTrailingSlashResponse -func (c *ClientWithResponses) GetJsonWithTrailingSlashWithResponse(ctx context.Context) (*getJsonWithTrailingSlashResponse, error) { - rsp, err := c.GetJsonWithTrailingSlash(ctx) - if err != nil { - return nil, err - } - return ParseGetJsonWithTrailingSlashResponse(rsp) -} - -// ParsePostBothResponse parses an HTTP response from a PostBothWithResponse call -func ParsePostBothResponse(rsp *http.Response) (*postBothResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &postBothResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetBothResponse parses an HTTP response from a GetBothWithResponse call -func ParseGetBothResponse(rsp *http.Response) (*getBothResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getBothResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParsePostJsonResponse parses an HTTP response from a PostJsonWithResponse call -func ParsePostJsonResponse(rsp *http.Response) (*postJsonResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &postJsonResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetJsonResponse parses an HTTP response from a GetJsonWithResponse call -func ParseGetJsonResponse(rsp *http.Response) (*getJsonResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getJsonResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParsePostOtherResponse parses an HTTP response from a PostOtherWithResponse call -func ParsePostOtherResponse(rsp *http.Response) (*postOtherResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &postOtherResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetOtherResponse parses an HTTP response from a GetOtherWithResponse call -func ParseGetOtherResponse(rsp *http.Response) (*getOtherResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getOtherResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetJsonWithTrailingSlashResponse parses an HTTP response from a GetJsonWithTrailingSlashWithResponse call -func ParseGetJsonWithTrailingSlashResponse(rsp *http.Response) (*getJsonWithTrailingSlashResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getJsonWithTrailingSlashResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ServerInterface represents all server handlers. -type ServerInterface interface { - - // (POST /with_both_bodies) - PostBoth(ctx echo.Context) error - - // (GET /with_both_responses) - GetBoth(ctx echo.Context) error - - // (POST /with_json_body) - PostJson(ctx echo.Context) error - - // (GET /with_json_response) - GetJson(ctx echo.Context) error - - // (POST /with_other_body) - PostOther(ctx echo.Context) error - - // (GET /with_other_response) - GetOther(ctx echo.Context) error - - // (GET /with_trailing_slash/) - GetJsonWithTrailingSlash(ctx echo.Context) error -} - -// ServerInterfaceWrapper converts echo contexts to parameters. -type ServerInterfaceWrapper struct { - Handler ServerInterface -} - -// PostBoth converts echo context to params. -func (w *ServerInterfaceWrapper) PostBoth(ctx echo.Context) error { - var err error - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.PostBoth(ctx) - return err -} - -// GetBoth converts echo context to params. -func (w *ServerInterfaceWrapper) GetBoth(ctx echo.Context) error { - var err error - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetBoth(ctx) - return err -} - -// PostJson converts echo context to params. -func (w *ServerInterfaceWrapper) PostJson(ctx echo.Context) error { - var err error - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.PostJson(ctx) - return err -} - -// GetJson converts echo context to params. -func (w *ServerInterfaceWrapper) GetJson(ctx echo.Context) error { - var err error - - ctx.Set("OpenId.Scopes", []string{"json.read", "json.admin"}) - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetJson(ctx) - return err -} - -// PostOther converts echo context to params. -func (w *ServerInterfaceWrapper) PostOther(ctx echo.Context) error { - var err error - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.PostOther(ctx) - return err -} - -// GetOther converts echo context to params. -func (w *ServerInterfaceWrapper) GetOther(ctx echo.Context) error { - var err error - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetOther(ctx) - return err -} - -// GetJsonWithTrailingSlash converts echo context to params. -func (w *ServerInterfaceWrapper) GetJsonWithTrailingSlash(ctx echo.Context) error { - var err error - - ctx.Set("OpenId.Scopes", []string{"json.read", "json.admin"}) - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetJsonWithTrailingSlash(ctx) - return err -} - -// RegisterHandlers adds each server route to the EchoRouter. -func RegisterHandlers(router 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 -}, si ServerInterface) { - - wrapper := ServerInterfaceWrapper{ - Handler: si, - } - - router.POST("/with_both_bodies", wrapper.PostBoth) - router.GET("/with_both_responses", wrapper.GetBoth) - router.POST("/with_json_body", wrapper.PostJson) - router.GET("/with_json_response", wrapper.GetJson) - router.POST("/with_other_body", wrapper.PostOther) - router.GET("/with_other_response", wrapper.GetOther) - router.GET("/with_trailing_slash/", wrapper.GetJsonWithTrailingSlash) - -} - -// Base64 encoded, gzipped, json marshaled Swagger object -var swaggerSpec = []string{ - - "H4sIAAAAAAAC/8xUzY4SQRB+lUnpcWRYvc1RD2ZNFCMkHpBsmp6C7s1Md1tV7GZCeHdTDcgQN8jBNXsh", - "1fRXle+nerZgY5diwCAM9RbYOuxMLqe5nCzv0YqeE8WEJB7z7coTyxfToR6kTwg1sJAPa9iVQLF96kJv", - "8OfGEzZQz/eocjBqsVOID6uozQ2yJZ/ExwA1zJznQpCFi0eH4pAKcVh8aD0GKUxoDuV3L+4bcoqBkQtD", - "WKwxIBnBprCRCK20/Y8AJbTeYuDMM2Qh8Pl2puzFi9KHGbIUU6QHJCjhAYn3VG5G49FYgTFhMMlDDe9G", - "49ENlJCMuOxP9ejF3S1j/mkOpqXI2Uo10qiu2wZq+BpZ3kdxsHcH9dT0irMxCIbcYlJqvc1N1T0rjWNY", - "Wr0mXEENr6pTmtUhyuosR/V3OCpaQXnDQmi685GrSJ0RqGHpg6Eeyj/CPEtTaIP5r4FwOsag89b4hPSP", - "eFI+wL4dj1+q5oFGpaTh9pej/aTM/0u0lwLJZI8mX8rjN91nzENpMdoNeemhnm9hkjATmIPOHRGaBsp9", - "bZrOB1jsFictUV//Fc5PFHe19c/1FPZsr7H+xPey9/9qgYWMb31Y33Fr2FV/2wr9ss4OLVPteKFrstv9", - "CgAA//91LTf11gYAAA==", -} - -// 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 -} diff --git a/internal/test/client/doc.go b/internal/test/client/doc.go index 4a3bcfc8f..58d26feaf 100644 --- a/internal/test/client/doc.go +++ b/internal/test/client/doc.go @@ -1,4 +1,3 @@ package client -//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --package=client -o client.gen.go client.yaml - +//go:generate go run github.com/weberr13/oapi-codegen/cmd/oapi-codegen --package=client -o client.gen.go client.yaml diff --git a/internal/test/components/components.gen.go b/internal/test/components/components.gen.go deleted file mode 100644 index a49fad16f..000000000 --- a/internal/test/components/components.gen.go +++ /dev/null @@ -1,1183 +0,0 @@ -// Package components provides primitives to interact the openapi HTTP API. -// -// Code generated by github.com/deepmap/oapi-codegen DO NOT EDIT. -package components - -import ( - "bytes" - "compress/gzip" - "context" - "encoding/base64" - "encoding/json" - "fmt" - "github.com/deepmap/oapi-codegen/pkg/runtime" - "github.com/getkin/kin-openapi/openapi3" - "github.com/labstack/echo/v4" - "github.com/pkg/errors" - "io" - "io/ioutil" - "net/http" - "net/url" - "strings" -) - -// AdditionalPropertiesObject1 defines model for AdditionalPropertiesObject1. -type AdditionalPropertiesObject1 struct { - Id int `json:"id"` - Name string `json:"name"` - Optional *string `json:"optional,omitempty"` - AdditionalProperties map[string]int `json:"-"` -} - -// AdditionalPropertiesObject2 defines model for AdditionalPropertiesObject2. -type AdditionalPropertiesObject2 struct { - Id int `json:"id"` - Name string `json:"name"` -} - -// AdditionalPropertiesObject3 defines model for AdditionalPropertiesObject3. -type AdditionalPropertiesObject3 struct { - Name string `json:"name"` - AdditionalProperties map[string]interface{} `json:"-"` -} - -// AdditionalPropertiesObject4 defines model for AdditionalPropertiesObject4. -type AdditionalPropertiesObject4 struct { - Inner AdditionalPropertiesObject4_Inner `json:"inner"` - Name string `json:"name"` - AdditionalProperties map[string]interface{} `json:"-"` -} - -// AdditionalPropertiesObject4_Inner defines model for AdditionalPropertiesObject4.Inner. -type AdditionalPropertiesObject4_Inner struct { - Name string `json:"name"` - AdditionalProperties map[string]interface{} `json:"-"` -} - -// AdditionalPropertiesObject5 defines model for AdditionalPropertiesObject5. -type AdditionalPropertiesObject5 struct { - AdditionalProperties map[string]SchemaObject `json:"-"` -} - -// ObjectWithJsonField defines model for ObjectWithJsonField. -type ObjectWithJsonField struct { - Name string `json:"name"` - Value1 json.RawMessage `json:"value1"` - Value2 json.RawMessage `json:"value2,omitempty"` -} - -// SchemaObject defines model for SchemaObject. -type SchemaObject struct { - FirstName string `json:"firstName"` - Role string `json:"role"` -} - -// ParameterObject defines model for ParameterObject. -type ParameterObject string - -// ResponseObject defines model for ResponseObject. -type ResponseObject struct { - Field SchemaObject `json:"Field"` -} - -// RequestBody defines model for RequestBody. -type RequestBody struct { - Field SchemaObject `json:"Field"` -} - -// ParamsWithAddPropsParams_P1 defines parameters for ParamsWithAddProps. -type ParamsWithAddPropsParams_P1 struct { - AdditionalProperties map[string]interface{} `json:"-"` -} - -// ParamsWithAddPropsParams defines parameters for ParamsWithAddProps. -type ParamsWithAddPropsParams struct { - - // This parameter has additional properties - P1 ParamsWithAddPropsParams_P1 `json:"p1"` - - // This parameter has an anonymous inner property which needs to be - // turned into a proper type for additionalProperties to work - P2 struct { - Inner ParamsWithAddPropsParams_P2_Inner `json:"inner"` - } `json:"p2"` -} - -// ParamsWithAddPropsParams_P2_Inner defines parameters for ParamsWithAddProps. -type ParamsWithAddPropsParams_P2_Inner struct { - AdditionalProperties map[string]string `json:"-"` -} - -// BodyWithAddPropsJSONBody defines parameters for BodyWithAddProps. -type BodyWithAddPropsJSONBody struct { - Inner BodyWithAddPropsJSONBody_Inner `json:"inner"` - Name string `json:"name"` - AdditionalProperties map[string]interface{} `json:"-"` -} - -// BodyWithAddPropsJSONBody_Inner defines parameters for BodyWithAddProps. -type BodyWithAddPropsJSONBody_Inner struct { - AdditionalProperties map[string]int `json:"-"` -} - -// BodyWithAddPropsRequestBody defines body for BodyWithAddProps for application/json ContentType. -type BodyWithAddPropsJSONRequestBody BodyWithAddPropsJSONBody - -// Getter for additional properties for ParamsWithAddPropsParams_P1. Returns the specified -// element and whether it was found -func (a ParamsWithAddPropsParams_P1) Get(fieldName string) (value interface{}, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for ParamsWithAddPropsParams_P1 -func (a *ParamsWithAddPropsParams_P1) Set(fieldName string, value interface{}) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]interface{}) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for ParamsWithAddPropsParams_P1 to handle AdditionalProperties -func (a *ParamsWithAddPropsParams_P1) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { - var fieldVal interface{} - 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 ParamsWithAddPropsParams_P1 to handle AdditionalProperties -func (a ParamsWithAddPropsParams_P1) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - 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) -} - -// Getter for additional properties for ParamsWithAddPropsParams_P2_Inner. Returns the specified -// element and whether it was found -func (a ParamsWithAddPropsParams_P2_Inner) Get(fieldName string) (value string, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for ParamsWithAddPropsParams_P2_Inner -func (a *ParamsWithAddPropsParams_P2_Inner) Set(fieldName string, value string) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]string) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for ParamsWithAddPropsParams_P2_Inner to handle AdditionalProperties -func (a *ParamsWithAddPropsParams_P2_Inner) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]string) - for fieldName, fieldBuf := range object { - var fieldVal string - 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 ParamsWithAddPropsParams_P2_Inner to handle AdditionalProperties -func (a ParamsWithAddPropsParams_P2_Inner) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - 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) -} - -// Getter for additional properties for BodyWithAddPropsJSONBody. Returns the specified -// element and whether it was found -func (a BodyWithAddPropsJSONBody) Get(fieldName string) (value interface{}, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for BodyWithAddPropsJSONBody -func (a *BodyWithAddPropsJSONBody) Set(fieldName string, value interface{}) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]interface{}) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for BodyWithAddPropsJSONBody to handle AdditionalProperties -func (a *BodyWithAddPropsJSONBody) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if raw, found := object["inner"]; found { - err = json.Unmarshal(raw, &a.Inner) - if err != nil { - return errors.Wrap(err, "error reading 'inner'") - } - delete(object, "inner") - } - - if raw, found := object["name"]; found { - err = json.Unmarshal(raw, &a.Name) - if err != nil { - return errors.Wrap(err, "error reading 'name'") - } - delete(object, "name") - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { - var fieldVal interface{} - 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 BodyWithAddPropsJSONBody to handle AdditionalProperties -func (a BodyWithAddPropsJSONBody) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - object["inner"], err = json.Marshal(a.Inner) - if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error marshaling 'inner'")) - } - - object["name"], err = json.Marshal(a.Name) - if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error marshaling 'name'")) - } - - 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) -} - -// Getter for additional properties for BodyWithAddPropsJSONBody_Inner. Returns the specified -// element and whether it was found -func (a BodyWithAddPropsJSONBody_Inner) Get(fieldName string) (value int, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for BodyWithAddPropsJSONBody_Inner -func (a *BodyWithAddPropsJSONBody_Inner) Set(fieldName string, value int) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]int) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for BodyWithAddPropsJSONBody_Inner to handle AdditionalProperties -func (a *BodyWithAddPropsJSONBody_Inner) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]int) - for fieldName, fieldBuf := range object { - var fieldVal int - 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 BodyWithAddPropsJSONBody_Inner to handle AdditionalProperties -func (a BodyWithAddPropsJSONBody_Inner) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - 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) -} - -// Getter for additional properties for AdditionalPropertiesObject1. Returns the specified -// element and whether it was found -func (a AdditionalPropertiesObject1) Get(fieldName string) (value int, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for AdditionalPropertiesObject1 -func (a *AdditionalPropertiesObject1) Set(fieldName string, value int) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]int) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for AdditionalPropertiesObject1 to handle AdditionalProperties -func (a *AdditionalPropertiesObject1) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if raw, found := object["id"]; found { - err = json.Unmarshal(raw, &a.Id) - if err != nil { - return errors.Wrap(err, "error reading 'id'") - } - delete(object, "id") - } - - if raw, found := object["name"]; found { - err = json.Unmarshal(raw, &a.Name) - if err != nil { - return errors.Wrap(err, "error reading 'name'") - } - delete(object, "name") - } - - if raw, found := object["optional"]; found { - err = json.Unmarshal(raw, &a.Optional) - if err != nil { - return errors.Wrap(err, "error reading 'optional'") - } - delete(object, "optional") - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]int) - for fieldName, fieldBuf := range object { - var fieldVal int - 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 AdditionalPropertiesObject1 to handle AdditionalProperties -func (a AdditionalPropertiesObject1) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - object["id"], err = json.Marshal(a.Id) - if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error marshaling 'id'")) - } - - object["name"], err = json.Marshal(a.Name) - if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error marshaling 'name'")) - } - - if a.Optional != nil { - object["optional"], err = json.Marshal(a.Optional) - if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error marshaling 'optional'")) - } - } - - 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) -} - -// Getter for additional properties for AdditionalPropertiesObject3. Returns the specified -// element and whether it was found -func (a AdditionalPropertiesObject3) Get(fieldName string) (value interface{}, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for AdditionalPropertiesObject3 -func (a *AdditionalPropertiesObject3) Set(fieldName string, value interface{}) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]interface{}) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for AdditionalPropertiesObject3 to handle AdditionalProperties -func (a *AdditionalPropertiesObject3) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if raw, found := object["name"]; found { - err = json.Unmarshal(raw, &a.Name) - if err != nil { - return errors.Wrap(err, "error reading 'name'") - } - delete(object, "name") - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { - var fieldVal interface{} - 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 AdditionalPropertiesObject3 to handle AdditionalProperties -func (a AdditionalPropertiesObject3) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - object["name"], err = json.Marshal(a.Name) - if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error marshaling 'name'")) - } - - 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) -} - -// Getter for additional properties for AdditionalPropertiesObject4. Returns the specified -// element and whether it was found -func (a AdditionalPropertiesObject4) Get(fieldName string) (value interface{}, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for AdditionalPropertiesObject4 -func (a *AdditionalPropertiesObject4) Set(fieldName string, value interface{}) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]interface{}) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for AdditionalPropertiesObject4 to handle AdditionalProperties -func (a *AdditionalPropertiesObject4) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if raw, found := object["inner"]; found { - err = json.Unmarshal(raw, &a.Inner) - if err != nil { - return errors.Wrap(err, "error reading 'inner'") - } - delete(object, "inner") - } - - if raw, found := object["name"]; found { - err = json.Unmarshal(raw, &a.Name) - if err != nil { - return errors.Wrap(err, "error reading 'name'") - } - delete(object, "name") - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { - var fieldVal interface{} - 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 AdditionalPropertiesObject4 to handle AdditionalProperties -func (a AdditionalPropertiesObject4) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - object["inner"], err = json.Marshal(a.Inner) - if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error marshaling 'inner'")) - } - - object["name"], err = json.Marshal(a.Name) - if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error marshaling 'name'")) - } - - 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) -} - -// Getter for additional properties for AdditionalPropertiesObject4_Inner. Returns the specified -// element and whether it was found -func (a AdditionalPropertiesObject4_Inner) Get(fieldName string) (value interface{}, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for AdditionalPropertiesObject4_Inner -func (a *AdditionalPropertiesObject4_Inner) Set(fieldName string, value interface{}) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]interface{}) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for AdditionalPropertiesObject4_Inner to handle AdditionalProperties -func (a *AdditionalPropertiesObject4_Inner) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if raw, found := object["name"]; found { - err = json.Unmarshal(raw, &a.Name) - if err != nil { - return errors.Wrap(err, "error reading 'name'") - } - delete(object, "name") - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { - var fieldVal interface{} - 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 AdditionalPropertiesObject4_Inner to handle AdditionalProperties -func (a AdditionalPropertiesObject4_Inner) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - object["name"], err = json.Marshal(a.Name) - if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error marshaling 'name'")) - } - - 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) -} - -// Getter for additional properties for AdditionalPropertiesObject5. Returns the specified -// element and whether it was found -func (a AdditionalPropertiesObject5) Get(fieldName string) (value SchemaObject, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for AdditionalPropertiesObject5 -func (a *AdditionalPropertiesObject5) Set(fieldName string, value SchemaObject) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]SchemaObject) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for AdditionalPropertiesObject5 to handle AdditionalProperties -func (a *AdditionalPropertiesObject5) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]SchemaObject) - for fieldName, fieldBuf := range object { - var fieldVal SchemaObject - 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 AdditionalPropertiesObject5 to handle AdditionalProperties -func (a AdditionalPropertiesObject5) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - 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) -} - -// RequestEditorFn is the function signature for the RequestEditor callback function -type RequestEditorFn func(req *http.Request, ctx context.Context) 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 - } - } - // 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 { - // ParamsWithAddProps request - ParamsWithAddProps(ctx context.Context, params *ParamsWithAddPropsParams) (*http.Response, error) - - // BodyWithAddProps request with any body - BodyWithAddPropsWithBody(ctx context.Context, contentType string, body io.Reader) (*http.Response, error) - - BodyWithAddProps(ctx context.Context, body BodyWithAddPropsJSONRequestBody) (*http.Response, error) -} - -func (c *Client) ParamsWithAddProps(ctx context.Context, params *ParamsWithAddPropsParams) (*http.Response, error) { - req, err := NewParamsWithAddPropsRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) BodyWithAddPropsWithBody(ctx context.Context, contentType string, body io.Reader) (*http.Response, error) { - req, err := NewBodyWithAddPropsRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) BodyWithAddProps(ctx context.Context, body BodyWithAddPropsJSONRequestBody) (*http.Response, error) { - req, err := NewBodyWithAddPropsRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -// NewParamsWithAddPropsRequest generates requests for ParamsWithAddProps -func NewParamsWithAddPropsRequest(server string, params *ParamsWithAddPropsParams) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/params_with_add_props")) - if err != nil { - return nil, err - } - - queryValues := queryUrl.Query() - - if queryFrag, err := runtime.StyleParam("simple", true, "p1", params.P1); 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) - } - } - } - - if queryFrag, err := runtime.StyleParam("form", true, "p2", params.P2); 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) - } - } - } - - queryUrl.RawQuery = queryValues.Encode() - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewBodyWithAddPropsRequest calls the generic BodyWithAddProps builder with application/json body -func NewBodyWithAddPropsRequest(server string, body BodyWithAddPropsJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewBodyWithAddPropsRequestWithBody(server, "application/json", bodyReader) -} - -// NewBodyWithAddPropsRequestWithBody generates requests for BodyWithAddProps with any type of body -func NewBodyWithAddPropsRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/params_with_add_props")) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryUrl.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - return req, nil -} - -// 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 { - if !strings.HasSuffix(baseURL, "/") { - baseURL += "/" - } - newBaseURL, err := url.Parse(baseURL) - if err != nil { - return err - } - c.Server = newBaseURL.String() - return nil - } -} - -type paramsWithAddPropsResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r paramsWithAddPropsResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r paramsWithAddPropsResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type bodyWithAddPropsResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r bodyWithAddPropsResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r bodyWithAddPropsResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// ParamsWithAddPropsWithResponse request returning *ParamsWithAddPropsResponse -func (c *ClientWithResponses) ParamsWithAddPropsWithResponse(ctx context.Context, params *ParamsWithAddPropsParams) (*paramsWithAddPropsResponse, error) { - rsp, err := c.ParamsWithAddProps(ctx, params) - if err != nil { - return nil, err - } - return ParseParamsWithAddPropsResponse(rsp) -} - -// BodyWithAddPropsWithBodyWithResponse request with arbitrary body returning *BodyWithAddPropsResponse -func (c *ClientWithResponses) BodyWithAddPropsWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader) (*bodyWithAddPropsResponse, error) { - rsp, err := c.BodyWithAddPropsWithBody(ctx, contentType, body) - if err != nil { - return nil, err - } - return ParseBodyWithAddPropsResponse(rsp) -} - -func (c *ClientWithResponses) BodyWithAddPropsWithResponse(ctx context.Context, body BodyWithAddPropsJSONRequestBody) (*bodyWithAddPropsResponse, error) { - rsp, err := c.BodyWithAddProps(ctx, body) - if err != nil { - return nil, err - } - return ParseBodyWithAddPropsResponse(rsp) -} - -// ParseParamsWithAddPropsResponse parses an HTTP response from a ParamsWithAddPropsWithResponse call -func ParseParamsWithAddPropsResponse(rsp *http.Response) (*paramsWithAddPropsResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := ¶msWithAddPropsResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseBodyWithAddPropsResponse parses an HTTP response from a BodyWithAddPropsWithResponse call -func ParseBodyWithAddPropsResponse(rsp *http.Response) (*bodyWithAddPropsResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &bodyWithAddPropsResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ServerInterface represents all server handlers. -type ServerInterface interface { - - // (GET /params_with_add_props) - ParamsWithAddProps(ctx echo.Context, params ParamsWithAddPropsParams) error - - // (POST /params_with_add_props) - BodyWithAddProps(ctx echo.Context) error -} - -// ServerInterfaceWrapper converts echo contexts to parameters. -type ServerInterfaceWrapper struct { - Handler ServerInterface -} - -// ParamsWithAddProps converts echo context to params. -func (w *ServerInterfaceWrapper) ParamsWithAddProps(ctx echo.Context) error { - var err error - - // Parameter object where we will unmarshal all parameters from the context - var params ParamsWithAddPropsParams - // ------------- Required query parameter "p1" ------------- - if paramValue := ctx.QueryParam("p1"); paramValue != "" { - - } else { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Query argument p1 is required, but not found")) - } - - err = runtime.BindQueryParameter("simple", true, true, "p1", ctx.QueryParams(), ¶ms.P1) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter p1: %s", err)) - } - - // ------------- Required query parameter "p2" ------------- - if paramValue := ctx.QueryParam("p2"); paramValue != "" { - - } else { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Query argument p2 is required, but not found")) - } - - err = runtime.BindQueryParameter("form", true, true, "p2", ctx.QueryParams(), ¶ms.P2) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter p2: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.ParamsWithAddProps(ctx, params) - return err -} - -// BodyWithAddProps converts echo context to params. -func (w *ServerInterfaceWrapper) BodyWithAddProps(ctx echo.Context) error { - var err error - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.BodyWithAddProps(ctx) - return err -} - -// RegisterHandlers adds each server route to the EchoRouter. -func RegisterHandlers(router 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 -}, si ServerInterface) { - - wrapper := ServerInterfaceWrapper{ - Handler: si, - } - - router.GET("/params_with_add_props", wrapper.ParamsWithAddProps) - router.POST("/params_with_add_props", wrapper.BodyWithAddProps) - -} - -// Base64 encoded, gzipped, json marshaled Swagger object -var swaggerSpec = []string{ - - "H4sIAAAAAAAC/9xWy27bOhD9FWLuXQp2Hu1GOxdF0RRoGzQBukiMgBFHEVOZVEg6rhDo34shJcuRaVdO", - "s2lXtiTO4xyeeTxBpheVVqichfQJKm74Ah0a/3TePX29vcfM0atMK4fK/+VVVcqMO6nV9N5qRe9sVuCC", - "e09GV2icRO/pg8RS0J//DeaQwn/TPu40GNnphf9tYzVNAgYfltKggPSq9TCn1w5/umlVcjkI6eoKIQXr", - "jFR30NBRgTYzsqIcIQXO1vggATKHhyWaeh0MrXunRZvzt/WL+q9DHnzYSivbgQkP/8hNzpiVi6pE1oFk", - "ug/WZkGOZkJIMuHl+RpFSOvYA4983ogvlcM7NLAV/iO3rLdlPUNM54yMmVQOkgF1UsR9K77ACOoEdBUC", - "xCh5zql3kVCEedId7RhJ9rBwspuFnJcWh8Dfa7RMacd4WepVnIM/xf1K0E53Q3NmuYVsRoAs46qOoKq3", - "MB2Q+2Fpvzksba9EpVW90EvLciottipkVrBil0a370cpNL8L+6rwx5mHvJKXsPh2X3WP71zj634lXcGC", - "E5Zrw4TM/CETCN9KPUT4Ll3xyWq1bqqjWE7gkZdL9B0s12bBHaTg+3ay4+jJiKPxsmsjxdh/RtVW7rk0", - "1n3ZBcDocoQA/Klkw9XcjwKpck3GpcxQWeyZgs9nl+TdSUfu4RKtYxdoHr2MHtHYcI3Hk6PJUWiwqHgl", - "IYXTydHkmCqDu8LnP/Wrgr2hi73hQtwQPP/lDj3c4UAiyyCDfoliXAnG2a0WdVuVLby4iq7pWujBj+Iz", - "AWlYwSzpZCbEuU8hebalXQ0zuSyk7VPY3QZ8sI0dqKtKqIiH/hpC+fezeV+T2NKIdbW/iTCtoUnGZKs2", - "OprvAes23JKoEIVlTrNbvFZuaRQKGria8fZkmMFUh7FsyXKlzY/dDJzsZeCg7hkR/4ClaNebN828SaDS", - "NiI234ZYu7Buqot2Oi4VfRXSYOai+BOS5bXayzPpOGYbkSgtyAOBmheuzuMH0FjWN9aNF06hbv/orqUZ", - "SsOv278CAAD//0Y7czRJDQAA", -} - -// 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 -} diff --git a/internal/test/components/doc.go b/internal/test/components/doc.go index c8f457a3a..25bf4a19c 100644 --- a/internal/test/components/doc.go +++ b/internal/test/components/doc.go @@ -1,3 +1,3 @@ package components -//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --package=components -o components.gen.go components.yaml +//go:generate go run github.com/weberr13/oapi-codegen/cmd/oapi-codegen --package=components -o components.gen.go components.yaml diff --git a/internal/test/issues/issue-52/issue.gen.go b/internal/test/issues/issue-52/issue.gen.go index f7a0d689e..6df59c3b4 100644 --- a/internal/test/issues/issue-52/issue.gen.go +++ b/internal/test/issues/issue-52/issue.gen.go @@ -286,7 +286,6 @@ func ParseExampleGetResponse(rsp *http.Response) (*exampleGetResponse, error) { // ServerInterface represents all server handlers. type ServerInterface interface { - // (GET /example) ExampleGet(ctx echo.Context) error } diff --git a/internal/test/issues/issue-f5-3231/doc.go b/internal/test/issues/issue-f5-3231/doc.go new file mode 100644 index 000000000..5083f826a --- /dev/null +++ b/internal/test/issues/issue-f5-3231/doc.go @@ -0,0 +1,3 @@ +package issue_f5_3231 + +//go:generate go run github.com/weberr13/oapi-codegen/cmd/oapi-codegen --package=issue_f5_3231 --generate types,server,client -o issue.gen.go spec.yaml diff --git a/internal/test/issues/issue-f5-3231/issue.gen.go b/internal/test/issues/issue-f5-3231/issue.gen.go new file mode 100644 index 000000000..9c0de6a67 --- /dev/null +++ b/internal/test/issues/issue-f5-3231/issue.gen.go @@ -0,0 +1,170 @@ +// Package issue_f5_3231 provides primitives to interact the openapi HTTP API. +// +// Code generated by github.com/weberr13/oapi-codegen DO NOT EDIT. +package issue_f5_3231 + +import ( + "context" + "fmt" + "net/http" + + "github.com/weberr13/oapi-codegen/pkg/runtime" +) + +// Book defines model for Book. +type Book struct { + Classification Classification `json:"classification,omitempty"` +} + +// Classification defines model for Classification. +type Classification interface{} + +// Novel defines model for Novel. +type Novel struct { + Genre *string `json:"genre,omitempty"` + Type string `json:"type"` +} + +// Textbook defines model for Textbook. +type Textbook struct { + Field *string `json:"field,omitempty"` + Type *string `json:"type,omitempty"` +} + +func factory(fm map[string]func() interface{}, path, dk string, o map[string]interface{}) (interface{}, error) { + var dp interface{} + var dv string + var ok bool + + if dp, ok = o[dk]; !ok { + return nil, fmt.Errorf("expecting OneOf object at path '%s' to to have a discriminator property '%s'", path, dk) + } + + if dv, ok = dp.(string); !ok { + return nil, fmt.Errorf("expecting OneOf field '%s's' discriminator property '%s' value to be a string", path, dk) + } + + f, ok := fm[dv] + if !ok { + return nil, fmt.Errorf("Unknown discriminator value '%s' when handling OneOf field '%s'", path, dv) + } + return f(), nil +} + +// Factory method for objects at path Book.classification +func Book_classification_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{}{ + "Novel": NewNovel, + "Textbook": NewTextbook, + } + return factory(fm, "Book.classification", "type", o) +} + +func SchemaPathFactory(path string) (func(map[string]interface{}) (interface{}, error), error) { + // Map StringPath => Factory + pathFactoryMap := map[string]func(map[string]interface{}) (interface{}, error){ + "Book.classification": Book_classification_Factory, + } + + return pathFactoryMap[path], nil +} + +func TypeFactory(kind string) (interface{}, error) { + // Map StringPath => Factory + var factoryMap = map[string]func() interface{}{ + "Novel": NewNovel, + "Textbook": NewTextbook, + } + f, ok := factoryMap[kind] + if !ok { + return nil, fmt.Errorf("cannot find type %s", kind) + } + return f(), nil +} + +func NewNovel() interface{} { + _d := "Novel" + return &Novel{Type: _d} +} + +func (r Novel) Discriminator() string { + return "type" +} + +func NewTextbook() interface{} { + _d := "Textbook" + return &Textbook{Type: &_d} +} + +func (r Textbook) Discriminator() string { + return "type" +} + +// RequestEditorFn is the function signature for the RequestEditor callback function +type RequestEditorFn func(req *http.Request, ctx context.Context) error + +type HTTPClientInterface 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 + + // HTTP client with any customized settings, such as certificate chains. + Client HTTPClientInterface + + // A callback for modifying requests which are generated before sending over + // the network. + RequestEditor RequestEditorFn +} + +// The interface specification for the client above. +type ClientInterface interface { +} + +// ClientWithResponses builds on ClientInterface to offer response payloads +type ClientWithResponses struct { + ClientInterface +} + +// NewClientWithResponses returns a ClientWithResponses with a default Client: +func NewClientWithResponses(server string) *ClientWithResponses { + return &ClientWithResponses{ + ClientInterface: &Client{ + Client: &http.Client{}, + Server: server, + }, + } +} + +// NewClientWithResponsesAndRequestEditorFunc takes in a RequestEditorFn callback function and returns a ClientWithResponses with a default Client: +func NewClientWithResponsesAndRequestEditorFunc(server string, reqEditorFn RequestEditorFn) *ClientWithResponses { + return &ClientWithResponses{ + ClientInterface: &Client{ + Client: &http.Client{}, + Server: server, + RequestEditor: reqEditorFn, + }, + } +} + +func (c *ClientWithResponses) UpdateHttpClient(cli HTTPClientInterface) { + c.ClientInterface.(*Client).Client = cli +} + +// ServerInterface represents all server handlers. +type ServerInterface interface { +} + +// ServerInterfaceWrapper converts echo contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface +} + +// RegisterHandlers adds each server route to the EchoRouter. +func RegisterHandlers(router runtime.EchoRouter, si ServerInterface) { + +} diff --git a/internal/test/issues/issue-f5-3231/issue_test.go b/internal/test/issues/issue-f5-3231/issue_test.go new file mode 100644 index 000000000..bec9723e5 --- /dev/null +++ b/internal/test/issues/issue-f5-3231/issue_test.go @@ -0,0 +1,31 @@ +package issue_f5_3231 + +import ( + "io/ioutil" + "testing" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/stretchr/testify/require" + "github.com/weberr13/oapi-codegen/pkg/codegen" +) + +func TestIssue(t *testing.T) { + // load spec from testdata identified by spec + bytes, err := ioutil.ReadFile(`spec.yaml`) + if err != nil { + t.Fatal(err) + } + // Get a spec from the test definition in this file: + swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(bytes) + require.NoError(t, err) + + opts := codegen.Options{ + GenerateClient: true, + GenerateServer: true, + GenerateTypes: true, + EmbedSpec: true, + } + + _, err = codegen.Generate(swagger, "issue_f5_3231", opts) + require.NoError(t, err) +} diff --git a/internal/test/issues/issue-f5-3231/spec.yaml b/internal/test/issues/issue-f5-3231/spec.yaml new file mode 100644 index 000000000..4961beddc --- /dev/null +++ b/internal/test/issues/issue-f5-3231/spec.yaml @@ -0,0 +1,41 @@ +openapi: 3.0.2 +info: + version: '0.0.1' + title: example + desscription: | + Ensure discriminator type is generated correctly +paths: +components: + schemas: + Book: + type: object + properties: + classification: + $ref: '#/components/schemas/Classification' + Classification: + oneOf: + - $ref: '#/components/schemas/Novel' + - $ref: '#/components/schemas/Textbook' + discriminator: + required: true + propertyName: type + + + Novel: + type: object + required: + - type + properties: + type: + type: string + genre: + type: string + + Textbook: + type: object + properties: + type: + type: string + field: + type: string + diff --git a/internal/test/parameters/doc.go b/internal/test/parameters/doc.go index e4b88fb55..0db61a22e 100644 --- a/internal/test/parameters/doc.go +++ b/internal/test/parameters/doc.go @@ -1,3 +1,3 @@ package parameters -//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --package=parameters -o parameters.gen.go parameters.yaml +//go:generate go run github.com/weberr13/oapi-codegen/cmd/oapi-codegen --package=parameters -o parameters.gen.go parameters.yaml diff --git a/internal/test/parameters/parameters.gen.go b/internal/test/parameters/parameters.gen.go deleted file mode 100644 index 835b987e5..000000000 --- a/internal/test/parameters/parameters.gen.go +++ /dev/null @@ -1,2869 +0,0 @@ -// Package parameters provides primitives to interact the openapi HTTP API. -// -// Code generated by github.com/deepmap/oapi-codegen DO NOT EDIT. -package parameters - -import ( - "bytes" - "compress/gzip" - "context" - "encoding/base64" - "encoding/json" - "fmt" - "github.com/deepmap/oapi-codegen/pkg/runtime" - "github.com/getkin/kin-openapi/openapi3" - "github.com/labstack/echo/v4" - "io/ioutil" - "net/http" - "net/url" - "strings" -) - -// ComplexObject defines model for ComplexObject. -type ComplexObject struct { - Id string `json:"Id"` - Object Object `json:"Object"` -} - -// Object defines model for Object. -type Object struct { - FirstName string `json:"firstName"` - Role string `json:"role"` -} - -// GetCookieParams defines parameters for GetCookie. -type GetCookieParams struct { - - // primitive - P *int32 `json:"p,omitempty"` - - // primitive - Ep *int32 `json:"ep,omitempty"` - - // exploded array - Ea *[]int32 `json:"ea,omitempty"` - - // array - A *[]int32 `json:"a,omitempty"` - - // exploded object - Eo *Object `json:"eo,omitempty"` - - // object - O *Object `json:"o,omitempty"` - - // complex object - Co *ComplexObject `json:"co,omitempty"` -} - -// GetHeaderParams defines parameters for GetHeader. -type GetHeaderParams struct { - - // primitive - XPrimitive *int32 `json:"X-Primitive,omitempty"` - - // primitive - XPrimitiveExploded *int32 `json:"X-Primitive-Exploded,omitempty"` - - // exploded array - XArrayExploded *[]int32 `json:"X-Array-Exploded,omitempty"` - - // array - XArray *[]int32 `json:"X-Array,omitempty"` - - // exploded object - XObjectExploded *Object `json:"X-Object-Exploded,omitempty"` - - // object - XObject *Object `json:"X-Object,omitempty"` - - // complex object - XComplexObject *ComplexObject `json:"X-Complex-Object,omitempty"` -} - -// GetQueryFormParams defines parameters for GetQueryForm. -type GetQueryFormParams struct { - - // exploded array - Ea *[]int32 `json:"ea,omitempty"` - - // array - A *[]int32 `json:"a,omitempty"` - - // exploded object - Eo *Object `json:"eo,omitempty"` - - // object - O *Object `json:"o,omitempty"` - - // exploded primitive - Ep *int32 `json:"ep,omitempty"` - - // primitive - P *int32 `json:"p,omitempty"` - - // complex object - Co *ComplexObject `json:"co,omitempty"` -} - -// RequestEditorFn is the function signature for the RequestEditor callback function -type RequestEditorFn func(req *http.Request, ctx context.Context) 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 - } - } - // 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 { - // GetContentObject request - GetContentObject(ctx context.Context, param ComplexObject) (*http.Response, error) - - // GetCookie request - GetCookie(ctx context.Context, params *GetCookieParams) (*http.Response, error) - - // GetHeader request - GetHeader(ctx context.Context, params *GetHeaderParams) (*http.Response, error) - - // GetLabelExplodeArray request - GetLabelExplodeArray(ctx context.Context, param []int32) (*http.Response, error) - - // GetLabelExplodeObject request - GetLabelExplodeObject(ctx context.Context, param Object) (*http.Response, error) - - // GetLabelNoExplodeArray request - GetLabelNoExplodeArray(ctx context.Context, param []int32) (*http.Response, error) - - // GetLabelNoExplodeObject request - GetLabelNoExplodeObject(ctx context.Context, param Object) (*http.Response, error) - - // GetMatrixExplodeArray request - GetMatrixExplodeArray(ctx context.Context, id []int32) (*http.Response, error) - - // GetMatrixExplodeObject request - GetMatrixExplodeObject(ctx context.Context, id Object) (*http.Response, error) - - // GetMatrixNoExplodeArray request - GetMatrixNoExplodeArray(ctx context.Context, id []int32) (*http.Response, error) - - // GetMatrixNoExplodeObject request - GetMatrixNoExplodeObject(ctx context.Context, id Object) (*http.Response, error) - - // GetPassThrough request - GetPassThrough(ctx context.Context, param string) (*http.Response, error) - - // GetQueryForm request - GetQueryForm(ctx context.Context, params *GetQueryFormParams) (*http.Response, error) - - // GetSimpleExplodeArray request - GetSimpleExplodeArray(ctx context.Context, param []int32) (*http.Response, error) - - // GetSimpleExplodeObject request - GetSimpleExplodeObject(ctx context.Context, param Object) (*http.Response, error) - - // GetSimpleNoExplodeArray request - GetSimpleNoExplodeArray(ctx context.Context, param []int32) (*http.Response, error) - - // GetSimpleNoExplodeObject request - GetSimpleNoExplodeObject(ctx context.Context, param Object) (*http.Response, error) - - // GetSimplePrimitive request - GetSimplePrimitive(ctx context.Context, param int32) (*http.Response, error) -} - -func (c *Client) GetContentObject(ctx context.Context, param ComplexObject) (*http.Response, error) { - req, err := NewGetContentObjectRequest(c.Server, param) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetCookie(ctx context.Context, params *GetCookieParams) (*http.Response, error) { - req, err := NewGetCookieRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetHeader(ctx context.Context, params *GetHeaderParams) (*http.Response, error) { - req, err := NewGetHeaderRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetLabelExplodeArray(ctx context.Context, param []int32) (*http.Response, error) { - req, err := NewGetLabelExplodeArrayRequest(c.Server, param) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetLabelExplodeObject(ctx context.Context, param Object) (*http.Response, error) { - req, err := NewGetLabelExplodeObjectRequest(c.Server, param) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetLabelNoExplodeArray(ctx context.Context, param []int32) (*http.Response, error) { - req, err := NewGetLabelNoExplodeArrayRequest(c.Server, param) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetLabelNoExplodeObject(ctx context.Context, param Object) (*http.Response, error) { - req, err := NewGetLabelNoExplodeObjectRequest(c.Server, param) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetMatrixExplodeArray(ctx context.Context, id []int32) (*http.Response, error) { - req, err := NewGetMatrixExplodeArrayRequest(c.Server, id) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetMatrixExplodeObject(ctx context.Context, id Object) (*http.Response, error) { - req, err := NewGetMatrixExplodeObjectRequest(c.Server, id) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetMatrixNoExplodeArray(ctx context.Context, id []int32) (*http.Response, error) { - req, err := NewGetMatrixNoExplodeArrayRequest(c.Server, id) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetMatrixNoExplodeObject(ctx context.Context, id Object) (*http.Response, error) { - req, err := NewGetMatrixNoExplodeObjectRequest(c.Server, id) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetPassThrough(ctx context.Context, param string) (*http.Response, error) { - req, err := NewGetPassThroughRequest(c.Server, param) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetQueryForm(ctx context.Context, params *GetQueryFormParams) (*http.Response, error) { - req, err := NewGetQueryFormRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetSimpleExplodeArray(ctx context.Context, param []int32) (*http.Response, error) { - req, err := NewGetSimpleExplodeArrayRequest(c.Server, param) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetSimpleExplodeObject(ctx context.Context, param Object) (*http.Response, error) { - req, err := NewGetSimpleExplodeObjectRequest(c.Server, param) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetSimpleNoExplodeArray(ctx context.Context, param []int32) (*http.Response, error) { - req, err := NewGetSimpleNoExplodeArrayRequest(c.Server, param) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetSimpleNoExplodeObject(ctx context.Context, param Object) (*http.Response, error) { - req, err := NewGetSimpleNoExplodeObjectRequest(c.Server, param) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) GetSimplePrimitive(ctx context.Context, param int32) (*http.Response, error) { - req, err := NewGetSimplePrimitiveRequest(c.Server, param) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -// NewGetContentObjectRequest generates requests for GetContentObject -func NewGetContentObjectRequest(server string, param ComplexObject) (*http.Request, error) { - var err error - - var pathParam0 string - - var pathParamBuf0 []byte - pathParamBuf0, err = json.Marshal(param) - if err != nil { - return nil, err - } - pathParam0 = string(pathParamBuf0) - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/contentObject/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetCookieRequest generates requests for GetCookie -func NewGetCookieRequest(server string, params *GetCookieParams) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/cookie")) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - if params.P != nil { - var cookieParam0 string - - cookieParam0, err = runtime.StyleParam("simple", false, "p", *params.P) - if err != nil { - return nil, err - } - - cookie0 := &http.Cookie{ - Name: "p", - Value: cookieParam0, - } - req.AddCookie(cookie0) - } - - if params.Ep != nil { - var cookieParam1 string - - cookieParam1, err = runtime.StyleParam("simple", true, "ep", *params.Ep) - if err != nil { - return nil, err - } - - cookie1 := &http.Cookie{ - Name: "ep", - Value: cookieParam1, - } - req.AddCookie(cookie1) - } - - if params.Ea != nil { - var cookieParam2 string - - cookieParam2, err = runtime.StyleParam("simple", true, "ea", *params.Ea) - if err != nil { - return nil, err - } - - cookie2 := &http.Cookie{ - Name: "ea", - Value: cookieParam2, - } - req.AddCookie(cookie2) - } - - if params.A != nil { - var cookieParam3 string - - cookieParam3, err = runtime.StyleParam("simple", false, "a", *params.A) - if err != nil { - return nil, err - } - - cookie3 := &http.Cookie{ - Name: "a", - Value: cookieParam3, - } - req.AddCookie(cookie3) - } - - if params.Eo != nil { - var cookieParam4 string - - cookieParam4, err = runtime.StyleParam("simple", true, "eo", *params.Eo) - if err != nil { - return nil, err - } - - cookie4 := &http.Cookie{ - Name: "eo", - Value: cookieParam4, - } - req.AddCookie(cookie4) - } - - if params.O != nil { - var cookieParam5 string - - cookieParam5, err = runtime.StyleParam("simple", false, "o", *params.O) - if err != nil { - return nil, err - } - - cookie5 := &http.Cookie{ - Name: "o", - Value: cookieParam5, - } - req.AddCookie(cookie5) - } - - if params.Co != nil { - var cookieParam6 string - - var cookieParamBuf6 []byte - cookieParamBuf6, err = json.Marshal(*params.Co) - if err != nil { - return nil, err - } - cookieParam6 = url.QueryEscape(string(cookieParamBuf6)) - - cookie6 := &http.Cookie{ - Name: "co", - Value: cookieParam6, - } - req.AddCookie(cookie6) - } - - return req, nil -} - -// NewGetHeaderRequest generates requests for GetHeader -func NewGetHeaderRequest(server string, params *GetHeaderParams) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/header")) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - if params.XPrimitive != nil { - var headerParam0 string - - headerParam0, err = runtime.StyleParam("simple", false, "X-Primitive", *params.XPrimitive) - if err != nil { - return nil, err - } - - req.Header.Add("X-Primitive", headerParam0) - } - - if params.XPrimitiveExploded != nil { - var headerParam1 string - - headerParam1, err = runtime.StyleParam("simple", true, "X-Primitive-Exploded", *params.XPrimitiveExploded) - if err != nil { - return nil, err - } - - req.Header.Add("X-Primitive-Exploded", headerParam1) - } - - if params.XArrayExploded != nil { - var headerParam2 string - - headerParam2, err = runtime.StyleParam("simple", true, "X-Array-Exploded", *params.XArrayExploded) - if err != nil { - return nil, err - } - - req.Header.Add("X-Array-Exploded", headerParam2) - } - - if params.XArray != nil { - var headerParam3 string - - headerParam3, err = runtime.StyleParam("simple", false, "X-Array", *params.XArray) - if err != nil { - return nil, err - } - - req.Header.Add("X-Array", headerParam3) - } - - if params.XObjectExploded != nil { - var headerParam4 string - - headerParam4, err = runtime.StyleParam("simple", true, "X-Object-Exploded", *params.XObjectExploded) - if err != nil { - return nil, err - } - - req.Header.Add("X-Object-Exploded", headerParam4) - } - - if params.XObject != nil { - var headerParam5 string - - headerParam5, err = runtime.StyleParam("simple", false, "X-Object", *params.XObject) - if err != nil { - return nil, err - } - - req.Header.Add("X-Object", headerParam5) - } - - if params.XComplexObject != nil { - var headerParam6 string - - var headerParamBuf6 []byte - headerParamBuf6, err = json.Marshal(*params.XComplexObject) - if err != nil { - return nil, err - } - headerParam6 = string(headerParamBuf6) - - req.Header.Add("X-Complex-Object", headerParam6) - } - - return req, nil -} - -// NewGetLabelExplodeArrayRequest generates requests for GetLabelExplodeArray -func NewGetLabelExplodeArrayRequest(server string, param []int32) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("label", true, "param", param) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/labelExplodeArray/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetLabelExplodeObjectRequest generates requests for GetLabelExplodeObject -func NewGetLabelExplodeObjectRequest(server string, param Object) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("label", true, "param", param) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/labelExplodeObject/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetLabelNoExplodeArrayRequest generates requests for GetLabelNoExplodeArray -func NewGetLabelNoExplodeArrayRequest(server string, param []int32) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("label", false, "param", param) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/labelNoExplodeArray/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetLabelNoExplodeObjectRequest generates requests for GetLabelNoExplodeObject -func NewGetLabelNoExplodeObjectRequest(server string, param Object) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("label", false, "param", param) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/labelNoExplodeObject/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetMatrixExplodeArrayRequest generates requests for GetMatrixExplodeArray -func NewGetMatrixExplodeArrayRequest(server string, id []int32) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("matrix", true, "id", id) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/matrixExplodeArray/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetMatrixExplodeObjectRequest generates requests for GetMatrixExplodeObject -func NewGetMatrixExplodeObjectRequest(server string, id Object) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("matrix", true, "id", id) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/matrixExplodeObject/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetMatrixNoExplodeArrayRequest generates requests for GetMatrixNoExplodeArray -func NewGetMatrixNoExplodeArrayRequest(server string, id []int32) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("matrix", false, "id", id) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/matrixNoExplodeArray/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetMatrixNoExplodeObjectRequest generates requests for GetMatrixNoExplodeObject -func NewGetMatrixNoExplodeObjectRequest(server string, id Object) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("matrix", false, "id", id) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/matrixNoExplodeObject/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetPassThroughRequest generates requests for GetPassThrough -func NewGetPassThroughRequest(server string, param string) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0 = param - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/passThrough/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetQueryFormRequest generates requests for GetQueryForm -func NewGetQueryFormRequest(server string, params *GetQueryFormParams) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/queryForm")) - if err != nil { - return nil, err - } - - queryValues := queryUrl.Query() - - if params.Ea != nil { - - if queryFrag, err := runtime.StyleParam("form", true, "ea", *params.Ea); 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) - } - } - } - - } - - if params.A != nil { - - if queryFrag, err := runtime.StyleParam("form", false, "a", *params.A); 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) - } - } - } - - } - - if params.Eo != nil { - - if queryFrag, err := runtime.StyleParam("form", true, "eo", *params.Eo); 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) - } - } - } - - } - - if params.O != nil { - - if queryFrag, err := runtime.StyleParam("form", false, "o", *params.O); 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) - } - } - } - - } - - if params.Ep != nil { - - if queryFrag, err := runtime.StyleParam("form", true, "ep", *params.Ep); 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) - } - } - } - - } - - if params.P != nil { - - if queryFrag, err := runtime.StyleParam("form", false, "p", *params.P); 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) - } - } - } - - } - - if params.Co != nil { - - if queryParamBuf, err := json.Marshal(*params.Co); err != nil { - return nil, err - } else { - queryValues.Add("co", string(queryParamBuf)) - } - - } - - queryUrl.RawQuery = queryValues.Encode() - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetSimpleExplodeArrayRequest generates requests for GetSimpleExplodeArray -func NewGetSimpleExplodeArrayRequest(server string, param []int32) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("simple", true, "param", param) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/simpleExplodeArray/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetSimpleExplodeObjectRequest generates requests for GetSimpleExplodeObject -func NewGetSimpleExplodeObjectRequest(server string, param Object) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("simple", true, "param", param) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/simpleExplodeObject/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetSimpleNoExplodeArrayRequest generates requests for GetSimpleNoExplodeArray -func NewGetSimpleNoExplodeArrayRequest(server string, param []int32) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("simple", false, "param", param) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/simpleNoExplodeArray/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetSimpleNoExplodeObjectRequest generates requests for GetSimpleNoExplodeObject -func NewGetSimpleNoExplodeObjectRequest(server string, param Object) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("simple", false, "param", param) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/simpleNoExplodeObject/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetSimplePrimitiveRequest generates requests for GetSimplePrimitive -func NewGetSimplePrimitiveRequest(server string, param int32) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("simple", false, "param", param) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/simplePrimitive/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// 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 { - if !strings.HasSuffix(baseURL, "/") { - baseURL += "/" - } - newBaseURL, err := url.Parse(baseURL) - if err != nil { - return err - } - c.Server = newBaseURL.String() - return nil - } -} - -type getContentObjectResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getContentObjectResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getContentObjectResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getCookieResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getCookieResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getCookieResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getHeaderResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getHeaderResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getHeaderResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getLabelExplodeArrayResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getLabelExplodeArrayResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getLabelExplodeArrayResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getLabelExplodeObjectResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getLabelExplodeObjectResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getLabelExplodeObjectResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getLabelNoExplodeArrayResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getLabelNoExplodeArrayResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getLabelNoExplodeArrayResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getLabelNoExplodeObjectResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getLabelNoExplodeObjectResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getLabelNoExplodeObjectResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getMatrixExplodeArrayResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getMatrixExplodeArrayResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getMatrixExplodeArrayResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getMatrixExplodeObjectResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getMatrixExplodeObjectResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getMatrixExplodeObjectResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getMatrixNoExplodeArrayResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getMatrixNoExplodeArrayResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getMatrixNoExplodeArrayResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getMatrixNoExplodeObjectResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getMatrixNoExplodeObjectResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getMatrixNoExplodeObjectResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getPassThroughResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getPassThroughResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getPassThroughResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getQueryFormResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getQueryFormResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getQueryFormResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getSimpleExplodeArrayResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getSimpleExplodeArrayResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getSimpleExplodeArrayResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getSimpleExplodeObjectResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getSimpleExplodeObjectResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getSimpleExplodeObjectResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getSimpleNoExplodeArrayResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getSimpleNoExplodeArrayResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getSimpleNoExplodeArrayResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getSimpleNoExplodeObjectResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getSimpleNoExplodeObjectResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getSimpleNoExplodeObjectResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type getSimplePrimitiveResponse struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r getSimplePrimitiveResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r getSimplePrimitiveResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// GetContentObjectWithResponse request returning *GetContentObjectResponse -func (c *ClientWithResponses) GetContentObjectWithResponse(ctx context.Context, param ComplexObject) (*getContentObjectResponse, error) { - rsp, err := c.GetContentObject(ctx, param) - if err != nil { - return nil, err - } - return ParseGetContentObjectResponse(rsp) -} - -// GetCookieWithResponse request returning *GetCookieResponse -func (c *ClientWithResponses) GetCookieWithResponse(ctx context.Context, params *GetCookieParams) (*getCookieResponse, error) { - rsp, err := c.GetCookie(ctx, params) - if err != nil { - return nil, err - } - return ParseGetCookieResponse(rsp) -} - -// GetHeaderWithResponse request returning *GetHeaderResponse -func (c *ClientWithResponses) GetHeaderWithResponse(ctx context.Context, params *GetHeaderParams) (*getHeaderResponse, error) { - rsp, err := c.GetHeader(ctx, params) - if err != nil { - return nil, err - } - return ParseGetHeaderResponse(rsp) -} - -// GetLabelExplodeArrayWithResponse request returning *GetLabelExplodeArrayResponse -func (c *ClientWithResponses) GetLabelExplodeArrayWithResponse(ctx context.Context, param []int32) (*getLabelExplodeArrayResponse, error) { - rsp, err := c.GetLabelExplodeArray(ctx, param) - if err != nil { - return nil, err - } - return ParseGetLabelExplodeArrayResponse(rsp) -} - -// GetLabelExplodeObjectWithResponse request returning *GetLabelExplodeObjectResponse -func (c *ClientWithResponses) GetLabelExplodeObjectWithResponse(ctx context.Context, param Object) (*getLabelExplodeObjectResponse, error) { - rsp, err := c.GetLabelExplodeObject(ctx, param) - if err != nil { - return nil, err - } - return ParseGetLabelExplodeObjectResponse(rsp) -} - -// GetLabelNoExplodeArrayWithResponse request returning *GetLabelNoExplodeArrayResponse -func (c *ClientWithResponses) GetLabelNoExplodeArrayWithResponse(ctx context.Context, param []int32) (*getLabelNoExplodeArrayResponse, error) { - rsp, err := c.GetLabelNoExplodeArray(ctx, param) - if err != nil { - return nil, err - } - return ParseGetLabelNoExplodeArrayResponse(rsp) -} - -// GetLabelNoExplodeObjectWithResponse request returning *GetLabelNoExplodeObjectResponse -func (c *ClientWithResponses) GetLabelNoExplodeObjectWithResponse(ctx context.Context, param Object) (*getLabelNoExplodeObjectResponse, error) { - rsp, err := c.GetLabelNoExplodeObject(ctx, param) - if err != nil { - return nil, err - } - return ParseGetLabelNoExplodeObjectResponse(rsp) -} - -// GetMatrixExplodeArrayWithResponse request returning *GetMatrixExplodeArrayResponse -func (c *ClientWithResponses) GetMatrixExplodeArrayWithResponse(ctx context.Context, id []int32) (*getMatrixExplodeArrayResponse, error) { - rsp, err := c.GetMatrixExplodeArray(ctx, id) - if err != nil { - return nil, err - } - return ParseGetMatrixExplodeArrayResponse(rsp) -} - -// GetMatrixExplodeObjectWithResponse request returning *GetMatrixExplodeObjectResponse -func (c *ClientWithResponses) GetMatrixExplodeObjectWithResponse(ctx context.Context, id Object) (*getMatrixExplodeObjectResponse, error) { - rsp, err := c.GetMatrixExplodeObject(ctx, id) - if err != nil { - return nil, err - } - return ParseGetMatrixExplodeObjectResponse(rsp) -} - -// GetMatrixNoExplodeArrayWithResponse request returning *GetMatrixNoExplodeArrayResponse -func (c *ClientWithResponses) GetMatrixNoExplodeArrayWithResponse(ctx context.Context, id []int32) (*getMatrixNoExplodeArrayResponse, error) { - rsp, err := c.GetMatrixNoExplodeArray(ctx, id) - if err != nil { - return nil, err - } - return ParseGetMatrixNoExplodeArrayResponse(rsp) -} - -// GetMatrixNoExplodeObjectWithResponse request returning *GetMatrixNoExplodeObjectResponse -func (c *ClientWithResponses) GetMatrixNoExplodeObjectWithResponse(ctx context.Context, id Object) (*getMatrixNoExplodeObjectResponse, error) { - rsp, err := c.GetMatrixNoExplodeObject(ctx, id) - if err != nil { - return nil, err - } - return ParseGetMatrixNoExplodeObjectResponse(rsp) -} - -// GetPassThroughWithResponse request returning *GetPassThroughResponse -func (c *ClientWithResponses) GetPassThroughWithResponse(ctx context.Context, param string) (*getPassThroughResponse, error) { - rsp, err := c.GetPassThrough(ctx, param) - if err != nil { - return nil, err - } - return ParseGetPassThroughResponse(rsp) -} - -// GetQueryFormWithResponse request returning *GetQueryFormResponse -func (c *ClientWithResponses) GetQueryFormWithResponse(ctx context.Context, params *GetQueryFormParams) (*getQueryFormResponse, error) { - rsp, err := c.GetQueryForm(ctx, params) - if err != nil { - return nil, err - } - return ParseGetQueryFormResponse(rsp) -} - -// GetSimpleExplodeArrayWithResponse request returning *GetSimpleExplodeArrayResponse -func (c *ClientWithResponses) GetSimpleExplodeArrayWithResponse(ctx context.Context, param []int32) (*getSimpleExplodeArrayResponse, error) { - rsp, err := c.GetSimpleExplodeArray(ctx, param) - if err != nil { - return nil, err - } - return ParseGetSimpleExplodeArrayResponse(rsp) -} - -// GetSimpleExplodeObjectWithResponse request returning *GetSimpleExplodeObjectResponse -func (c *ClientWithResponses) GetSimpleExplodeObjectWithResponse(ctx context.Context, param Object) (*getSimpleExplodeObjectResponse, error) { - rsp, err := c.GetSimpleExplodeObject(ctx, param) - if err != nil { - return nil, err - } - return ParseGetSimpleExplodeObjectResponse(rsp) -} - -// GetSimpleNoExplodeArrayWithResponse request returning *GetSimpleNoExplodeArrayResponse -func (c *ClientWithResponses) GetSimpleNoExplodeArrayWithResponse(ctx context.Context, param []int32) (*getSimpleNoExplodeArrayResponse, error) { - rsp, err := c.GetSimpleNoExplodeArray(ctx, param) - if err != nil { - return nil, err - } - return ParseGetSimpleNoExplodeArrayResponse(rsp) -} - -// GetSimpleNoExplodeObjectWithResponse request returning *GetSimpleNoExplodeObjectResponse -func (c *ClientWithResponses) GetSimpleNoExplodeObjectWithResponse(ctx context.Context, param Object) (*getSimpleNoExplodeObjectResponse, error) { - rsp, err := c.GetSimpleNoExplodeObject(ctx, param) - if err != nil { - return nil, err - } - return ParseGetSimpleNoExplodeObjectResponse(rsp) -} - -// GetSimplePrimitiveWithResponse request returning *GetSimplePrimitiveResponse -func (c *ClientWithResponses) GetSimplePrimitiveWithResponse(ctx context.Context, param int32) (*getSimplePrimitiveResponse, error) { - rsp, err := c.GetSimplePrimitive(ctx, param) - if err != nil { - return nil, err - } - return ParseGetSimplePrimitiveResponse(rsp) -} - -// ParseGetContentObjectResponse parses an HTTP response from a GetContentObjectWithResponse call -func ParseGetContentObjectResponse(rsp *http.Response) (*getContentObjectResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getContentObjectResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetCookieResponse parses an HTTP response from a GetCookieWithResponse call -func ParseGetCookieResponse(rsp *http.Response) (*getCookieResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getCookieResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetHeaderResponse parses an HTTP response from a GetHeaderWithResponse call -func ParseGetHeaderResponse(rsp *http.Response) (*getHeaderResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getHeaderResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetLabelExplodeArrayResponse parses an HTTP response from a GetLabelExplodeArrayWithResponse call -func ParseGetLabelExplodeArrayResponse(rsp *http.Response) (*getLabelExplodeArrayResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getLabelExplodeArrayResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetLabelExplodeObjectResponse parses an HTTP response from a GetLabelExplodeObjectWithResponse call -func ParseGetLabelExplodeObjectResponse(rsp *http.Response) (*getLabelExplodeObjectResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getLabelExplodeObjectResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetLabelNoExplodeArrayResponse parses an HTTP response from a GetLabelNoExplodeArrayWithResponse call -func ParseGetLabelNoExplodeArrayResponse(rsp *http.Response) (*getLabelNoExplodeArrayResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getLabelNoExplodeArrayResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetLabelNoExplodeObjectResponse parses an HTTP response from a GetLabelNoExplodeObjectWithResponse call -func ParseGetLabelNoExplodeObjectResponse(rsp *http.Response) (*getLabelNoExplodeObjectResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getLabelNoExplodeObjectResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetMatrixExplodeArrayResponse parses an HTTP response from a GetMatrixExplodeArrayWithResponse call -func ParseGetMatrixExplodeArrayResponse(rsp *http.Response) (*getMatrixExplodeArrayResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getMatrixExplodeArrayResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetMatrixExplodeObjectResponse parses an HTTP response from a GetMatrixExplodeObjectWithResponse call -func ParseGetMatrixExplodeObjectResponse(rsp *http.Response) (*getMatrixExplodeObjectResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getMatrixExplodeObjectResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetMatrixNoExplodeArrayResponse parses an HTTP response from a GetMatrixNoExplodeArrayWithResponse call -func ParseGetMatrixNoExplodeArrayResponse(rsp *http.Response) (*getMatrixNoExplodeArrayResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getMatrixNoExplodeArrayResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetMatrixNoExplodeObjectResponse parses an HTTP response from a GetMatrixNoExplodeObjectWithResponse call -func ParseGetMatrixNoExplodeObjectResponse(rsp *http.Response) (*getMatrixNoExplodeObjectResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getMatrixNoExplodeObjectResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetPassThroughResponse parses an HTTP response from a GetPassThroughWithResponse call -func ParseGetPassThroughResponse(rsp *http.Response) (*getPassThroughResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getPassThroughResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetQueryFormResponse parses an HTTP response from a GetQueryFormWithResponse call -func ParseGetQueryFormResponse(rsp *http.Response) (*getQueryFormResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getQueryFormResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetSimpleExplodeArrayResponse parses an HTTP response from a GetSimpleExplodeArrayWithResponse call -func ParseGetSimpleExplodeArrayResponse(rsp *http.Response) (*getSimpleExplodeArrayResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getSimpleExplodeArrayResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetSimpleExplodeObjectResponse parses an HTTP response from a GetSimpleExplodeObjectWithResponse call -func ParseGetSimpleExplodeObjectResponse(rsp *http.Response) (*getSimpleExplodeObjectResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getSimpleExplodeObjectResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetSimpleNoExplodeArrayResponse parses an HTTP response from a GetSimpleNoExplodeArrayWithResponse call -func ParseGetSimpleNoExplodeArrayResponse(rsp *http.Response) (*getSimpleNoExplodeArrayResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getSimpleNoExplodeArrayResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetSimpleNoExplodeObjectResponse parses an HTTP response from a GetSimpleNoExplodeObjectWithResponse call -func ParseGetSimpleNoExplodeObjectResponse(rsp *http.Response) (*getSimpleNoExplodeObjectResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getSimpleNoExplodeObjectResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseGetSimplePrimitiveResponse parses an HTTP response from a GetSimplePrimitiveWithResponse call -func ParseGetSimplePrimitiveResponse(rsp *http.Response) (*getSimplePrimitiveResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &getSimplePrimitiveResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ServerInterface represents all server handlers. -type ServerInterface interface { - - // (GET /contentObject/{param}) - GetContentObject(ctx echo.Context, param ComplexObject) error - - // (GET /cookie) - GetCookie(ctx echo.Context, params GetCookieParams) error - - // (GET /header) - GetHeader(ctx echo.Context, params GetHeaderParams) error - - // (GET /labelExplodeArray/{.param*}) - GetLabelExplodeArray(ctx echo.Context, param []int32) error - - // (GET /labelExplodeObject/{.param*}) - GetLabelExplodeObject(ctx echo.Context, param Object) error - - // (GET /labelNoExplodeArray/{.param}) - GetLabelNoExplodeArray(ctx echo.Context, param []int32) error - - // (GET /labelNoExplodeObject/{.param}) - GetLabelNoExplodeObject(ctx echo.Context, param Object) error - - // (GET /matrixExplodeArray/{.id*}) - GetMatrixExplodeArray(ctx echo.Context, id []int32) error - - // (GET /matrixExplodeObject/{.id*}) - GetMatrixExplodeObject(ctx echo.Context, id Object) error - - // (GET /matrixNoExplodeArray/{.id}) - GetMatrixNoExplodeArray(ctx echo.Context, id []int32) error - - // (GET /matrixNoExplodeObject/{.id}) - GetMatrixNoExplodeObject(ctx echo.Context, id Object) error - - // (GET /passThrough/{param}) - GetPassThrough(ctx echo.Context, param string) error - - // (GET /queryForm) - GetQueryForm(ctx echo.Context, params GetQueryFormParams) error - - // (GET /simpleExplodeArray/{param*}) - GetSimpleExplodeArray(ctx echo.Context, param []int32) error - - // (GET /simpleExplodeObject/{param*}) - GetSimpleExplodeObject(ctx echo.Context, param Object) error - - // (GET /simpleNoExplodeArray/{param}) - GetSimpleNoExplodeArray(ctx echo.Context, param []int32) error - - // (GET /simpleNoExplodeObject/{param}) - GetSimpleNoExplodeObject(ctx echo.Context, param Object) error - - // (GET /simplePrimitive/{param}) - GetSimplePrimitive(ctx echo.Context, param int32) error -} - -// ServerInterfaceWrapper converts echo contexts to parameters. -type ServerInterfaceWrapper struct { - Handler ServerInterface -} - -// GetContentObject converts echo context to params. -func (w *ServerInterfaceWrapper) GetContentObject(ctx echo.Context) error { - var err error - // ------------- Path parameter "param" ------------- - var param ComplexObject - - err = json.Unmarshal([]byte(ctx.Param("param")), ¶m) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter 'param' as JSON") - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetContentObject(ctx, param) - return err -} - -// GetCookie converts echo context to params. -func (w *ServerInterfaceWrapper) GetCookie(ctx echo.Context) error { - var err error - - // Parameter object where we will unmarshal all parameters from the context - var params GetCookieParams - - if cookie, err := ctx.Cookie("p"); err == nil { - - var value int32 - err = runtime.BindStyledParameter("simple", false, "p", cookie.Value, &value) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter p: %s", err)) - } - params.P = &value - - } - - if cookie, err := ctx.Cookie("ep"); err == nil { - - var value int32 - err = runtime.BindStyledParameter("simple", true, "ep", cookie.Value, &value) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter ep: %s", err)) - } - params.Ep = &value - - } - - if cookie, err := ctx.Cookie("ea"); err == nil { - - var value []int32 - err = runtime.BindStyledParameter("simple", true, "ea", cookie.Value, &value) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter ea: %s", err)) - } - params.Ea = &value - - } - - if cookie, err := ctx.Cookie("a"); err == nil { - - var value []int32 - err = runtime.BindStyledParameter("simple", false, "a", cookie.Value, &value) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter a: %s", err)) - } - params.A = &value - - } - - if cookie, err := ctx.Cookie("eo"); err == nil { - - var value Object - err = runtime.BindStyledParameter("simple", true, "eo", cookie.Value, &value) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter eo: %s", err)) - } - params.Eo = &value - - } - - if cookie, err := ctx.Cookie("o"); err == nil { - - var value Object - err = runtime.BindStyledParameter("simple", false, "o", cookie.Value, &value) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter o: %s", err)) - } - params.O = &value - - } - - if cookie, err := ctx.Cookie("co"); err == nil { - - var value ComplexObject - var decoded string - decoded, err := url.QueryUnescape(cookie.Value) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, "Error unescaping cookie parameter 'co'") - } - err = json.Unmarshal([]byte(decoded), &value) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter 'co' as JSON") - } - params.Co = &value - - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetCookie(ctx, params) - return err -} - -// GetHeader converts echo context to params. -func (w *ServerInterfaceWrapper) GetHeader(ctx echo.Context) error { - var err error - - // Parameter object where we will unmarshal all parameters from the context - var params GetHeaderParams - - headers := ctx.Request().Header - // ------------- Optional header parameter "X-Primitive" ------------- - if valueList, found := headers[http.CanonicalHeaderKey("X-Primitive")]; found { - var XPrimitive int32 - n := len(valueList) - if n != 1 { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-Primitive, got %d", n)) - } - - err = runtime.BindStyledParameter("simple", false, "X-Primitive", valueList[0], &XPrimitive) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter X-Primitive: %s", err)) - } - - params.XPrimitive = &XPrimitive - } - // ------------- Optional header parameter "X-Primitive-Exploded" ------------- - if valueList, found := headers[http.CanonicalHeaderKey("X-Primitive-Exploded")]; found { - var XPrimitiveExploded int32 - n := len(valueList) - if n != 1 { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-Primitive-Exploded, got %d", n)) - } - - err = runtime.BindStyledParameter("simple", true, "X-Primitive-Exploded", valueList[0], &XPrimitiveExploded) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter X-Primitive-Exploded: %s", err)) - } - - params.XPrimitiveExploded = &XPrimitiveExploded - } - // ------------- Optional header parameter "X-Array-Exploded" ------------- - if valueList, found := headers[http.CanonicalHeaderKey("X-Array-Exploded")]; found { - var XArrayExploded []int32 - n := len(valueList) - if n != 1 { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-Array-Exploded, got %d", n)) - } - - err = runtime.BindStyledParameter("simple", true, "X-Array-Exploded", valueList[0], &XArrayExploded) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter X-Array-Exploded: %s", err)) - } - - params.XArrayExploded = &XArrayExploded - } - // ------------- Optional header parameter "X-Array" ------------- - if valueList, found := headers[http.CanonicalHeaderKey("X-Array")]; found { - var XArray []int32 - n := len(valueList) - if n != 1 { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-Array, got %d", n)) - } - - err = runtime.BindStyledParameter("simple", false, "X-Array", valueList[0], &XArray) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter X-Array: %s", err)) - } - - params.XArray = &XArray - } - // ------------- Optional header parameter "X-Object-Exploded" ------------- - if valueList, found := headers[http.CanonicalHeaderKey("X-Object-Exploded")]; found { - var XObjectExploded Object - n := len(valueList) - if n != 1 { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-Object-Exploded, got %d", n)) - } - - err = runtime.BindStyledParameter("simple", true, "X-Object-Exploded", valueList[0], &XObjectExploded) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter X-Object-Exploded: %s", err)) - } - - params.XObjectExploded = &XObjectExploded - } - // ------------- Optional header parameter "X-Object" ------------- - if valueList, found := headers[http.CanonicalHeaderKey("X-Object")]; found { - var XObject Object - n := len(valueList) - if n != 1 { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-Object, got %d", n)) - } - - err = runtime.BindStyledParameter("simple", false, "X-Object", valueList[0], &XObject) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter X-Object: %s", err)) - } - - params.XObject = &XObject - } - // ------------- Optional header parameter "X-Complex-Object" ------------- - if valueList, found := headers[http.CanonicalHeaderKey("X-Complex-Object")]; found { - var XComplexObject ComplexObject - n := len(valueList) - if n != 1 { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-Complex-Object, got %d", n)) - } - - err = json.Unmarshal([]byte(valueList[0]), &XComplexObject) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter 'X-Complex-Object' as JSON") - } - - params.XComplexObject = &XComplexObject - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetHeader(ctx, params) - return err -} - -// GetLabelExplodeArray converts echo context to params. -func (w *ServerInterfaceWrapper) GetLabelExplodeArray(ctx echo.Context) error { - var err error - // ------------- Path parameter "param" ------------- - var param []int32 - - err = runtime.BindStyledParameter("label", true, "param", ctx.Param("param"), ¶m) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter param: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetLabelExplodeArray(ctx, param) - return err -} - -// GetLabelExplodeObject converts echo context to params. -func (w *ServerInterfaceWrapper) GetLabelExplodeObject(ctx echo.Context) error { - var err error - // ------------- Path parameter "param" ------------- - var param Object - - err = runtime.BindStyledParameter("label", true, "param", ctx.Param("param"), ¶m) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter param: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetLabelExplodeObject(ctx, param) - return err -} - -// GetLabelNoExplodeArray converts echo context to params. -func (w *ServerInterfaceWrapper) GetLabelNoExplodeArray(ctx echo.Context) error { - var err error - // ------------- Path parameter "param" ------------- - var param []int32 - - err = runtime.BindStyledParameter("label", false, "param", ctx.Param("param"), ¶m) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter param: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetLabelNoExplodeArray(ctx, param) - return err -} - -// GetLabelNoExplodeObject converts echo context to params. -func (w *ServerInterfaceWrapper) GetLabelNoExplodeObject(ctx echo.Context) error { - var err error - // ------------- Path parameter "param" ------------- - var param Object - - err = runtime.BindStyledParameter("label", false, "param", ctx.Param("param"), ¶m) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter param: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetLabelNoExplodeObject(ctx, param) - return err -} - -// GetMatrixExplodeArray converts echo context to params. -func (w *ServerInterfaceWrapper) GetMatrixExplodeArray(ctx echo.Context) error { - var err error - // ------------- Path parameter "id" ------------- - var id []int32 - - err = runtime.BindStyledParameter("matrix", true, "id", ctx.Param("id"), &id) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetMatrixExplodeArray(ctx, id) - return err -} - -// GetMatrixExplodeObject converts echo context to params. -func (w *ServerInterfaceWrapper) GetMatrixExplodeObject(ctx echo.Context) error { - var err error - // ------------- Path parameter "id" ------------- - var id Object - - err = runtime.BindStyledParameter("matrix", true, "id", ctx.Param("id"), &id) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetMatrixExplodeObject(ctx, id) - return err -} - -// GetMatrixNoExplodeArray converts echo context to params. -func (w *ServerInterfaceWrapper) GetMatrixNoExplodeArray(ctx echo.Context) error { - var err error - // ------------- Path parameter "id" ------------- - var id []int32 - - err = runtime.BindStyledParameter("matrix", false, "id", ctx.Param("id"), &id) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetMatrixNoExplodeArray(ctx, id) - return err -} - -// GetMatrixNoExplodeObject converts echo context to params. -func (w *ServerInterfaceWrapper) GetMatrixNoExplodeObject(ctx echo.Context) error { - var err error - // ------------- Path parameter "id" ------------- - var id Object - - err = runtime.BindStyledParameter("matrix", false, "id", ctx.Param("id"), &id) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetMatrixNoExplodeObject(ctx, id) - return err -} - -// GetPassThrough converts echo context to params. -func (w *ServerInterfaceWrapper) GetPassThrough(ctx echo.Context) error { - var err error - // ------------- Path parameter "param" ------------- - var param string - - param = ctx.Param("param") - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetPassThrough(ctx, param) - return err -} - -// GetQueryForm converts echo context to params. -func (w *ServerInterfaceWrapper) GetQueryForm(ctx echo.Context) error { - var err error - - // Parameter object where we will unmarshal all parameters from the context - var params GetQueryFormParams - // ------------- Optional query parameter "ea" ------------- - if paramValue := ctx.QueryParam("ea"); paramValue != "" { - - } - - err = runtime.BindQueryParameter("form", true, false, "ea", ctx.QueryParams(), ¶ms.Ea) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter ea: %s", err)) - } - - // ------------- Optional query parameter "a" ------------- - if paramValue := ctx.QueryParam("a"); paramValue != "" { - - } - - err = runtime.BindQueryParameter("form", false, false, "a", ctx.QueryParams(), ¶ms.A) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter a: %s", err)) - } - - // ------------- Optional query parameter "eo" ------------- - if paramValue := ctx.QueryParam("eo"); paramValue != "" { - - } - - err = runtime.BindQueryParameter("form", true, false, "eo", ctx.QueryParams(), ¶ms.Eo) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter eo: %s", err)) - } - - // ------------- Optional query parameter "o" ------------- - if paramValue := ctx.QueryParam("o"); paramValue != "" { - - } - - err = runtime.BindQueryParameter("form", false, false, "o", ctx.QueryParams(), ¶ms.O) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter o: %s", err)) - } - - // ------------- Optional query parameter "ep" ------------- - if paramValue := ctx.QueryParam("ep"); paramValue != "" { - - } - - err = runtime.BindQueryParameter("form", true, false, "ep", ctx.QueryParams(), ¶ms.Ep) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter ep: %s", err)) - } - - // ------------- Optional query parameter "p" ------------- - if paramValue := ctx.QueryParam("p"); paramValue != "" { - - } - - err = runtime.BindQueryParameter("form", false, false, "p", ctx.QueryParams(), ¶ms.P) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter p: %s", err)) - } - - // ------------- Optional query parameter "co" ------------- - if paramValue := ctx.QueryParam("co"); paramValue != "" { - - var value ComplexObject - err = json.Unmarshal([]byte(paramValue), &value) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter 'co' as JSON") - } - params.Co = &value - - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetQueryForm(ctx, params) - return err -} - -// GetSimpleExplodeArray converts echo context to params. -func (w *ServerInterfaceWrapper) GetSimpleExplodeArray(ctx echo.Context) error { - var err error - // ------------- Path parameter "param" ------------- - var param []int32 - - err = runtime.BindStyledParameter("simple", true, "param", ctx.Param("param"), ¶m) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter param: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetSimpleExplodeArray(ctx, param) - return err -} - -// GetSimpleExplodeObject converts echo context to params. -func (w *ServerInterfaceWrapper) GetSimpleExplodeObject(ctx echo.Context) error { - var err error - // ------------- Path parameter "param" ------------- - var param Object - - err = runtime.BindStyledParameter("simple", true, "param", ctx.Param("param"), ¶m) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter param: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetSimpleExplodeObject(ctx, param) - return err -} - -// GetSimpleNoExplodeArray converts echo context to params. -func (w *ServerInterfaceWrapper) GetSimpleNoExplodeArray(ctx echo.Context) error { - var err error - // ------------- Path parameter "param" ------------- - var param []int32 - - err = runtime.BindStyledParameter("simple", false, "param", ctx.Param("param"), ¶m) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter param: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetSimpleNoExplodeArray(ctx, param) - return err -} - -// GetSimpleNoExplodeObject converts echo context to params. -func (w *ServerInterfaceWrapper) GetSimpleNoExplodeObject(ctx echo.Context) error { - var err error - // ------------- Path parameter "param" ------------- - var param Object - - err = runtime.BindStyledParameter("simple", false, "param", ctx.Param("param"), ¶m) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter param: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetSimpleNoExplodeObject(ctx, param) - return err -} - -// GetSimplePrimitive converts echo context to params. -func (w *ServerInterfaceWrapper) GetSimplePrimitive(ctx echo.Context) error { - var err error - // ------------- Path parameter "param" ------------- - var param int32 - - err = runtime.BindStyledParameter("simple", false, "param", ctx.Param("param"), ¶m) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter param: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.GetSimplePrimitive(ctx, param) - return err -} - -// RegisterHandlers adds each server route to the EchoRouter. -func RegisterHandlers(router 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 -}, si ServerInterface) { - - wrapper := ServerInterfaceWrapper{ - Handler: si, - } - - router.GET("/contentObject/:param", wrapper.GetContentObject) - router.GET("/cookie", wrapper.GetCookie) - router.GET("/header", wrapper.GetHeader) - router.GET("/labelExplodeArray/:param", wrapper.GetLabelExplodeArray) - router.GET("/labelExplodeObject/:param", wrapper.GetLabelExplodeObject) - router.GET("/labelNoExplodeArray/:param", wrapper.GetLabelNoExplodeArray) - router.GET("/labelNoExplodeObject/:param", wrapper.GetLabelNoExplodeObject) - router.GET("/matrixExplodeArray/:id", wrapper.GetMatrixExplodeArray) - router.GET("/matrixExplodeObject/:id", wrapper.GetMatrixExplodeObject) - router.GET("/matrixNoExplodeArray/:id", wrapper.GetMatrixNoExplodeArray) - router.GET("/matrixNoExplodeObject/:id", wrapper.GetMatrixNoExplodeObject) - router.GET("/passThrough/:param", wrapper.GetPassThrough) - router.GET("/queryForm", wrapper.GetQueryForm) - router.GET("/simpleExplodeArray/:param", wrapper.GetSimpleExplodeArray) - router.GET("/simpleExplodeObject/:param", wrapper.GetSimpleExplodeObject) - router.GET("/simpleNoExplodeArray/:param", wrapper.GetSimpleNoExplodeArray) - router.GET("/simpleNoExplodeObject/:param", wrapper.GetSimpleNoExplodeObject) - router.GET("/simplePrimitive/:param", wrapper.GetSimplePrimitive) - -} - -// Base64 encoded, gzipped, json marshaled Swagger object -var swaggerSpec = []string{ - - "H4sIAAAAAAAC/9xZyW7jOBD9FaNmTgO15e6+6dYIZgkwWWacwwCBD4xUtpmRRIakAxuG/r1BarG1WKYS", - "WXZyi6VaXj0+VcjiFnwWcRZjrCR4WxAoOYslmh9TGvEQ/80e6Sc+ixXGSv+pcK1cHhIa61/SX2JEzPMN", - "R/BAKkHjBSRJ4kCA0heUK8pi8ODHSJq4ozzXiD09o69Am6ZxTPYrpq3Wd+lLbwtcMI5C0RTcddCQzYGd", - "+a8C5+DBL+6uQjcL797tMgp8WVGBAXiPubOjg89Kwcq551RIdUsibIQgWNj0opLLWDl7oWaGKxrPmXYO", - "qY8Z6bFJBDfXDzq6okqHhweUajRF8YoCHHhFIVN6v44n44k2ZBxjwil48H08GX8FBzhRS4PfzdYxrc/d", - "ciJIlOg3CzTl6mKJXi/NMvyJ6mrfwYQSJEKFQoL3WNIF4TykvnF2nyWrqKNtUcoLnrEBnoENTk6DyQz7", - "XCqxwmTmlLX7bTI5lK+wcysCT0xO12fsf4rtbBiLGg1loXNBI6roqzbENQ9ZgODNSSgxK8zPw+SllcrK", - "LHfczZmIiAIPaKy+fwMnFxiNFS5QaIVZQdB8HUCA/UPI0gYjIgTZ2OIg7TiowkhaASqepOkbANZwtS3R", - "gLgK4lj+0Vkxx9oR2nXFKpY6hDaSeoJwqqZSLs1PDXYsN5bkN9SUzEy7WCIJULS1i79Si/e2i2UeJsP0", - "35f7PZdhG0cLli+/Z8I9TyupI/uhrS1RDdZYDsC8tPZSh5l+SZZ0nqLbHIL08ZtOvbIs0MEKsxYUkicM", - "sxUxMnK3Y9Nrfmvd1P1ddau3qCZN2OzH+lGtA1JtzG7XVAg97fIckKsoImIDXrwKwxqF+ba4K4eHdsd9", - "kGij36HpumVNmjtOV9mvha/9z/7zqq6go6y7DjweFd57iLww5UVECbquCI8G7V/pTc3pLV8pDU6uuLS6", - "wfgrFNeJwLf3uSMMdpPaUFzV2hwNLLjqocl9Ir3Ve1w3Et/R4T6Y5jiR8mEp2GqxtBnM3e/MW8dyHca1", - "Zxm6vaxQbP5gImor9p/C6MhZ2uqkaFIOMXPayUe7QseTYgXm+VDanRirrJ5hHlWBcBIEBRnHJiVVPgYa", - "8rbw0QeCcx6TK+U0j+b660zpbVV5C2BxMJzW3C73dJ2WeMr/aiUSS9dOHVi8nPP1UIRVt57H9wPTBr8L", - "PmEPTqT9lee0yfEizthDkVaM9O3p2r+RqBD1JmIspHUaVkzvl+Z6PYW/EiF4sFSKe66b3a0rlGocIPKI", - "8DGhkMySnwEAAP//njtWvlEhAAA=", -} - -// 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 -} diff --git a/internal/test/parameters/parameters_test.go b/internal/test/parameters/parameters_test.go index 466a54ff5..8755b5566 100644 --- a/internal/test/parameters/parameters_test.go +++ b/internal/test/parameters/parameters_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/deepmap/oapi-codegen/pkg/testutil" + "github.com/weberr13/oapi-codegen/pkg/testutil" ) type testServer struct { diff --git a/internal/test/schemas/doc.go b/internal/test/schemas/doc.go index 81a093624..f6dc80930 100644 --- a/internal/test/schemas/doc.go +++ b/internal/test/schemas/doc.go @@ -1,3 +1,3 @@ package schemas -//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --package=schemas -o schemas.gen.go schemas.yaml +//go:generate go run github.com/weberr13/oapi-codegen/cmd/oapi-codegen --package=schemas -o schemas.gen.go schemas.yaml diff --git a/internal/test/schemas/schemas.gen.go b/internal/test/schemas/schemas.gen.go deleted file mode 100644 index b8fe16f42..000000000 --- a/internal/test/schemas/schemas.gen.go +++ /dev/null @@ -1,612 +0,0 @@ -// Package schemas provides primitives to interact the openapi HTTP API. -// -// Code generated by github.com/deepmap/oapi-codegen DO NOT EDIT. -package schemas - -import ( - "bytes" - "compress/gzip" - "context" - "encoding/base64" - "encoding/json" - "fmt" - "github.com/deepmap/oapi-codegen/pkg/runtime" - "github.com/getkin/kin-openapi/openapi3" - "github.com/labstack/echo/v4" - "io" - "io/ioutil" - "net/http" - "net/url" - "strings" -) - -// N5StartsWithNumber defines model for 5StartsWithNumber. -type N5StartsWithNumber map[string]interface{} - -// AnyType1 defines model for AnyType1. -type AnyType1 interface{} - -// AnyType2 defines model for AnyType2. -type AnyType2 interface{} - -// CustomStringType defines model for CustomStringType. -type CustomStringType string - -// GenericObject defines model for GenericObject. -type GenericObject map[string]interface{} - -// Issue9JSONBody defines parameters for Issue9. -type Issue9JSONBody interface{} - -// Issue9Params defines parameters for Issue9. -type Issue9Params struct { - Foo string `json:"foo"` -} - -// Issue9RequestBody defines body for Issue9 for application/json ContentType. -type Issue9JSONRequestBody Issue9JSONBody - -// RequestEditorFn is the function signature for the RequestEditor callback function -type RequestEditorFn func(req *http.Request, ctx context.Context) 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 - } - } - // 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 { - // Issue30 request - Issue30(ctx context.Context, pFallthrough string) (*http.Response, error) - - // Issue41 request - Issue41(ctx context.Context, n1param N5StartsWithNumber) (*http.Response, error) - - // Issue9 request with any body - Issue9WithBody(ctx context.Context, params *Issue9Params, contentType string, body io.Reader) (*http.Response, error) - - Issue9(ctx context.Context, params *Issue9Params, body Issue9JSONRequestBody) (*http.Response, error) -} - -func (c *Client) Issue30(ctx context.Context, pFallthrough string) (*http.Response, error) { - req, err := NewIssue30Request(c.Server, pFallthrough) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) Issue41(ctx context.Context, n1param N5StartsWithNumber) (*http.Response, error) { - req, err := NewIssue41Request(c.Server, n1param) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) Issue9WithBody(ctx context.Context, params *Issue9Params, contentType string, body io.Reader) (*http.Response, error) { - req, err := NewIssue9RequestWithBody(c.Server, params, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -func (c *Client) Issue9(ctx context.Context, params *Issue9Params, body Issue9JSONRequestBody) (*http.Response, error) { - req, err := NewIssue9Request(c.Server, params, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if c.RequestEditor != nil { - err = c.RequestEditor(req, ctx) - if err != nil { - return nil, err - } - } - return c.Client.Do(req) -} - -// NewIssue30Request generates requests for Issue30 -func NewIssue30Request(server string, pFallthrough string) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("simple", false, "fallthrough", pFallthrough) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/issues/30/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewIssue41Request generates requests for Issue41 -func NewIssue41Request(server string, n1param N5StartsWithNumber) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParam("simple", false, "1param", n1param) - if err != nil { - return nil, err - } - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/issues/41/%s", pathParam0)) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryUrl.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewIssue9Request calls the generic Issue9 builder with application/json body -func NewIssue9Request(server string, params *Issue9Params, body Issue9JSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewIssue9RequestWithBody(server, params, "application/json", bodyReader) -} - -// NewIssue9RequestWithBody generates requests for Issue9 with any type of body -func NewIssue9RequestWithBody(server string, params *Issue9Params, contentType string, body io.Reader) (*http.Request, error) { - var err error - - queryUrl, err := url.Parse(server) - if err != nil { - return nil, err - } - queryUrl, err = queryUrl.Parse(fmt.Sprintf("/issues/9")) - if err != nil { - return nil, err - } - - queryValues := queryUrl.Query() - - if queryFrag, err := runtime.StyleParam("form", true, "foo", params.Foo); 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) - } - } - } - - queryUrl.RawQuery = queryValues.Encode() - - req, err := http.NewRequest("GET", queryUrl.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - return req, nil -} - -// 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 { - if !strings.HasSuffix(baseURL, "/") { - baseURL += "/" - } - newBaseURL, err := url.Parse(baseURL) - if err != nil { - return err - } - c.Server = newBaseURL.String() - return nil - } -} - -type issue30Response struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r issue30Response) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r issue30Response) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type issue41Response struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r issue41Response) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r issue41Response) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type issue9Response struct { - Body []byte - HTTPResponse *http.Response -} - -// Status returns HTTPResponse.Status -func (r issue9Response) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r issue9Response) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// Issue30WithResponse request returning *Issue30Response -func (c *ClientWithResponses) Issue30WithResponse(ctx context.Context, pFallthrough string) (*issue30Response, error) { - rsp, err := c.Issue30(ctx, pFallthrough) - if err != nil { - return nil, err - } - return ParseIssue30Response(rsp) -} - -// Issue41WithResponse request returning *Issue41Response -func (c *ClientWithResponses) Issue41WithResponse(ctx context.Context, n1param N5StartsWithNumber) (*issue41Response, error) { - rsp, err := c.Issue41(ctx, n1param) - if err != nil { - return nil, err - } - return ParseIssue41Response(rsp) -} - -// Issue9WithBodyWithResponse request with arbitrary body returning *Issue9Response -func (c *ClientWithResponses) Issue9WithBodyWithResponse(ctx context.Context, params *Issue9Params, contentType string, body io.Reader) (*issue9Response, error) { - rsp, err := c.Issue9WithBody(ctx, params, contentType, body) - if err != nil { - return nil, err - } - return ParseIssue9Response(rsp) -} - -func (c *ClientWithResponses) Issue9WithResponse(ctx context.Context, params *Issue9Params, body Issue9JSONRequestBody) (*issue9Response, error) { - rsp, err := c.Issue9(ctx, params, body) - if err != nil { - return nil, err - } - return ParseIssue9Response(rsp) -} - -// ParseIssue30Response parses an HTTP response from a Issue30WithResponse call -func ParseIssue30Response(rsp *http.Response) (*issue30Response, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &issue30Response{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseIssue41Response parses an HTTP response from a Issue41WithResponse call -func ParseIssue41Response(rsp *http.Response) (*issue41Response, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &issue41Response{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ParseIssue9Response parses an HTTP response from a Issue9WithResponse call -func ParseIssue9Response(rsp *http.Response) (*issue9Response, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer rsp.Body.Close() - if err != nil { - return nil, err - } - - response := &issue9Response{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - } - - return response, nil -} - -// ServerInterface represents all server handlers. -type ServerInterface interface { - - // (GET /issues/30/{fallthrough}) - Issue30(ctx echo.Context, pFallthrough string) error - - // (GET /issues/41/{1param}) - Issue41(ctx echo.Context, n1param N5StartsWithNumber) error - - // (GET /issues/9) - Issue9(ctx echo.Context, params Issue9Params) error -} - -// ServerInterfaceWrapper converts echo contexts to parameters. -type ServerInterfaceWrapper struct { - Handler ServerInterface -} - -// Issue30 converts echo context to params. -func (w *ServerInterfaceWrapper) Issue30(ctx echo.Context) error { - var err error - // ------------- Path parameter "fallthrough" ------------- - var pFallthrough string - - err = runtime.BindStyledParameter("simple", false, "fallthrough", ctx.Param("fallthrough"), &pFallthrough) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter fallthrough: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.Issue30(ctx, pFallthrough) - return err -} - -// Issue41 converts echo context to params. -func (w *ServerInterfaceWrapper) Issue41(ctx echo.Context) error { - var err error - // ------------- Path parameter "1param" ------------- - var n1param N5StartsWithNumber - - err = runtime.BindStyledParameter("simple", false, "1param", ctx.Param("1param"), &n1param) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter 1param: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.Issue41(ctx, n1param) - return err -} - -// Issue9 converts echo context to params. -func (w *ServerInterfaceWrapper) Issue9(ctx echo.Context) error { - var err error - - // Parameter object where we will unmarshal all parameters from the context - var params Issue9Params - // ------------- Required query parameter "foo" ------------- - if paramValue := ctx.QueryParam("foo"); paramValue != "" { - - } else { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Query argument foo is required, but not found")) - } - - err = runtime.BindQueryParameter("form", true, true, "foo", ctx.QueryParams(), ¶ms.Foo) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter foo: %s", err)) - } - - // Invoke the callback with all the unmarshalled arguments - err = w.Handler.Issue9(ctx, params) - return err -} - -// RegisterHandlers adds each server route to the EchoRouter. -func RegisterHandlers(router 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 -}, si ServerInterface) { - - wrapper := ServerInterfaceWrapper{ - Handler: si, - } - - router.GET("/issues/30/:fallthrough", wrapper.Issue30) - router.GET("/issues/41/:1param", wrapper.Issue41) - router.GET("/issues/9", wrapper.Issue9) - -} - -// Base64 encoded, gzipped, json marshaled Swagger object -var swaggerSpec = []string{ - - "H4sIAAAAAAAC/5STQVPbMBCF/8rOtkePnRR6QLeWQ4dLYQozPRQOirWORW1JSKtQj8f/vSM5IaZAO70p", - "jlbvfW93R6xt76whwwHFiKFuqZf5+PGapefwXXP7NfYb8umjolB77VhbgwJvWh1gLgEje4KQS+BRcwsS", - "zFxWIA+OUKDd3FPNOBX4yQw3g6M1ivH468NbAq2NnYINgTSgDZNvZE3jlB46j4Ftf81em+1NVhmxsb6X", - "jALr/OdRP+RrqewLGfK6vpwNifFPh9NUoDaNfcURBYZaBgrQWA876bWNAXQIMX+KRoHdkQfWPZVw1ZEM", - "BFIpkMCH2lR6a6QZYBO30OhfpMpbk4xq7uigck1+l+PbkQ+z+rpclasEYB0Z6TQKPClX5RoLdJLb3Ldq", - "9lKdrKqxkV3Hrbdx204vWb5RSBIKftLwaL1aRu08ZV+gTYaUm45yj8PsdEs5N+vIy/TchUKBF0n5JBt0", - "0suemHxA8WNEnfSSRSwwvYICF96wQE8PUXtSKNhHKvaDuGjNoXnT3VQ8MZ6uq3GdpTLe3tRzyquDk8WI", - "arOdh/RpRF8BOZ1j/RfHrP9XhPeeGhT4rjouW7XftOrlmiXEBePZm2TnnSbDkPUDpJxAm9p6TzV3Qzp3", - "UZHKg5rMpaHK1BurBpBG3Zoj3tzWV2I4eyOFh0h+WLTT2v9r43yZAn+2akg3amuYTOaUznW6zkaq+5Bg", - "x+NTeTufJ3GZD7LLZM9sNLILNOWSPOx7gug7FNgyO1FV+2VK61kqItdLV0qN0930OwAA///Z/BiYHwUA", - "AA==", -} - -// 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 -} diff --git a/internal/test/server/server.gen.go b/internal/test/server/server.gen.go index 5babef1eb..aa5d8822b 100644 --- a/internal/test/server/server.gen.go +++ b/internal/test/server/server.gen.go @@ -365,7 +365,7 @@ func Handler(si ServerInterface) http.Handler { } // HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux. -func HandlerFromMux(si ServerInterface, r chi.Router) http.Handler { +func HandlerFromMux(si ServerInterface, r *chi.Mux) http.Handler { r.Group(func(r chi.Router) { r.Use(GetSimpleCtx) r.Get("/get-simple", si.GetSimple) diff --git a/pkg/codegen/codegen.go b/pkg/codegen/codegen.go index 90015ee59..03d5bdaa2 100644 --- a/pkg/codegen/codegen.go +++ b/pkg/codegen/codegen.go @@ -19,6 +19,7 @@ import ( "bytes" "fmt" "go/format" + "os" "regexp" "sort" "strings" @@ -27,19 +28,21 @@ import ( "github.com/getkin/kin-openapi/openapi3" "github.com/pkg/errors" - "github.com/deepmap/oapi-codegen/pkg/codegen/templates" + "github.com/weberr13/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 - 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. + 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 + 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. + ClearRefsSpec bool // Whether to resolve all references in the included swagger spec + ImportedTypes map[string]TypeImportSpec // Additional imports added when using remote references } type goImport struct { @@ -72,19 +75,47 @@ var ( {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: "openapi_types\\.", alias: "openapi_types", packageName: "github.com/weberr13/oapi-codegen/pkg/types"}, {lookFor: "path\\.", packageName: "path"}, - {lookFor: "runtime\\.", packageName: "github.com/deepmap/oapi-codegen/pkg/runtime"}, + {lookFor: "runtime\\.", packageName: "github.com/weberr13/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"}, + {lookFor: "decode\\.", packageName: "github.com/weberr13/go-decode/decode"}, } ) // Uses the Go templating engine to generate all of our server wrappers from + +type genCtx struct { + PackageName string + TypeDefs []TypeDefinition + OpDefs []OperationDefinition + GoSchemaMap map[string]Schema + ImportedTypes map[string]TypeImportSpec + Swagger *openapi3.Swagger + HasDecorators bool +} + +func newGenCtx(swagger *openapi3.Swagger, packageName string, opts Options) *genCtx { + return &genCtx{Swagger: swagger, PackageName: packageName, + TypeDefs: []TypeDefinition{}, GoSchemaMap: map[string]Schema{}, + ImportedTypes: opts.ImportedTypes, + } +} + +func (ctx *genCtx) getAllOpTypes() []TypeDefinition { + var td []TypeDefinition + for _, op := range ctx.OpDefs { + td = append(td, op.TypeDefinitions...) + } + return td +} + +// Generate 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) { @@ -99,14 +130,19 @@ func Generate(swagger *openapi3.Swagger, packageName string, opts Options) (stri return "", errors.Wrap(err, "error parsing oapi-codegen templates") } - ops, err := OperationDefinitions(swagger) - if err != nil { - return "", errors.Wrap(err, "error creating operation definitions") + ctx := newGenCtx(swagger, packageName, opts) + + // only generate operation typedefs if not producing resolved spec + if !opts.ClearRefsSpec { + err = OperationDefinitions(ctx, swagger) + if err != nil { + return "", errors.Wrap(err, "error creating operation definitions") + } } var typeDefinitions string if opts.GenerateTypes { - typeDefinitions, err = GenerateTypeDefinitions(t, swagger, ops) + typeDefinitions, err = GenerateTypeDefinitions(ctx, t, swagger) if err != nil { return "", errors.Wrap(err, "error generating type definitions") } @@ -130,7 +166,7 @@ func Generate(swagger *openapi3.Swagger, packageName string, opts Options) (stri var clientOut string if opts.GenerateClient { - clientOut, err = GenerateClient(t, ops) + clientOut, err = GenerateClient(ctx, t) if err != nil { return "", errors.Wrap(err, "error generating client") } @@ -138,7 +174,7 @@ func Generate(swagger *openapi3.Swagger, packageName string, opts Options) (stri var clientWithResponsesOut string if opts.GenerateClient { - clientWithResponsesOut, err = GenerateClientWithResponses(t, ops) + clientWithResponsesOut, err = GenerateClientWithResponses(ctx, t) if err != nil { return "", errors.Wrap(err, "error generating client with responses") } @@ -146,18 +182,25 @@ func Generate(swagger *openapi3.Swagger, packageName string, opts Options) (stri var inlinedSpec string if opts.EmbedSpec { - inlinedSpec, err = GenerateInlinedSpec(t, swagger) + inlinedSpec, err = GenerateInlinedSpec(ctx, 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 + var imports []TypeImportSpec var buf bytes.Buffer w := bufio.NewWriter(&buf) + // TODO: this is error prone, use tighter matches + allCode := strings.Join([]string{typeDefinitions, echoServerOut, chiServerOut, clientOut, clientWithResponsesOut, inlinedSpec}, "\n") + for t, i := range ctx.ImportedTypes { + if strings.Contains(allCode, t) { + allGoImports = append(allGoImports, goImport{lookFor: `\` + i.Name, packageName: i.PackageName}) + } + } // Based on module prefixes, figure out which optional imports are required. for _, str := range []string{typeDefinitions, chiServerOut, echoServerOut, clientOut, clientWithResponsesOut, inlinedSpec} { for _, goImport := range allGoImports { @@ -171,7 +214,7 @@ func Generate(swagger *openapi3.Swagger, packageName string, opts Options) (stri } } - importsOut, err := GenerateImports(t, imports, packageName) + importsOut, err := GenerateImports(ctx, t, imports) if err != nil { return "", errors.Wrap(err, "error generating imports") } @@ -240,41 +283,39 @@ func Generate(swagger *openapi3.Swagger, packageName string, opts Options) (stri return string(outBytes), nil } -func GenerateTypeDefinitions(t *template.Template, swagger *openapi3.Swagger, ops []OperationDefinition) (string, error) { - schemaTypes, err := GenerateTypesForSchemas(t, swagger.Components.Schemas) +func GenerateTypeDefinitions(ctx *genCtx, t *template.Template, swagger *openapi3.Swagger) (string, error) { + var err error + + err = GenerateTypesForSchemas(ctx, t, swagger.Components.Schemas) if err != nil { return "", errors.Wrap(err, "error generating Go types for component schemas") } - paramTypes, err := GenerateTypesForParameters(t, swagger.Components.Parameters) + err = GenerateTypesForParameters(ctx, 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) + err = GenerateTypesForResponses(ctx, 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) + err = GenerateTypesForRequestBodies(ctx, 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) + paramTypesOut, err := GenerateTypesForOperations(ctx, t) if err != nil { return "", errors.Wrap(err, "error generating Go types for operation parameters") } - typesOut, err := GenerateTypes(t, allTypes) + typesOut, err := GenerateTypes(ctx, t) if err != nil { return "", errors.Wrap(err, "error generating code for type definitions") } - - allOfBoilerplate, err := GenerateAdditionalPropertyBoilerplate(t, allTypes) + allOfBoilerplate, err := GenerateAdditionalPropertyBoilerplate(ctx, t, ctx.TypeDefs) if err != nil { return "", errors.Wrap(err, "error generating allOf boilerplate") } @@ -285,38 +326,37 @@ func GenerateTypeDefinitions(t *template.Template, swagger *openapi3.Swagger, op // 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) ([]TypeDefinition, error) { - types := make([]TypeDefinition, 0) +func GenerateTypesForSchemas(ctx *genCtx, t *template.Template, schemas map[string]*openapi3.SchemaRef) error { + // We're going to define Go types for every object under components/schemas for _, schemaName := range SortedSchemaKeys(schemas) { schemaRef := schemas[schemaName] - goSchema, err := GenerateGoSchema(schemaRef, []string{schemaName}) + goSchema, err := GenerateGoSchema(ctx, schemaRef, []string{schemaName}) if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error converting Schema %s to Go type", schemaName)) + return errors.Wrap(err, fmt.Sprintf("error converting Schema %s to Go type", schemaName)) } - types = append(types, TypeDefinition{ + ctx.TypeDefs = append(ctx.TypeDefs, TypeDefinition{ JsonName: schemaName, TypeName: SchemaNameToTypeName(schemaName), Schema: goSchema, }) - types = append(types, goSchema.GetAdditionalTypeDefs()...) + ctx.TypeDefs = append(ctx.TypeDefs, goSchema.GetAdditionalTypeDefs()...) } - return types, nil + return 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 +func GenerateTypesForParameters(ctx *genCtx, t *template.Template, params map[string]*openapi3.ParameterRef) error { for _, paramName := range SortedParameterKeys(params) { paramOrRef := params[paramName] - goType, err := paramToGoType(paramOrRef.Value, nil) + goType, err := paramToGoType(ctx, paramOrRef.Value, nil) if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error generating Go type for schema in parameter %s", paramName)) + return errors.Wrap(err, fmt.Sprintf("error generating Go type for schema in parameter %s", paramName)) } typeDef := TypeDefinition{ @@ -327,22 +367,21 @@ func GenerateTypesForParameters(t *template.Template, params map[string]*openapi if paramOrRef.Ref != "" { // Generate a reference type for referenced parameters - refType, err := RefPathToGoType(paramOrRef.Ref) + refType, err := RefPathToGoType(paramOrRef.Ref, ctx.ImportedTypes) if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error generating Go type for (%s) in parameter %s", paramOrRef.Ref, paramName)) + return 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) + ctx.TypeDefs = append(ctx.TypeDefs, typeDef) } - return types, nil + return 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 +func GenerateTypesForResponses(ctx *genCtx, t *template.Template, responses openapi3.Responses) error { for _, responseName := range SortedResponsesKeys(responses) { responseOrRef := responses[responseName] @@ -353,9 +392,9 @@ func GenerateTypesForResponses(t *template.Template, responses openapi3.Response response := responseOrRef.Value jsonResponse, found := response.Content["application/json"] if found { - goType, err := GenerateGoSchema(jsonResponse.Schema, []string{responseName}) + goType, err := GenerateGoSchema(ctx, jsonResponse.Schema, []string{responseName}) if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error generating Go type for schema in response %s", responseName)) + return errors.Wrap(err, fmt.Sprintf("error generating Go type for schema in response %s", responseName)) } typeDef := TypeDefinition{ @@ -366,21 +405,21 @@ func GenerateTypesForResponses(t *template.Template, responses openapi3.Response if responseOrRef.Ref != "" { // Generate a reference type for referenced parameters - refType, err := RefPathToGoType(responseOrRef.Ref) + refType, err := RefPathToGoType(responseOrRef.Ref, ctx.ImportedTypes) if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error generating Go type for (%s) in parameter %s", responseOrRef.Ref, responseName)) + return 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) + ctx.TypeDefs = append(ctx.TypeDefs, typeDef) } } - return types, nil + return 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) { +func GenerateTypesForRequestBodies(ctx *genCtx, t *template.Template, bodies map[string]*openapi3.RequestBodyRef) error { var types []TypeDefinition for _, bodyName := range SortedRequestBodyKeys(bodies) { @@ -391,9 +430,9 @@ func GenerateTypesForRequestBodies(t *template.Template, bodies map[string]*open response := bodyOrRef.Value jsonBody, found := response.Content["application/json"] if found { - goType, err := GenerateGoSchema(jsonBody.Schema, []string{bodyName}) + goType, err := GenerateGoSchema(ctx, jsonBody.Schema, []string{bodyName}) if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error generating Go type for schema in body %s", bodyName)) + return errors.Wrap(err, fmt.Sprintf("error generating Go type for schema in body %s", bodyName)) } typeDef := TypeDefinition{ @@ -404,31 +443,26 @@ func GenerateTypesForRequestBodies(t *template.Template, bodies map[string]*open if bodyOrRef.Ref != "" { // Generate a reference type for referenced bodies - refType, err := RefPathToGoType(bodyOrRef.Ref) + refType, err := RefPathToGoType(bodyOrRef.Ref, ctx.ImportedTypes) if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("error generating Go type for (%s) in body %s", bodyOrRef.Ref, bodyName)) + return 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 + ctx.TypeDefs = append(ctx.TypeDefs, types...) + return 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) { +func GenerateTypes(ctx *genCtx, t *template.Template) (string, error) { var buf bytes.Buffer w := bufio.NewWriter(&buf) - context := struct { - Types []TypeDefinition - }{ - Types: types, - } - - err := t.ExecuteTemplate(w, "typedef.tmpl", context) + err := t.ExecuteTemplate(w, "typedef.tmpl", ctx) if err != nil { return "", errors.Wrap(err, "error generating types") } @@ -440,17 +474,17 @@ func GenerateTypes(t *template.Template, types []TypeDefinition) (string, error) } // Generate our import statements and package definition. -func GenerateImports(t *template.Template, imports []string, packageName string) (string, error) { - sort.Strings(imports) +func GenerateImports(ctx *genCtx, t *template.Template, imports []TypeImportSpec) (string, error) { + sort.Slice(imports, func(i, j int) bool { return imports[i].ImportPath < imports[j].ImportPath }) var buf bytes.Buffer w := bufio.NewWriter(&buf) context := struct { - Imports []string + Imports []TypeImportSpec PackageName string }{ Imports: imports, - PackageName: packageName, + PackageName: ctx.PackageName, } err := t.ExecuteTemplate(w, "imports.tmpl", context) if err != nil { @@ -463,25 +497,108 @@ func GenerateImports(t *template.Template, imports []string, packageName string) return buf.String(), nil } +func getDecorators(decorators map[string]Decorator, s Schema) map[string]Decorator { + if len(s.Decorators) > 0 { + for k, v := range s.Decorators { + decorators[k] = v + } + } + if s.AdditionalPropertiesType != nil { + m := getDecorators(decorators, *s.AdditionalPropertiesType) + for k, v := range m { + decorators[k] = v + } + } + for _, p := range s.Properties { + m := getDecorators(decorators, p.Schema) + for k, v := range m { + decorators[k] = v + } + } + for _, p := range s.AdditionalTypes { + m := getDecorators(decorators, p.Schema) + for k, v := range m { + decorators[k] = v + } + } + return decorators +} + // 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) { +func GenerateAdditionalPropertyBoilerplate(ctx *genCtx, t *template.Template, td []TypeDefinition) (string, error) { var buf bytes.Buffer w := bufio.NewWriter(&buf) var filteredTypes []TypeDefinition - for _, t := range typeDefs { + decorators := make(map[string]Decorator) + for _, t := range td { if t.Schema.HasAdditionalProperties { filteredTypes = append(filteredTypes, t) } + // If the type is an empty interface, can assume it's decorators are held by parent that references it + if t.Schema.GoType != "interface{}" { + decorators = getDecorators(decorators, t.Schema) + } + } + + // filter out all decorators with a schema path that is deeper than SchemaName.property + // since the decode library always operates on an object of the current schema, iterating over its properties + for k, _ := range decorators { + if strings.Count(k, ".") > 1 { + delete(decorators, k) + } + } + + // todo: this has side effects that should be computed elsewhere + ctx.HasDecorators = ctx.HasDecorators || len(decorators) > 0 + + type factoryMap struct { + Discriminator string + Factories []Decorator + } + + dsm := map[string]Decorator{} + dsp := map[string]factoryMap{} + for _, v := range decorators { + dsm[v.SchemaName] = v + + fm := dsp[v.SchemaPath] + fm.Discriminator = v.Discriminator + fm.Factories = append(fm.Factories, v) + dsp[v.SchemaPath] = fm + + } + for _, v := range dsp { + sort.Slice(v.Factories, func(i, j int) bool { return v.Factories[i].JSONName < v.Factories[j].JSONName }) + } + + // issue a warning if dsm contains schemas that have duplicate JSONName (this will cause TypeFactory to have + // duplicate map entries and will therefore not compile. TypeFactory is intended to be removed. This is a temporary measure + // todo: remove once we no longer use type factory + djn := map[string]Decorator{} + for _, v := range dsm { + if d, ok := djn[v.JSONName]; ok { + fmt.Fprintf(os.Stderr, "Duplicate Discriminator JSON value `%s` (schema1: %s, schema2: %s). Code will not compile\n", v.JSONName, d.SchemaName, v.SchemaName) + } + djn[v.JSONName] = v } context := struct { - Types []TypeDefinition + Types []TypeDefinition + Decorators map[string]Decorator + DecoratedSchemas map[string]Decorator + DecoratedPaths map[string]factoryMap + HasDecorators bool }{ - Types: filteredTypes, + Types: filteredTypes, + Decorators: decorators, + DecoratedSchemas: dsm, + DecoratedPaths: dsp, + HasDecorators: ctx.HasDecorators, } + //debug.PrintStack() err := t.ExecuteTemplate(w, "additional-properties.tmpl", context) if err != nil { return "", errors.Wrap(err, "error generating additional properties code") diff --git a/pkg/codegen/codegen_test.go b/pkg/codegen/codegen_test.go index f534d9ec7..d2e3f8857 100644 --- a/pkg/codegen/codegen_test.go +++ b/pkg/codegen/codegen_test.go @@ -2,16 +2,28 @@ package codegen import ( "bytes" + "encoding/json" + "errors" + "flag" "go/format" "io/ioutil" + "net" "net/http" + "net/http/httptest" + "os" + "os/exec" + "path/filepath" + "strings" "testing" examplePetstoreClient "github.com/deepmap/oapi-codegen/examples/petstore-expanded" - examplePetstore "github.com/deepmap/oapi-codegen/examples/petstore-expanded/echo/api" + examplePetstore "github.com/weberr13/oapi-codegen/examples/petstore-expanded/echo/api" + "github.com/getkin/kin-openapi/openapi3" "github.com/golangci/lint-1" + "github.com/onsi/gomega/gexec" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestExamplePetStoreCodeGeneration(t *testing.T) { @@ -78,7 +90,6 @@ func TestExamplePetStoreParseFunction(t *testing.T) { assert.NotNil(t, findPetByIDResponse.JSON200.Tag) assert.Equal(t, "cat", *findPetByIDResponse.JSON200.Tag) } - func TestFilterOperationsByTag(t *testing.T) { packageName := "testswagger" t.Run("include tags", func(t *testing.T) { @@ -124,36 +135,163 @@ func TestFilterOperationsByTag(t *testing.T) { }) } -func TestExampleOpenAPICodeGeneration(t *testing.T) { +var update = flag.Bool("update", false, "update .golden files") + +//func TestExampleOpenAPICodeGeneration(t *testing.T) { +// +// testCases := map[string]struct { +// Spec string +// Name string +// }{ +// "standard test": { +// Spec: "testdata/testOpenAPIDefinition.yaml", +// Name: "testOpenAPIDefinition", +// }, +// "discriminated oneOf test with enums": { +// Spec: "testdata/testOpenAPIDefinitionWithOneOfDiscriminatorsAndEnums.yaml", +// Name: "testOpenAPIDefinitionWithOneOfDiscriminatorsAndEnums", +// }, +// "discriminated oneOf test with enums and mappings": { +// Spec: "testdata/pets.yaml", +// Name: "pets", +// }, +// } +// for testname, test := range testCases { +// t.Run(testname, func(t *testing.T) { +// // Input vars for code generation: +// packageName := "testswagger" +// opts := Options{ +// GenerateClient: true, +// GenerateServer: true, +// GenerateTypes: true, +// EmbedSpec: true, +// } +// // load spec from testdata identified by spec +// bytes, err := ioutil.ReadFile(test.Spec) +// if err != nil { +// t.Fatal(err) +// } +// // Get a spec from the test definition in this file: +// swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(bytes) +// assert.NoError(t, err) +// +// // Run our code generation: +// code, err := Generate(swagger, packageName, opts) +// codeBytes := []byte(code) +// assert.NoError(t, err) +// assert.NotEmpty(t, code) +// +// // Make sure the code is formattable +// _, err = format.Source([]byte(code)) +// assert.NoError(t, err) +// +// // Make sure the generated code is valid: +// linter := new(lint.Linter) +// problems, err := linter.Lint("test.gen.go", codeBytes) +// assert.NoError(t, err) +// assert.Len(t, problems, 0) +// +// // if update flag is set, write to golden file +// golden := filepath.Join("testdata/", test.Name+".golden") +// if *update { +// ioutil.WriteFile(golden, codeBytes, 0644) +// } +// +// // load the golden file and run formatting to ensure test does not fail due to different go format version +// expected, _ := ioutil.ReadFile(golden) +// expected, err = format.Source(expected) +// assert.NoError(t, err) +// +// // Compare generated code with golden file contents +// assert.Equal(t, codeBytes, expected) +// }) +// } +//} + +func TestOneOfCodeGenerationErrors(t *testing.T) { + + testCases := map[string]struct { + Spec string + ContentAsserts func(t *testing.T, code string, err error) + }{ + "failed oneOf - anonymous nested schema": { + Spec: "testdata/failedOneOfAnonymousSchema.yaml", + ContentAsserts: func(t *testing.T, code string, err error) { + assert.Empty(t, code) + // Check that we have valid (formattable) code: + // + // Cannot instance an interface + assert.NotNil(t, err, "expecting error") + assert.Contains(t, err.Error(), `'Cat.echoChamberOneOf.sound' defines a oneOf property inside an anonymous schema`) + }, + }, + "failed oneOf - missing discriminator": { + Spec: "testdata/failedOneOfMissingDiscriminator.yaml", + ContentAsserts: func(t *testing.T, code string, err error) { + assert.Empty(t, code) + + assert.NotNil(t, err, "expecting error") + assert.Contains(t, err.Error(), `error processing oneOf`) + assert.Contains(t, err.Error(), `Schema 'CatAlive' does not have discriminator property`) + }, + }, + } + for testname, test := range testCases { + t.Run(testname, func(t *testing.T) { + // Input vars for code generation: + packageName := "testswagger" + opts := Options{ + GenerateClient: true, + GenerateServer: true, + GenerateTypes: true, + EmbedSpec: true, + } + // load spec from testdata identified by spec + bytes, err := ioutil.ReadFile(test.Spec) + if err != nil { + t.Fatal(err) + } + // Get a spec from the test definition in this file: + swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(bytes) + assert.NoError(t, err) + + // Run our code generation: + code, err := Generate(swagger, packageName, opts) + assert.Error(t, err) + test.ContentAsserts(t, code, err) + }) + } +} + +func TestExampleOpenAPICodeGenerationOfDefaults(t *testing.T) { + testSpec := "testdata/pets.yaml" + _, code, err := loadSwaggerFromFileAndGenerateCode(t, testSpec, Options{GenerateTypes: true}) + assert.NoError(t, err) + + // ensure default values are stored as struct tags in generated structs + assert.Regexp(t, "Type.*\\*string.*`.*default:\"black\"`", code) + assert.Regexp(t, "Halls.*\\*int.*`.*default:\"7\"`", code) + assert.Regexp(t, "Towers.*\\*int.*`.*default:\"1\"`", code) + assert.NotRegexp(t, "Type.*\\*array.*`.*default:\".*\"`", code) +} +func loadSwaggerFromFileAndGenerateCode(t *testing.T, testSpec string, opts Options) (*openapi3.Swagger, string, error) { // Input vars for code generation: packageName := "testswagger" - opts := Options{ - GenerateClient: true, - GenerateEchoServer: true, - GenerateTypes: true, - EmbedSpec: true, - } // Get a spec from the test definition in this file: - swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData([]byte(testOpenAPIDefinition)) - assert.NoError(t, err) - + swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromFile(testSpec) + if err != nil { + return nil, "", err + } // Run our code generation: code, err := Generate(swagger, packageName, opts) - assert.NoError(t, err) - assert.NotEmpty(t, code) - - // Check that we have valid (formattable) code: - _, err = format.Source([]byte(code)) - assert.NoError(t, err) - - // Check that we have a package: - assert.Contains(t, code, "package testswagger") - - // Check that response structs are generated correctly: - assert.Contains(t, code, "type getTestByNameResponse struct {") - + if err != nil { + return nil, "", err + } + if code == "" { + return nil, "", errors.New("empty code generated") + } // Check that response structs contains fallbacks to interface for invalid types: // Here an invalid array with no items. assert.Contains(t, code, ` @@ -178,147 +316,114 @@ type getTestByNameResponse struct { assert.Contains(t, code, "func (c *Client) GetTestByName(ctx context.Context, name string, params *GetTestByNameParams) (*http.Response, error) {") assert.Contains(t, code, "func (c *ClientWithResponses) GetTestByNameWithResponse(ctx context.Context, name string, params *GetTestByNameParams) (*getTestByNameResponse, error) {") + // Make sure the code is formattable + _, err = format.Source([]byte(code)) + if err != nil { + return nil, "", err + } // Make sure the generated code is valid: linter := new(lint.Linter) problems, err := linter.Lint("test.gen.go", []byte(code)) - assert.NoError(t, err) - assert.Len(t, problems, 0) + if err != nil { + return nil, "", err + } + if len(problems) > 0 { + return nil, "", errors.New("linting problems found") + } + return swagger, code, nil +} + +func createTestServer(handler http.Handler) *httptest.Server { + ts := httptest.NewUnstartedServer(handler) + l, _ := net.Listen("tcp", "localhost:23456") + ts.Listener.Close() + ts.Listener = l + return ts } -const testOpenAPIDefinition = ` -openapi: 3.0.1 - -info: - title: OpenAPI-CodeGen Test - description: 'This is a test OpenAPI Spec' - version: 1.0.0 - -servers: -- url: https://test.oapi-codegen.com/v2 -- url: http://test.oapi-codegen.com/v2 - -paths: - /test/{name}: - get: - tags: - - test - summary: Get test - operationId: getTestByName - parameters: - - name: name - in: path - required: true - schema: - type: string - - name: $top - in: query - required: false - schema: - type: integer - responses: - 200: - description: Success - content: - application/xml: - schema: - type: array - items: - $ref: '#/components/schemas/Test' - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/Test' - 422: - description: InvalidArray - content: - application/xml: - schema: - type: array - application/json: - schema: - type: array - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /cat: - get: - tags: - - cat - summary: Get cat status - operationId: getCatStatus - responses: - 200: - description: Success - content: - application/json: - schema: - oneOf: - - $ref: '#/components/schemas/CatAlive' - - $ref: '#/components/schemas/CatDead' - application/xml: - schema: - anyOf: - - $ref: '#/components/schemas/CatAlive' - - $ref: '#/components/schemas/CatDead' - application/yaml: - schema: - allOf: - - $ref: '#/components/schemas/CatAlive' - - $ref: '#/components/schemas/CatDead' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - -components: - schemas: - - Test: - properties: - name: - type: string - cases: - type: array - items: - $ref: '#/components/schemas/TestCase' - - TestCase: - properties: - name: - type: string - command: - type: string - - Error: - properties: - code: - type: integer - format: int32 - message: - type: string - - CatAlive: - properties: - name: - type: string - alive_since: - type: string - format: date-time - - CatDead: - properties: - name: - type: string - dead_since: - type: string - format: date-time - cause: - type: string - enum: [car, dog, oldage] -` +func startTestServer(system http.FileSystem) func() { + fs := http.FileServer(system) + ts := createTestServer(fs) + ts.Start() + return ts.Close +} + +// TestResolvedSchema tests that a schema containing remote references is resolved correctly. +// To do so, it starts an HTTP server serving files; the schema under test here contains a reference +// to a file located at the server we just started. This requires that the host address be known here +// at the test site, but also be coded in the spec itself (see testResolvingSpec.yaml) +// Additionally, in order to ensure that the test is generating the proper spec, the generated code is compiled +// and executed and the resulting document is then compared with a golden file (which was inspected manually) +func TestResolvedSchema(t *testing.T) { + + cs := startTestServer(http.Dir("testdata")) + defer cs() + + const mainStr = "\nfunc main(){ s, _ := GetSwaggerSpec(); fmt.Println(s)}" + const testDir = "./testdata" + const packageName = "main" + testSpec := "testResolvingSpec.yaml" + testSpecPath := filepath.Join(testDir, testSpec) + + // TODO: these tests duplicate code that is in main() - we should refactor main at some point + opts := Options{ + EmbedSpec: true, + } + // load spec from testdata identified by spec + specBytes, err := ioutil.ReadFile(testSpecPath) + require.NoError(t, err) + + // Get a spec from the test definition in this file: + swagger, err := openapi3.NewSwaggerLoader( + openapi3.WithAllowExternalRefs(true), + openapi3.WithClearResolvedRefs(true)).LoadSwaggerFromData(specBytes) + require.NoError(t, err) + + // Run our code generation: + code, err := Generate(swagger, packageName, opts) + require.NoError(t, err) + require.NotEmpty(t, code) + + // append our main driver so that we can get the swagger string and dump it to stdout, and save the `program` + code += mainStr + tmpDir, err := ioutil.TempDir(testDir, "resolve") + require.NoError(t, err) + + // defer clean up test dir/file + defer os.RemoveAll(tmpDir) + + testFile := filepath.Join(tmpDir, testSpec+".go") + err = ioutil.WriteFile(testFile, []byte(code), 0644) + require.NoError(t, err) + + // user gomega to build a temporary executable representing the spec + testPath, _ := filepath.Abs(testFile) + testPath = filepath.Dir(testPath) + testBin, err := gexec.Build(testFile) + require.NoError(t, err) + defer gexec.CleanupBuildArtifacts() + + // run the executable + stdOut := &bytes.Buffer{} + stdErr := &bytes.Buffer{} + command := exec.Command(testBin) + command.Stdout = stdOut + command.Stderr = stdErr + require.NoError(t, command.Start()) + require.NoError(t, command.Wait()) + + ib := &bytes.Buffer{} + require.NoError(t, json.Indent(ib, stdOut.Bytes(), "", " ")) + + golden := strings.TrimSuffix(testSpecPath, ".yaml") + ".json.golden" + if *update { + ioutil.WriteFile(golden, ib.Bytes(), 0644) + } + + // load the golden file and run formatting to ensure test does not fail due to different go format version + expected, _ := ioutil.ReadFile(golden) + + // Compare generated code with golden file contents + require.Equal(t, ib.Bytes(), expected) + +} diff --git a/pkg/codegen/inline.go b/pkg/codegen/inline.go index 76251c9a9..3715e1952 100644 --- a/pkg/codegen/inline.go +++ b/pkg/codegen/inline.go @@ -26,7 +26,7 @@ import ( // 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) { +func GenerateInlinedSpec(ctx *genCtx, t *template.Template, swagger *openapi3.Swagger) (string, error) { // Marshal to json encoded, err := swagger.MarshalJSON() if err != nil { diff --git a/pkg/codegen/operations.go b/pkg/codegen/operations.go index 916643dd3..35bcefdee 100644 --- a/pkg/codegen/operations.go +++ b/pkg/codegen/operations.go @@ -141,12 +141,12 @@ func (p ParameterDefinitions) FindByName(name string) *ParameterDefinition { // 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) { +func DescribeParameters(ctx *genCtx, 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)) + goType, err := paramToGoType(ctx, param, append(path, param.Name)) if err != nil { return nil, fmt.Errorf("error generating type for param (%s): %s", param.Name, err) @@ -164,7 +164,7 @@ func DescribeParameters(params openapi3.Parameters, path []string) ([]ParameterD // name as the type. $ref: "#/components/schemas/custom_type" becomes // "CustomType". if paramOrRef.Ref != "" { - goType, err := RefPathToGoType(paramOrRef.Ref) + goType, err := RefPathToGoType(paramOrRef.Ref, ctx.ImportedTypes) if err != nil { return nil, fmt.Errorf("error dereferencing (%s) for param (%s): %s", paramOrRef.Ref, param.Name, err) @@ -204,10 +204,11 @@ type OperationDefinition struct { 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} + 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} + ImportedTypes map[string]TypeImportSpec // map of typename to go path for import Spec *openapi3.Operation } @@ -258,7 +259,7 @@ func (o *OperationDefinition) SummaryAsComment() string { // 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) { +func (o *OperationDefinition) GetResponseTypeDefinitions(ctx *genCtx) ([]TypeDefinition, error) { var tds []TypeDefinition responses := o.Spec.Responses @@ -273,7 +274,7 @@ func (o *OperationDefinition) GetResponseTypeDefinitions() ([]TypeDefinition, er 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}) + responseSchema, err := GenerateGoSchema(ctx, 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)) } @@ -298,7 +299,7 @@ func (o *OperationDefinition) GetResponseTypeDefinitions() ([]TypeDefinition, er ResponseName: responseName, } if contentType.Schema.Ref != "" { - refType, err := RefPathToGoType(contentType.Schema.Ref) + refType, err := RefPathToGoType(contentType.Schema.Ref, o.ImportedTypes) if err != nil { return nil, errors.Wrap(err, "error dereferencing response Ref") } @@ -368,16 +369,15 @@ func FilterParameterDefinitionByType(params []ParameterDefinition, in string) [] } // OperationDefinitions returns all operations for a swagger definition. -func OperationDefinitions(swagger *openapi3.Swagger) ([]OperationDefinition, error) { - var operations []OperationDefinition +func OperationDefinitions(ctx *genCtx, swagger *openapi3.Swagger) error { 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) + globalParams, err := DescribeParameters(ctx, pathItem.Parameters, nil) if err != nil { - return nil, fmt.Errorf("error describing global parameters for %s: %s", + return fmt.Errorf("error describing global parameters for %s: %s", requestPath, err) } @@ -386,22 +386,20 @@ func OperationDefinitions(swagger *openapi3.Swagger) ([]OperationDefinition, err 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) + opID := op.OperationID + if opID == "" { + // construct a default operationID + opID = opName + " " + requestPath + opID = ReplacePathParamsWithParNStr(opID) + opID = strings.ReplaceAll(opID, "/", " ") } + opID = ToCamelCase(opID) // These are parameters defined for the specific path method that // we're iterating over. - localParams, err := DescribeParameters(op.Parameters, []string{op.OperationID + "Params"}) + localParams, err := DescribeParameters(ctx, op.Parameters, []string{opID + "Params"}) if err != nil { - return nil, fmt.Errorf("error describing global parameters for %s/%s: %s", + return 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 @@ -414,12 +412,12 @@ func OperationDefinitions(swagger *openapi3.Swagger) ([]OperationDefinition, err pathParams := FilterParameterDefinitionByType(allParams, "path") pathParams, err = SortParamsByPath(requestPath, pathParams) if err != nil { - return nil, err + return err } - bodyDefinitions, typeDefinitions, err := GenerateBodyDefinitions(op.OperationID, op.RequestBody) + bodyDefinitions, typeDefinitions, err := GenerateBodyDefinitions(ctx, opID, op.RequestBody) if err != nil { - return nil, errors.Wrap(err, "error generating body definitions") + return errors.Wrap(err, "error generating body definitions") } opDef := OperationDefinition{ @@ -427,7 +425,7 @@ func OperationDefinitions(swagger *openapi3.Swagger) ([]OperationDefinition, err HeaderParams: FilterParameterDefinitionByType(allParams, "header"), QueryParams: FilterParameterDefinitionByType(allParams, "query"), CookieParams: FilterParameterDefinitionByType(allParams, "cookie"), - OperationId: ToCamelCase(op.OperationID), + OperationId: opID, // Replace newlines in summary. Summary: op.Summary, Method: opName, @@ -435,6 +433,7 @@ func OperationDefinitions(swagger *openapi3.Swagger) ([]OperationDefinition, err Spec: op, Bodies: bodyDefinitions, TypeDefinitions: typeDefinitions, + ImportedTypes: ctx.ImportedTypes, } // check for overrides of SecurityDefinitions. @@ -458,10 +457,10 @@ func OperationDefinitions(swagger *openapi3.Swagger) ([]OperationDefinition, err // Generate all the type definitions needed for this operation opDef.TypeDefinitions = append(opDef.TypeDefinitions, GenerateTypeDefsForOperation(opDef)...) - operations = append(operations, opDef) + ctx.OpDefs = append(ctx.OpDefs, opDef) } } - return operations, nil + return nil } func generateDefaultOperationID(opName string, requestPath string) (string, error) { @@ -486,7 +485,7 @@ func generateDefaultOperationID(opName string, requestPath string) (string, erro // 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) { +func GenerateBodyDefinitions(ctx *genCtx, operationID string, bodyOrRef *openapi3.RequestBodyRef) ([]RequestBodyDefinition, []TypeDefinition, error) { if bodyOrRef == nil { return nil, nil, nil } @@ -508,7 +507,7 @@ func GenerateBodyDefinitions(operationID string, bodyOrRef *openapi3.RequestBody } bodyTypeName := operationID + tag + "Body" - bodySchema, err := GenerateGoSchema(content.Schema, []string{bodyTypeName}) + bodySchema, err := GenerateGoSchema(ctx, content.Schema, []string{bodyTypeName}) if err != nil { return nil, nil, errors.Wrap(err, "error generating request body definition") } @@ -516,7 +515,7 @@ func GenerateBodyDefinitions(operationID string, bodyOrRef *openapi3.RequestBody // If the body is a pre-defined type if bodyOrRef.Ref != "" { // Convert the reference path to Go type - refType, err := RefPathToGoType(bodyOrRef.Ref) + refType, err := RefPathToGoType(bodyOrRef.Ref, ctx.ImportedTypes) if err != nil { return nil, nil, errors.Wrap(err, fmt.Sprintf("error turning reference (%s) into a Go type", bodyOrRef.Ref)) } @@ -607,27 +606,22 @@ func GenerateParamsTypes(op OperationDefinition) []TypeDefinition { } // Generates code for all types produced -func GenerateTypesForOperations(t *template.Template, ops []OperationDefinition) (string, error) { +func GenerateTypesForOperations(ctx *genCtx, t *template.Template) (string, error) { var buf bytes.Buffer w := bufio.NewWriter(&buf) - err := t.ExecuteTemplate(w, "param-types.tmpl", ops) + err := t.ExecuteTemplate(w, "param-types.tmpl", ctx) if err != nil { return "", errors.Wrap(err, "error generating types for params objects") } - err = t.ExecuteTemplate(w, "request-bodies.tmpl", ops) + err = t.ExecuteTemplate(w, "request-bodies.tmpl", ctx) 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) + addProps, err := GenerateAdditionalPropertyBoilerplate(ctx, t, ctx.getAllOpTypes()) if err != nil { return "", errors.Wrap(err, "error generating additional properties boilerplate for operations") } @@ -681,18 +675,19 @@ func GenerateChiServer(t *template.Template, operations []OperationDefinition) ( // 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) +func GenerateEchoServer(ctx *genCtx, t *template.Template, operations []OperationDefinition) (string, error) { + si, err := GenerateServerInterface(ctx, t, operations) + if err != nil { return "", fmt.Errorf("Error generating server types and interface: %s", err) } - wrappers, err := GenerateWrappers(t, operations) + wrappers, err := GenerateWrappers(ctx, t) if err != nil { return "", fmt.Errorf("Error generating handler wrappers: %s", err) } - register, err := GenerateRegistration(t, operations) + register, err := GenerateRegistration(ctx, t) if err != nil { return "", fmt.Errorf("Error generating handler registration: %s", err) } @@ -700,11 +695,11 @@ func GenerateEchoServer(t *template.Template, operations []OperationDefinition) } // Uses the template engine to generate the server interface -func GenerateServerInterface(t *template.Template, ops []OperationDefinition) (string, error) { +func GenerateServerInterface(ctx *genCtx, t *template.Template, operations []OperationDefinition) (string, error) { var buf bytes.Buffer w := bufio.NewWriter(&buf) - err := t.ExecuteTemplate(w, "server-interface.tmpl", ops) + err := t.ExecuteTemplate(w, "server-interface.tmpl", ctx) if err != nil { return "", fmt.Errorf("error generating server interface: %s", err) @@ -719,11 +714,11 @@ func GenerateServerInterface(t *template.Template, ops []OperationDefinition) (s // 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) { +func GenerateWrappers(ctx *genCtx, t *template.Template) (string, error) { var buf bytes.Buffer w := bufio.NewWriter(&buf) - err := t.ExecuteTemplate(w, "wrappers.tmpl", ops) + err := t.ExecuteTemplate(w, "wrappers.tmpl", ctx) if err != nil { return "", fmt.Errorf("error generating server interface: %s", err) @@ -737,11 +732,11 @@ func GenerateWrappers(t *template.Template, ops []OperationDefinition) (string, // 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) { +func GenerateRegistration(ctx *genCtx, t *template.Template) (string, error) { var buf bytes.Buffer w := bufio.NewWriter(&buf) - err := t.ExecuteTemplate(w, "register.tmpl", ops) + err := t.ExecuteTemplate(w, "register.tmpl", ctx) if err != nil { return "", fmt.Errorf("error generating route registration: %s", err) @@ -755,11 +750,11 @@ func GenerateRegistration(t *template.Template, ops []OperationDefinition) (stri // 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) { +func GenerateClient(ctx *genCtx, t *template.Template) (string, error) { var buf bytes.Buffer w := bufio.NewWriter(&buf) - err := t.ExecuteTemplate(w, "client.tmpl", ops) + err := t.ExecuteTemplate(w, "client.tmpl", ctx) if err != nil { return "", fmt.Errorf("error generating client bindings: %s", err) @@ -773,11 +768,11 @@ func GenerateClient(t *template.Template, ops []OperationDefinition) (string, er // This generates a client which extends the basic client which does response // unmarshaling. -func GenerateClientWithResponses(t *template.Template, ops []OperationDefinition) (string, error) { +func GenerateClientWithResponses(ctx *genCtx, t *template.Template) (string, error) { var buf bytes.Buffer w := bufio.NewWriter(&buf) - err := t.ExecuteTemplate(w, "client-with-responses.tmpl", ops) + err := t.ExecuteTemplate(w, "client-with-responses.tmpl", ctx) if err != nil { return "", fmt.Errorf("error generating client bindings: %s", err) diff --git a/pkg/codegen/operations_test.go b/pkg/codegen/operations_test.go index 0636f299a..538b06fb9 100644 --- a/pkg/codegen/operations_test.go +++ b/pkg/codegen/operations_test.go @@ -20,45 +20,45 @@ import ( func TestGenerateDefaultOperationID(t *testing.T) { type test struct { - op string - path string - want string + op string + path string + want string wantErr bool } - suite := []test { + suite := []test{ { - op: http.MethodGet, - path: "/v1/foo/bar", - want: "GetV1FooBar", + op: http.MethodGet, + path: "/v1/foo/bar", + want: "GetV1FooBar", wantErr: false, }, { - op: http.MethodGet, - path: "/v1/foo/bar/", - want: "GetV1FooBar", + op: http.MethodGet, + path: "/v1/foo/bar/", + want: "GetV1FooBar", wantErr: false, }, { - op: http.MethodPost, - path: "/v1", - want: "PostV1", + op: http.MethodPost, + path: "/v1", + want: "PostV1", wantErr: false, }, { - op: http.MethodPost, - path: "v1", - want: "PostV1", + op: http.MethodPost, + path: "v1", + want: "PostV1", wantErr: false, }, { - path: "v1", - want: "", + path: "v1", + want: "", wantErr: true, }, { - path: "", - want: "PostV1", + path: "", + want: "PostV1", wantErr: true, }, } @@ -71,11 +71,11 @@ func TestGenerateDefaultOperationID(t *testing.T) { } } - if test.wantErr { + if test.wantErr { return } if got != test.want { t.Fatalf("Operation ID generation error. Want [%v] Got [%v]", test.want, got) } } -} \ No newline at end of file +} diff --git a/pkg/codegen/schema.go b/pkg/codegen/schema.go index 36a1ac277..8544e49f6 100644 --- a/pkg/codegen/schema.go +++ b/pkg/codegen/schema.go @@ -5,13 +5,33 @@ import ( "strings" "github.com/getkin/kin-openapi/openapi3" + "github.com/iancoleman/strcase" "github.com/pkg/errors" ) +// Decorator functions for some of the generated schema types +type Decorator struct { + SchemaPath string + SchemaName string + JSONName string + Discriminator string + DiscriminatorPascal string + Required bool +} + +// TypeImportSpec describes a type, defined by an external OpenAPI schema and its associated golang import related bits. +// This is used when generating code for types in the current schema that refer to the imported types +type TypeImportSpec struct { + Name string + PackageName string + ImportPath string +} + // 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 + GoType string // The Go type needed to represent the schema + RefType string // If the type has a type name, this is set + Default *string // Default value, if specified in the spec. Only applies to base data types Properties []Property // For an object, the fields with names HasAdditionalProperties bool // Whether we support additional properties @@ -19,6 +39,13 @@ type Schema struct { 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 + + Decorators map[string]Decorator +} + +// Create a new TypeImportSpec for the provided type, package and import +func NewTypeImportSpec(n, p, i string) TypeImportSpec { + return TypeImportSpec{Name: n, PackageName: p, ImportPath: i} } func (s Schema) IsRef() bool { @@ -82,10 +109,78 @@ 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 +func generateSchemaDecorators(path []string, srefs []*openapi3.SchemaRef, discriminator *openapi3.Discriminator, + importedTypes map[string]TypeImportSpec) (map[string]Decorator, error) { + rm := map[string]string{} + m := make(map[string]Decorator) + oneOfPath := append(path[:0], path...) + + // Special case where the schema directly contains oneOf instead of properties + if len(oneOfPath) == 1 { + oneOfPath = append(oneOfPath, discriminator.PropertyName) + } + + // reverse mapping so that the refs are the keys + if discriminator.Mapping != nil { + for k, v := range discriminator.Mapping { + rm[v] = k + } + } + + for _, v := range srefs { + required := false + name, err := RefPathToGoType(v.Ref, importedTypes) + if err != nil { + continue + } + + // by default the key is the schema name. This is also the default for external schemas + jname := strcase.ToCamel(name) + + if v.Value.Properties != nil { + // by if the discriminator is specified and is enum, override default + discriminatorDef, ok := v.Value.Properties[discriminator.PropertyName] + if !ok { + return nil, fmt.Errorf("Schema '%s' does not have discriminator property '%s'", name, discriminator.PropertyName) + } + if discriminatorDef.Value.Type == "string" { + if len(discriminatorDef.Value.Enum) > 0 { + jname = discriminatorDef.Value.Enum[0].(string) + } + } + + // if the discriminator is denoted as a required property, mark that + for _, r := range v.Value.Required { + if r == discriminator.PropertyName { + required = true + } + } + } + + // if we have explicit mapping, use that + if mapping, ok := rm[v.Ref]; ok { + jname = mapping + } + + // add a decorator for this schema instance + //decPath := append(path[:0], path...) + //decPath = append(decPath, name) + dsp := DotSeparatedPath(oneOfPath) + dk := fmt.Sprintf("%s(%s=%s)", dsp, discriminator.PropertyName, jname) + m[dk] = Decorator{ + SchemaPath: dsp, + SchemaName: name, + JSONName: jname, + Discriminator: discriminator.PropertyName, + DiscriminatorPascal: strcase.ToCamel(discriminator.PropertyName), + Required: required, + } + } + + return m, nil +} + +func GenerateGoSchema(ctx *genCtx, sref *openapi3.SchemaRef, path []string) (Schema, error) { // Add a fallback value in case the sref is nil. // i.e. the parent schema defines a type:array, but the array has @@ -96,25 +191,51 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { schema := sref.Value + var refType string + + //If Ref is set on the SchemaRef, it means that this type is actually a reference to + // another type. if sref.Ref != "" { - var err error - // Convert the reference path to Go type - refType, err = RefPathToGoType(sref.Ref) + refType, err := RefPathToGoType(sref.Ref, ctx.ImportedTypes) if err != nil { - return Schema{}, fmt.Errorf("error turning reference (%s) into a Go type: %s", - sref.Ref, err) + return Schema{}, fmt.Errorf("error turning reference (%s) into a Go type: %s", sref.Ref, err) } - return Schema{ - GoType: refType, - }, nil + + // If the type being referenced to is a oneOf, we stil want the decorators and GoType to be set + if schema != nil && schema.OneOf != nil { + if schema.Discriminator != nil && schema.Discriminator.PropertyName != "" { + decorators, err := generateSchemaDecorators(path, schema.OneOf, schema.Discriminator, ctx.ImportedTypes) + if err != nil { + return Schema{}, errors.Wrap(err, "error processing oneOf") + } + return Schema{GoType: refType, RefType: refType, SkipOptionalPointer: true, Decorators: decorators}, nil + } + return Schema{GoType: refType, RefType: refType}, nil + } + //We're not de-referencing, so simply use the referenced type. + 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 + + // When a discriminator is found there is a way to support this if schema.OneOf != nil { + if schema.Discriminator != nil && schema.Discriminator.PropertyName != "" { + // we only support oneOf properties of a named schema. This requires refType to be defined + // and path to include the schema name and attribute names only + if refType == "" && len(path) > 2 { + return Schema{}, fmt.Errorf("oneOf only supported for named schemas, '%s' defines a oneOf property inside an anonymous schema", DotSeparatedPath(path)) + } + decorators, err := generateSchemaDecorators(path, schema.OneOf, schema.Discriminator, ctx.ImportedTypes) + if err != nil { + return Schema{}, errors.Wrap(err, "error processing oneOf") + } + + return Schema{GoType: "interface{}", RefType: refType, SkipOptionalPointer: true, Decorators: decorators}, nil + } return Schema{GoType: "interface{}", RefType: refType}, nil } @@ -123,7 +244,7 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { // 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) + mergedSchema, err := MergeSchemas(ctx, schema.AllOf, path, ctx.ImportedTypes) if err != nil { return Schema{}, errors.Wrap(err, "error merging schemas") } @@ -159,7 +280,7 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { for _, pName := range SortedSchemaKeys(schema.Properties) { p := schema.Properties[pName] propertyPath := append(path, pName) - pSchema, err := GenerateGoSchema(p, propertyPath) + pSchema, err := GenerateGoSchema(ctx, p, propertyPath) if err != nil { return Schema{}, errors.Wrap(err, fmt.Sprintf("error generating Go schema for property '%s'", pName)) } @@ -200,7 +321,7 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { GoType: "interface{}", } if schema.AdditionalProperties != nil { - additionalSchema, err := GenerateGoSchema(schema.AdditionalProperties, path) + additionalSchema, err := GenerateGoSchema(ctx, schema.AdditionalProperties, path) if err != nil { return Schema{}, errors.Wrap(err, "error generating type for additional properties") } @@ -212,16 +333,18 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { return outSchema, nil } else { f := schema.Format + defaultOK := true 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) + arrayType, err := GenerateGoSchema(ctx, schema.Items, path) if err != nil { return Schema{}, errors.Wrap(err, "error generating type for array") } outSchema.GoType = "[]" + arrayType.TypeDecl() + defaultOK = false case "integer": // We default to int if format doesn't ask for something else. if f == "int64" { @@ -266,6 +389,10 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { default: return Schema{}, fmt.Errorf("unhandled Schema type: %s", t) } + if defaultOK && schema.Default != nil { + dv := fmt.Sprintf("%v", schema.Default) + outSchema.Default = &dv + } } return outSchema, nil } @@ -303,6 +430,13 @@ func GenFieldsFromProperties(props []Property) []string { } else { field += fmt.Sprintf(" `json:\"%s,omitempty\"`", p.JsonFieldName) } + + // set default value if present + if p.Schema.Default != nil { + field += fmt.Sprintf(" default:\"%s\"", *p.Schema.Default) + } + + field += "`" fields = append(fields, field) } return fields @@ -328,7 +462,7 @@ func GenStructFromSchema(schema Schema) string { } // Merge all the fields in the schemas supplied into one giant schema. -func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) { +func MergeSchemas(ctx *genCtx, allOf []*openapi3.SchemaRef, path []string, importedTypes map[string]TypeImportSpec) (Schema, error) { var outSchema Schema for _, schemaOrRef := range allOf { ref := schemaOrRef.Ref @@ -336,13 +470,13 @@ func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) { var refType string var err error if ref != "" { - refType, err = RefPathToGoType(ref) + refType, err = RefPathToGoType(ref, importedTypes) if err != nil { return Schema{}, errors.Wrap(err, "error converting reference path to a go type") } } - schema, err := GenerateGoSchema(schemaOrRef, path) + schema, err := GenerateGoSchema(ctx, schemaOrRef, path) if err != nil { return Schema{}, errors.Wrap(err, "error generating Go schema in allOf") } @@ -373,7 +507,7 @@ func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) { // Now, we generate the struct which merges together all the fields. var err error - outSchema.GoType, err = GenStructFromAllOf(allOf, path) + outSchema.GoType, err = GenStructFromAllOf(ctx, allOf, path) if err != nil { return Schema{}, errors.Wrap(err, "unable to generate aggregate type for AllOf") } @@ -383,7 +517,7 @@ func MergeSchemas(allOf []*openapi3.SchemaRef, path []string) (Schema, error) { // 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) { +func GenStructFromAllOf(ctx *genCtx, allOf []*openapi3.SchemaRef, path []string) (string, error) { // Start out with struct { objectParts := []string{"struct {"} for _, schemaOrRef := range allOf { @@ -395,7 +529,7 @@ func GenStructFromAllOf(allOf []*openapi3.SchemaRef, path []string) (string, err // InlinedMember // ... // } - goType, err := RefPathToGoType(ref) + goType, err := RefPathToGoType(ref, ctx.ImportedTypes) if err != nil { return "", err } @@ -406,7 +540,7 @@ func GenStructFromAllOf(allOf []*openapi3.SchemaRef, path []string) (string, err } 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) + goSchema, err := GenerateGoSchema(ctx, schemaOrRef, path) if err != nil { return "", err } @@ -421,14 +555,14 @@ func GenStructFromAllOf(allOf []*openapi3.SchemaRef, path []string) (string, err // 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) { +func paramToGoType(ctx *genCtx, 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) + return GenerateGoSchema(ctx, param.Schema, path) } // At this point, we have a content type. We know how to deal with @@ -450,5 +584,5 @@ func paramToGoType(param *openapi3.Parameter, path []string) (Schema, error) { } // For json, we go through the standard schema mechanism - return GenerateGoSchema(mt.Schema, path) + return GenerateGoSchema(ctx, mt.Schema, path) } diff --git a/pkg/codegen/template_helpers.go b/pkg/codegen/template_helpers.go index 2afb7bdf0..eb1711ac3 100644 --- a/pkg/codegen/template_helpers.go +++ b/pkg/codegen/template_helpers.go @@ -101,6 +101,8 @@ func genResponsePayload(operationID string) string { func genResponseUnmarshal(op *OperationDefinition) string { var buffer = bytes.NewBufferString("") var caseClauses = make(map[string]string) + operationID := op.OperationID + responses := op.Responses // Get the type definitions from the operation: typeDefinitions, err := op.GetResponseTypeDefinitions() @@ -109,7 +111,6 @@ func genResponseUnmarshal(op *OperationDefinition) string { } // Add a case for each possible response: - responses := op.Spec.Responses for _, typeDefinition := range typeDefinitions { responseRef, ok := responses[typeDefinition.ResponseName] @@ -139,21 +140,68 @@ func genResponseUnmarshal(op *OperationDefinition) string { // 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 { + contentType, ok := responseRef.Value.Content[contentTypeName] + if !ok { + continue + } + + // But we can only do this if we actually have a schema (otherwise there will be no struct to unmarshal into): + if contentType.Schema == nil { + fmt.Fprintf(os.Stderr, "Response %s.%s has nil schema\n", operationID, responseName) + continue + } + + // Make sure that we actually have a go-type for this response: + goType, err := GenerateGoSchema(ctx, contentType.Schema, []string{contentTypeName}) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to determine Go type for %s.%s: %v\n", operationID, contentTypeName, err) + continue + } // We get "interface{}" when using "anyOf" or "oneOf" (which doesn't work with Go types): - if typeDefinition.TypeName == "interface{}" { + if goType.TypeDecl() == "interface{}" && !goType.SkipOptionalPointer { // Unable to unmarshal this, so we leave it out: continue } + // decodeable types unmarshal differently + if goType.TypeDecl() == "interface{}" { + // Need to define the type in a ref in order to decode.Unmarshal + attributeName := fmt.Sprintf("JSON%s", ToCamelCase(responseName)) + + var decorator *Decorator + for _, v := range goType.Decorators { + if v.Discriminator != "" { + decorator = &v + } + } + if decorator != nil { + caseAction := fmt.Sprintf("res, err := decode.UnmarshalJSONInto(bodyBytes, &%s{}, SchemaPathFactory) \n if err != nil { \n return nil, err \n} \n response.%s = &res", decorator.SchemaName, attributeName) + if responseName == "default" { + caseClause := fmt.Sprintf("case strings.Contains(rsp.Header.Get(\"%s\"), \"json\"):", echo.HeaderContentType) + leastSpecific[caseClause] = caseAction + } else { + caseClause := fmt.Sprintf("case strings.Contains(rsp.Header.Get(\"%s\"), \"json\") && rsp.StatusCode == %s:", echo.HeaderContentType, responseName) + mostSpecific[caseClause] = caseAction + } + } + continue + } + // Add content-types here (json / yaml / xml etc): switch { // JSON: case StringInArray(contentTypeName, contentTypesJSON): - var caseAction string - if typeDefinition.Schema.TypeDecl() == "interface{}" { - caseAction = fmt.Sprintf("var temp interface{}\nresponse.%s = &temp \n if err := json.Unmarshal(bodyBytes, response.%s); err != nil { \n return nil, err \n}", typeDefinition.TypeName, typeDefinition.TypeName) + attributeName := fmt.Sprintf("JSON%s", ToCamelCase(responseName)) + fmtStr := "response.%s = &%s{} \n if err := json.Unmarshal(bodyBytes, response.%s); err != nil { \n return nil, err \n}" + if ctx.HasDecorators { + fmtStr = "response.%s = &%s{} \nif _, err := decode.UnmarshalJSONInto(bodyBytes, response.%s, SchemaPathFactory); err != nil { \n return nil, err \n}" + } + caseAction := fmt.Sprintf(fmtStr, attributeName, goType.TypeDecl(), attributeName) + if responseName == "default" { + caseClause := fmt.Sprintf("case strings.Contains(rsp.Header.Get(\"%s\"), \"json\"):", echo.HeaderContentType) + leastSpecific[caseClause] = caseAction } else { caseAction = fmt.Sprintf("response.%s = &%s{} \n if err := json.Unmarshal(bodyBytes, response.%s); err != nil { \n return nil, err \n}", typeDefinition.TypeName, typeDefinition.Schema.TypeDecl(), typeDefinition.TypeName) } @@ -223,8 +271,8 @@ func genResponseTypeName(operationID string) string { return fmt.Sprintf("%s%s", LowercaseFirstCharacter(operationID), responseTypeSuffix) } -func getResponseTypeDefinitions(op *OperationDefinition) []TypeDefinition { - td, err := op.GetResponseTypeDefinitions() +func getResponseTypeDefinitions(ctx *genCtx, op *OperationDefinition) []TypeDefinition { + td, err := op.GetResponseTypeDefinitions(ctx) if err != nil { panic(err) } @@ -261,4 +309,6 @@ var TemplateFunctions = template.FuncMap{ "lower": strings.ToLower, "title": strings.Title, "stripNewLines": stripNewLines, + "split": strings.Split, + "dottedStringToTypeName": DottedStringToTypeName, } diff --git a/pkg/codegen/templates/additional-properties.tmpl b/pkg/codegen/templates/additional-properties.tmpl index 0430d9135..70e1b1367 100644 --- a/pkg/codegen/templates/additional-properties.tmpl +++ b/pkg/codegen/templates/additional-properties.tmpl @@ -1,3 +1,73 @@ +{{if .HasDecorators}} +func factory(fm map[string]func() interface{}, path, dk string, o map[string]interface{}) (interface{}, error) { + var dp interface{} + var dv string + var ok bool + + if dp, ok = o[dk]; !ok { + return nil, fmt.Errorf( "expecting OneOf object at path '%s' to to have a discriminator property '%s'", path, dk ) + } + + if dv, ok = dp.(string); !ok { + return nil, fmt.Errorf("expecting OneOf field '%s's' discriminator property '%s' value to be a string", path, dk) + } + + f, ok := fm[dv] + if !ok { + return nil, fmt.Errorf("Unknown discriminator value '%s' when handling OneOf field '%s'", path, dv) + } + return f(), nil +} + +{{range $key, $value := .DecoratedPaths}} +// Factory method for objects at path {{$key}} +func {{dottedStringToTypeName $key}}_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{} { {{range $v2 := $value.Factories}} + "{{ $v2.JSONName }}": New{{ $v2.SchemaName }}, + {{- end }} + } + return factory(fm, "{{$key}}", "{{$value.Discriminator}}", o) +} +{{end}} + + +func SchemaPathFactory(path string) (func(map[string]interface{}) (interface{}, error), error) { + // Map StringPath => Factory + pathFactoryMap := map[string]func(map[string]interface{}) (interface{}, error) { {{range $key, $value := .DecoratedPaths}} + "{{$key}}": {{dottedStringToTypeName $key}}_Factory, + {{- end}} + } + + return pathFactoryMap[path], nil +} + + +func TypeFactory(kind string) (interface{}, error) { + // Map StringPath => Factory + var factoryMap = map[string]func() interface{} { {{range $key, $value := .DecoratedSchemas}} + "{{$value.JSONName}}": New{{ $value.SchemaName }}, + {{- end}} + } + f, ok := factoryMap[kind] + if !ok { + return nil, fmt.Errorf("cannot find type %s", kind) + } + return f(), nil +} + +{{range $key, $value := .DecoratedSchemas}} +func New{{ $key }}() interface{} { + _d := "{{- $value.JSONName -}}"; return &{{ $key }} { {{ $value.DiscriminatorPascal }}: {{if ne true $value.Required }} &{{end}}_d } +} + +func (r {{ $key }}) Discriminator() string { + return "{{ $value.Discriminator }}" +} + +{{end -}} +{{end}} + + {{range .Types}}{{$addType := .Schema.AdditionalPropertiesType.TypeDecl}} // Getter for additional properties for {{.TypeName}}. Returns the specified diff --git a/pkg/codegen/templates/client-with-responses.tmpl b/pkg/codegen/templates/client-with-responses.tmpl index e71f4be4e..4d785e9a8 100644 --- a/pkg/codegen/templates/client-with-responses.tmpl +++ b/pkg/codegen/templates/client-with-responses.tmpl @@ -10,7 +10,12 @@ func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithRes if err != nil { return nil, err } - return &ClientWithResponses{client}, nil + return &ClientWithResponses{ + ClientInterface: &Client{ + Client: client, + Server: server, + }, + }, nil } // WithBaseURL overrides the baseURL. @@ -29,10 +34,26 @@ func WithBaseURL(baseURL string) ClientOption { } {{range .}}{{$opid := .OperationId}}{{$op := .}} +// NewClientWithResponsesAndRequestEditorFunc takes in a RequestEditorFn callback function and returns a ClientWithResponses with a default Client: +func NewClientWithResponsesAndRequestEditorFunc(server string, reqEditorFn RequestEditorFn) *ClientWithResponses { + return &ClientWithResponses{ + ClientInterface: &Client{ + Client: &http.Client{}, + Server: server, + RequestEditor: reqEditorFn, + }, + } +} + +func (c *ClientWithResponses) UpdateHttpClient(cli HTTPClientInterface) { + c.ClientInterface.(*Client).Client = cli +} + +{{range .OpDefs}}{{$opid := .OperationId}}{{$op := .}} type {{$opid | lcFirst}}Response struct { Body []byte HTTPResponse *http.Response - {{- range getResponseTypeDefinitions .}} + {{- range getResponseTypeDefinitions $ .}} {{.TypeName}} *{{.Schema.TypeDecl}} {{- end}} } @@ -55,7 +76,7 @@ func (r {{$opid | lcFirst}}Response) StatusCode() int { {{end}} -{{range .}} +{{range .OpDefs}} {{$opid := .OperationId -}} {{/* Generate client methods (with responses)*/}} @@ -84,7 +105,7 @@ func (c *ClientWithResponses) {{$opid}}{{.Suffix}}WithResponse(ctx context.Conte {{end}}{{/* operations */}} {{/* Generate parse functions for responses*/}} -{{range .}}{{$opid := .OperationId}} +{{range .OpDefs}}{{$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) { @@ -96,9 +117,9 @@ func Parse{{genResponseTypeName $opid | ucFirst}}(rsp *http.Response) (*{{genRes response := {{genResponsePayload $opid}} - {{genResponseUnmarshal .}} + {{genResponseUnmarshal $ $opid .Spec.Responses }} return response, nil } -{{end}}{{/* range . $opid := .OperationId */}} +{{end}}{{/* range .OpDefs $opid := .OperationId */}} diff --git a/pkg/codegen/templates/client.tmpl b/pkg/codegen/templates/client.tmpl index 19e0734db..f9b1d3bc7 100644 --- a/pkg/codegen/templates/client.tmpl +++ b/pkg/codegen/templates/client.tmpl @@ -1,11 +1,8 @@ // RequestEditorFn is the function signature for the RequestEditor callback function type RequestEditorFn func(req *http.Request, ctx context.Context) error -// Doer performs HTTP requests. -// -// The standard http.Client implements this interface. -type HttpRequestDoer interface { - Do(req *http.Request) (*http.Response, error) +type HTTPClientInterface interface { + Do(req *http.Request) (*http.Response, error) } // Client which conforms to the OpenAPI3 specification for this service. @@ -14,9 +11,8 @@ type Client struct { // 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 + // HTTP client with any customized settings, such as certificate chains. + Client HTTPClientInterface // A callback for modifying requests which are generated before sending over // the network. @@ -65,7 +61,7 @@ func WithRequestEditorFn(fn RequestEditorFn) ClientOption { // The interface specification for the client above. type ClientInterface interface { -{{range . -}} +{{range .OpDefs -}} {{$hasParams := .RequiresParamObject -}} {{$pathParams := .PathParams -}} {{$opid := .OperationId -}} @@ -74,12 +70,12 @@ type ClientInterface interface { {{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 */}} +{{end}}{{/* range .OpDefs $opid := .OperationId */}} } {{/* Generate client methods */}} -{{range . -}} +{{range .OpDefs -}} {{$hasParams := .RequiresParamObject -}} {{$pathParams := .PathParams -}} {{$opid := .OperationId -}} @@ -118,7 +114,7 @@ func (c *Client) {{$opid}}{{.Suffix}}(ctx context.Context{{genParamArgs $pathPar {{end}} {{/* Generate request builders */}} -{{range .}} +{{range .OpDefs}} {{$hasParams := .RequiresParamObject -}} {{$pathParams := .PathParams -}} {{$bodyRequired := .BodyRequired -}} @@ -154,7 +150,7 @@ func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamAr pathParam{{$paramIdx}} = string(pathParamBuf{{$paramIdx}}) {{end}} {{if .IsStyled}} - pathParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, "{{.ParamName}}", {{.GoVariableName}}) + pathParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, url.PathEscape, "{{.ParamName}}", {{.GoVariableName}}) if err != nil { return nil, err } @@ -184,7 +180,8 @@ func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamAr {{end}} {{if .IsStyled}} - if queryFrag, err := runtime.StyleParam("{{.Style}}", {{.Explode}}, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}); err != nil { + queryParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, url.QueryEscape, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}) + if err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -220,7 +217,10 @@ func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamAr headerParam{{$paramIdx}} = string(headerParamBuf{{$paramIdx}}) {{end}} {{if .IsStyled}} - headerParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}) + passthrough := func(s string) string { + return s + } + headerParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, passthrough, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}) if err != nil { return nil, err } @@ -244,7 +244,10 @@ func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamAr cookieParam{{$paramIdx}} = url.QueryEscape(string(cookieParamBuf{{$paramIdx}})) {{end}} {{if .IsStyled}} - cookieParam{{$paramIdx}}, err = runtime.StyleParam("simple", {{.Explode}}, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}) + passthrough := func(s string) string { + return s + } + cookieParam{{$paramIdx}}, err = runtime.StyleParam("simple", {{.Explode}}, passthrough, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}) if err != nil { return nil, err } diff --git a/pkg/codegen/templates/imports.tmpl b/pkg/codegen/templates/imports.tmpl index b5c5f1ed8..4da634468 100644 --- a/pkg/codegen/templates/imports.tmpl +++ b/pkg/codegen/templates/imports.tmpl @@ -1,10 +1,10 @@ // Package {{.PackageName}} provides primitives to interact the openapi HTTP API. // -// Code generated by github.com/deepmap/oapi-codegen DO NOT EDIT. +// Code generated by github.com/weberr13/oapi-codegen DO NOT EDIT. package {{.PackageName}} {{if .Imports}} import ( -{{range .Imports}} {{ . }} +{{range .Imports}} {{.PackageName}} "{{.ImportPath}}" {{end}}) {{end}} diff --git a/pkg/codegen/templates/inline.tmpl b/pkg/codegen/templates/inline.tmpl index 0ab3116ea..26c7a33fe 100644 --- a/pkg/codegen/templates/inline.tmpl +++ b/pkg/codegen/templates/inline.tmpl @@ -7,23 +7,34 @@ var swaggerSpec = []string{ // GetSwagger returns the Swagger specification corresponding to the generated code // in this file. func GetSwagger() (*openapi3.Swagger, error) { + + spec, err := GetSwaggerSpec() + if err != nil { + return nil, err + } + swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData([]byte(spec)) + if err != nil { + return nil, fmt.Errorf("error loading Swagger: %s", err) + } + return swagger, nil +} + + +// GetSwaggerSpec returns the Swagger specification as string corresponding to the generated code +// in this file. +func GetSwaggerSpec() (string, error) { zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) if err != nil { - return nil, fmt.Errorf("error base64 decoding spec: %s", err) + return "", 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) + return "", 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 "", fmt.Errorf("error decompressing spec: %s", err) } - return swagger, nil + return buf.String(), nil } diff --git a/pkg/codegen/templates/param-types.tmpl b/pkg/codegen/templates/param-types.tmpl index b35cce5d7..1089fd0b7 100644 --- a/pkg/codegen/templates/param-types.tmpl +++ b/pkg/codegen/templates/param-types.tmpl @@ -1,4 +1,4 @@ -{{range .}}{{$opid := .OperationId}} +{{range .OpDefs}}{{$opid := .OperationId}} {{range .TypeDefinitions}} // {{.TypeName}} defines parameters for {{$opid}}. type {{.TypeName}} {{.Schema.TypeDecl}} diff --git a/pkg/codegen/templates/register.tmpl b/pkg/codegen/templates/register.tmpl index 4198b23b3..2b4a86692 100644 --- a/pkg/codegen/templates/register.tmpl +++ b/pkg/codegen/templates/register.tmpl @@ -17,6 +17,6 @@ func RegisterHandlers(router interface { Handler: si, } {{end}} -{{range .}}router.{{.Method}}("{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}}) +{{range .OpDefs}}router.{{.Method}}("{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}}) {{end}} } diff --git a/pkg/codegen/templates/request-bodies.tmpl b/pkg/codegen/templates/request-bodies.tmpl index cec74bcb0..5db05b299 100644 --- a/pkg/codegen/templates/request-bodies.tmpl +++ b/pkg/codegen/templates/request-bodies.tmpl @@ -1,4 +1,4 @@ -{{range .}}{{$opid := .OperationId}} +{{range .OpDefs}}{{$opid := .OperationId}} {{range .Bodies}} // {{$opid}}RequestBody defines body for {{$opid}} for application/json ContentType. type {{$opid}}{{.NameTag}}RequestBody {{.TypeDef}} diff --git a/pkg/codegen/templates/templates.gen.go b/pkg/codegen/templates/templates.gen.go index d674c6d13..1aaa39f25 100644 --- a/pkg/codegen/templates/templates.gen.go +++ b/pkg/codegen/templates/templates.gen.go @@ -2,7 +2,77 @@ package templates import "text/template" -var templates = map[string]string{"additional-properties.tmpl": `{{range .Types}}{{$addType := .Schema.AdditionalPropertiesType.TypeDecl}} +var templates = map[string]string{"additional-properties.tmpl": `{{if .HasDecorators}} +func factory(fm map[string]func() interface{}, path, dk string, o map[string]interface{}) (interface{}, error) { + var dp interface{} + var dv string + var ok bool + + if dp, ok = o[dk]; !ok { + return nil, fmt.Errorf( "expecting OneOf object at path '%s' to to have a discriminator property '%s'", path, dk ) + } + + if dv, ok = dp.(string); !ok { + return nil, fmt.Errorf("expecting OneOf field '%s's' discriminator property '%s' value to be a string", path, dk) + } + + f, ok := fm[dv] + if !ok { + return nil, fmt.Errorf("Unknown discriminator value '%s' when handling OneOf field '%s'", path, dv) + } + return f(), nil +} + +{{range $key, $value := .DecoratedPaths}} +// Factory method for objects at path {{$key}} +func {{dottedStringToTypeName $key}}_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{} { {{range $v2 := $value.Factories}} + "{{ $v2.JSONName }}": New{{ $v2.SchemaName }}, + {{- end }} + } + return factory(fm, "{{$key}}", "{{$value.Discriminator}}", o) +} +{{end}} + + +func SchemaPathFactory(path string) (func(map[string]interface{}) (interface{}, error), error) { + // Map StringPath => Factory + pathFactoryMap := map[string]func(map[string]interface{}) (interface{}, error) { {{range $key, $value := .DecoratedPaths}} + "{{$key}}": {{dottedStringToTypeName $key}}_Factory, + {{- end}} + } + + return pathFactoryMap[path], nil +} + + +func TypeFactory(kind string) (interface{}, error) { + // Map StringPath => Factory + var factoryMap = map[string]func() interface{} { {{range $key, $value := .DecoratedSchemas}} + "{{$value.JSONName}}": New{{ $value.SchemaName }}, + {{- end}} + } + f, ok := factoryMap[kind] + if !ok { + return nil, fmt.Errorf("cannot find type %s", kind) + } + return f(), nil +} + +{{range $key, $value := .DecoratedSchemas}} +func New{{ $key }}() interface{} { + _d := "{{- $value.JSONName -}}"; return &{{ $key }} { {{ $value.DiscriminatorPascal }}: {{if ne true $value.Required }} &{{end}}_d } +} + +func (r {{ $key }}) Discriminator() string { + return "{{ $value.Discriminator }}" +} + +{{end -}} +{{end}} + + +{{range .Types}}{{$addType := .Schema.AdditionalPropertiesType.TypeDecl}} // Getter for additional properties for {{.TypeName}}. Returns the specified // element and whether it was found @@ -282,7 +352,12 @@ func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithRes if err != nil { return nil, err } - return &ClientWithResponses{client}, nil + return &ClientWithResponses{ + ClientInterface: &Client{ + Client: client, + Server: server, + }, + }, nil } // WithBaseURL overrides the baseURL. @@ -301,10 +376,26 @@ func WithBaseURL(baseURL string) ClientOption { } {{range .}}{{$opid := .OperationId}}{{$op := .}} +// NewClientWithResponsesAndRequestEditorFunc takes in a RequestEditorFn callback function and returns a ClientWithResponses with a default Client: +func NewClientWithResponsesAndRequestEditorFunc(server string, reqEditorFn RequestEditorFn) *ClientWithResponses { + return &ClientWithResponses{ + ClientInterface: &Client{ + Client: &http.Client{}, + Server: server, + RequestEditor: reqEditorFn, + }, + } +} + +func (c *ClientWithResponses) UpdateHttpClient(cli HTTPClientInterface) { + c.ClientInterface.(*Client).Client = cli +} + +{{range .OpDefs}}{{$opid := .OperationId}}{{$op := .}} type {{$opid | lcFirst}}Response struct { Body []byte HTTPResponse *http.Response - {{- range getResponseTypeDefinitions .}} + {{- range getResponseTypeDefinitions $ .}} {{.TypeName}} *{{.Schema.TypeDecl}} {{- end}} } @@ -327,7 +418,7 @@ func (r {{$opid | lcFirst}}Response) StatusCode() int { {{end}} -{{range .}} +{{range .OpDefs}} {{$opid := .OperationId -}} {{/* Generate client methods (with responses)*/}} @@ -356,7 +447,7 @@ func (c *ClientWithResponses) {{$opid}}{{.Suffix}}WithResponse(ctx context.Conte {{end}}{{/* operations */}} {{/* Generate parse functions for responses*/}} -{{range .}}{{$opid := .OperationId}} +{{range .OpDefs}}{{$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) { @@ -368,21 +459,18 @@ func Parse{{genResponseTypeName $opid | ucFirst}}(rsp *http.Response) (*{{genRes response := {{genResponsePayload $opid}} - {{genResponseUnmarshal .}} + {{genResponseUnmarshal $ $opid .Spec.Responses }} return response, nil } -{{end}}{{/* range . $opid := .OperationId */}} +{{end}}{{/* range .OpDefs $opid := .OperationId */}} `, "client.tmpl": `// RequestEditorFn is the function signature for the RequestEditor callback function type RequestEditorFn func(req *http.Request, ctx context.Context) error -// Doer performs HTTP requests. -// -// The standard http.Client implements this interface. -type HttpRequestDoer interface { - Do(req *http.Request) (*http.Response, error) +type HTTPClientInterface interface { + Do(req *http.Request) (*http.Response, error) } // Client which conforms to the OpenAPI3 specification for this service. @@ -391,9 +479,8 @@ type Client struct { // 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 + // HTTP client with any customized settings, such as certificate chains. + Client HTTPClientInterface // A callback for modifying requests which are generated before sending over // the network. @@ -442,7 +529,7 @@ func WithRequestEditorFn(fn RequestEditorFn) ClientOption { // The interface specification for the client above. type ClientInterface interface { -{{range . -}} +{{range .OpDefs -}} {{$hasParams := .RequiresParamObject -}} {{$pathParams := .PathParams -}} {{$opid := .OperationId -}} @@ -451,12 +538,12 @@ type ClientInterface interface { {{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 */}} +{{end}}{{/* range .OpDefs $opid := .OperationId */}} } {{/* Generate client methods */}} -{{range . -}} +{{range .OpDefs -}} {{$hasParams := .RequiresParamObject -}} {{$pathParams := .PathParams -}} {{$opid := .OperationId -}} @@ -495,7 +582,7 @@ func (c *Client) {{$opid}}{{.Suffix}}(ctx context.Context{{genParamArgs $pathPar {{end}} {{/* Generate request builders */}} -{{range .}} +{{range .OpDefs}} {{$hasParams := .RequiresParamObject -}} {{$pathParams := .PathParams -}} {{$bodyRequired := .BodyRequired -}} @@ -531,7 +618,7 @@ func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamAr pathParam{{$paramIdx}} = string(pathParamBuf{{$paramIdx}}) {{end}} {{if .IsStyled}} - pathParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, "{{.ParamName}}", {{.GoVariableName}}) + pathParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, url.PathEscape, "{{.ParamName}}", {{.GoVariableName}}) if err != nil { return nil, err } @@ -561,7 +648,8 @@ func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamAr {{end}} {{if .IsStyled}} - if queryFrag, err := runtime.StyleParam("{{.Style}}", {{.Explode}}, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}); err != nil { + queryParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, url.QueryEscape, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}) + if err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -597,7 +685,10 @@ func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamAr headerParam{{$paramIdx}} = string(headerParamBuf{{$paramIdx}}) {{end}} {{if .IsStyled}} - headerParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}) + passthrough := func(s string) string { + return s + } + headerParam{{$paramIdx}}, err = runtime.StyleParam("{{.Style}}", {{.Explode}}, passthrough, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}) if err != nil { return nil, err } @@ -621,7 +712,10 @@ func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamAr cookieParam{{$paramIdx}} = url.QueryEscape(string(cookieParamBuf{{$paramIdx}})) {{end}} {{if .IsStyled}} - cookieParam{{$paramIdx}}, err = runtime.StyleParam("simple", {{.Explode}}, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}) + passthrough := func(s string) string { + return s + } + cookieParam{{$paramIdx}}, err = runtime.StyleParam("simple", {{.Explode}}, passthrough, "{{.ParamName}}", {{if not .Required}}*{{end}}params.{{.GoName}}) if err != nil { return nil, err } @@ -641,12 +735,12 @@ func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamAr `, "imports.tmpl": `// Package {{.PackageName}} provides primitives to interact the openapi HTTP API. // -// Code generated by github.com/deepmap/oapi-codegen DO NOT EDIT. +// Code generated by github.com/weberr13/oapi-codegen DO NOT EDIT. package {{.PackageName}} {{if .Imports}} import ( -{{range .Imports}} {{ . }} +{{range .Imports}} {{.PackageName}} "{{.ImportPath}}" {{end}}) {{end}} `, @@ -659,28 +753,39 @@ var swaggerSpec = []string{ // GetSwagger returns the Swagger specification corresponding to the generated code // in this file. func GetSwagger() (*openapi3.Swagger, error) { + + spec, err := GetSwaggerSpec() + if err != nil { + return nil, err + } + swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData([]byte(spec)) + if err != nil { + return nil, fmt.Errorf("error loading Swagger: %s", err) + } + return swagger, nil +} + + +// GetSwaggerSpec returns the Swagger specification as string corresponding to the generated code +// in this file. +func GetSwaggerSpec() (string, error) { zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) if err != nil { - return nil, fmt.Errorf("error base64 decoding spec: %s", err) + return "", 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) + return "", 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) + return "", 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 + return buf.String(), nil } `, - "param-types.tmpl": `{{range .}}{{$opid := .OperationId}} + "param-types.tmpl": `{{range .OpDefs}}{{$opid := .OperationId}} {{range .TypeDefinitions}} // {{.TypeName}} defines parameters for {{$opid}}. type {{.TypeName}} {{.Schema.TypeDecl}} @@ -706,11 +811,11 @@ func RegisterHandlers(router interface { Handler: si, } {{end}} -{{range .}}router.{{.Method}}("{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}}) +{{range .OpDefs}}router.{{.Method}}("{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}}) {{end}} } `, - "request-bodies.tmpl": `{{range .}}{{$opid := .OperationId}} + "request-bodies.tmpl": `{{range .OpDefs}}{{$opid := .OperationId}} {{range .Bodies}} // {{$opid}}RequestBody defines body for {{$opid}} for application/json ContentType. type {{$opid}}{{.NameTag}}RequestBody {{.TypeDef}} @@ -725,7 +830,7 @@ type ServerInterface interface { {{end}} } `, - "typedef.tmpl": `{{range .Types}} + "typedef.tmpl": `{{range .TypeDefs}} // {{.TypeName}} defines model for {{.JsonName}}. type {{.TypeName}} {{.Schema.TypeDecl}} {{end}} @@ -735,7 +840,7 @@ type ServerInterfaceWrapper struct { Handler ServerInterface } -{{range .}}{{$opid := .OperationId}}// {{$opid}} converts echo context to params. +{{range .OpDefs}}{{$opid := .OperationId}}// {{$opid}} converts echo context to params. func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx echo.Context) error { var err error {{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" ------------- @@ -750,7 +855,7 @@ func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx echo.Context) error { } {{end}} {{if .IsStyled}} - err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", ctx.Param("{{.ParamName}}"), &{{$varName}}) + err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, url.PathUnescape, "{{.ParamName}}", ctx.Param("{{.ParamName}}"), &{{$varName}}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err)) } @@ -807,7 +912,10 @@ func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx echo.Context) error { } {{end}} {{if .IsStyled}} - err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", valueList[0], &{{.GoName}}) + passthrough := func(s string) (string, error) { + return s, nil + } + err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, passthrough, "{{.ParamName}}", valueList[0], &{{.GoName}}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err)) } @@ -839,7 +947,10 @@ func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx echo.Context) error { {{end}} {{if .IsStyled}} var value {{.TypeDef}} - err = runtime.BindStyledParameter("simple",{{.Explode}}, "{{.ParamName}}", cookie.Value, &value) + passthrough := func(s string) (string, error) { + return s, nil + } + err = runtime.BindStyledParameter("simple",{{.Explode}}, passthrough, "{{.ParamName}}", cookie.Value, &value) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err)) } diff --git a/pkg/codegen/templates/typedef.tmpl b/pkg/codegen/templates/typedef.tmpl index d93847ac1..60241f598 100644 --- a/pkg/codegen/templates/typedef.tmpl +++ b/pkg/codegen/templates/typedef.tmpl @@ -1,4 +1,4 @@ -{{range .Types}} +{{range .TypeDefs}} // {{.TypeName}} defines model for {{.JsonName}}. type {{.TypeName}} {{.Schema.TypeDecl}} {{end}} diff --git a/pkg/codegen/templates/wrappers.tmpl b/pkg/codegen/templates/wrappers.tmpl index d82ac0342..5f7fa70d8 100644 --- a/pkg/codegen/templates/wrappers.tmpl +++ b/pkg/codegen/templates/wrappers.tmpl @@ -3,7 +3,7 @@ type ServerInterfaceWrapper struct { Handler ServerInterface } -{{range .}}{{$opid := .OperationId}}// {{$opid}} converts echo context to params. +{{range .OpDefs}}{{$opid := .OperationId}}// {{$opid}} converts echo context to params. func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx echo.Context) error { var err error {{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" ------------- @@ -18,7 +18,7 @@ func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx echo.Context) error { } {{end}} {{if .IsStyled}} - err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", ctx.Param("{{.ParamName}}"), &{{$varName}}) + err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, url.PathUnescape, "{{.ParamName}}", ctx.Param("{{.ParamName}}"), &{{$varName}}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err)) } @@ -75,7 +75,10 @@ func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx echo.Context) error { } {{end}} {{if .IsStyled}} - err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, "{{.ParamName}}", valueList[0], &{{.GoName}}) + passthrough := func(s string) (string, error) { + return s, nil + } + err = runtime.BindStyledParameter("{{.Style}}",{{.Explode}}, passthrough, "{{.ParamName}}", valueList[0], &{{.GoName}}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err)) } @@ -107,7 +110,10 @@ func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx echo.Context) error { {{end}} {{if .IsStyled}} var value {{.TypeDef}} - err = runtime.BindStyledParameter("simple",{{.Explode}}, "{{.ParamName}}", cookie.Value, &value) + passthrough := func(s string) (string, error) { + return s, nil + } + err = runtime.BindStyledParameter("simple",{{.Explode}}, passthrough, "{{.ParamName}}", cookie.Value, &value) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter {{.ParamName}}: %s", err)) } diff --git a/pkg/codegen/testdata/failedOneOfAnonymousSchema.yaml b/pkg/codegen/testdata/failedOneOfAnonymousSchema.yaml new file mode 100644 index 000000000..d3f391336 --- /dev/null +++ b/pkg/codegen/testdata/failedOneOfAnonymousSchema.yaml @@ -0,0 +1,90 @@ +openapi: 3.0.1 +info: + title: failed + version: 1.0.0 +servers: [] +paths: {} +components: + schemas: + Cat: + type: object + properties: + type: + type: string + + # refer to schema that has a oneOf + sound: + oneOf: + - $ref: '#/components/schemas/Meow' + - $ref: '#/components/schemas/Growl' + discriminator: + propertyName: type + mapping: + LOUD: '#/components/schemas/Meow' + WARN: '#/components/schemas/Growl' + + # nested anonymous schemas with oneOf are unsupported + echoChamberOneOf: + type: object + properties: + type: + type: string + sound: + oneOf: + - $ref: '#/components/schemas/Meow' + - $ref: '#/components/schemas/Purr' + discriminator: + propertyName: type + + + GeneralSound: + type: object + properties: + type: + type: string + sound: + type: string + + GeneralOneOfSound: + type: object + properties: + type: + type: string + sound: + oneOf: + - $ref: '#/components/schemas/Meow' + - $ref: '#/components/schemas/Purr' + - $ref: '#/components/schemas/Growl' + discriminator: + propertyName: type + mapping: + LOUD: '#/components/schemas/Meow' + WARN: '#/components/schemas/Growl' + + Meow: + type: object + properties: + type: + type: string + enum: [MEOW] + squeel: + type: string + + Purr: + type: object + properties: + type: + type: string + enum: [PURR] + heritage: + type: string + + Growl: + type: object + properties: + type: + type: string + enum: [GROWL] + severity: + type: string + diff --git a/pkg/codegen/testdata/failedOneOfMissingDiscriminator.yaml b/pkg/codegen/testdata/failedOneOfMissingDiscriminator.yaml new file mode 100644 index 000000000..36ec1ee07 --- /dev/null +++ b/pkg/codegen/testdata/failedOneOfMissingDiscriminator.yaml @@ -0,0 +1,152 @@ +openapi: 3.0.1 + +info: + title: OpenAPI-CodeGen Test + description: 'This is a test OpenAPI Spec' + version: 1.0.0 + +servers: +- url: https://test.oapi-codegen.com/v2 +- url: http://test.oapi-codegen.com/v2 + +paths: + /test/{name}: + get: + tags: + - test + summary: Get test + operationId: getTestByName + parameters: + - name: name + in: path + required: true + schema: + type: string + responses: + 200: + description: Success + content: + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Test' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Test' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /cat: + put: + summary: deposit cats + operationId: putCats + requestBody: + description: list of feline creatures + required: true + content: + application-json: + schema: + $ref: '#/components/schemas/Cats' + + get: + tags: + - cat + summary: Get cat status + operationId: getCatStatus + responses: + 200: + description: Success + content: + application/json: + schema: + discriminator: + propertyName: "type" + oneOf: + - $ref: '#/components/schemas/CatAlive' + - $ref: '#/components/schemas/CatDead' + application/xml: + schema: + anyOf: + - $ref: '#/components/schemas/CatAlive' + - $ref: '#/components/schemas/CatDead' + application/yaml: + schema: + allOf: + - $ref: '#/components/schemas/CatAlive' + - $ref: '#/components/schemas/CatDead' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + + Test: + properties: + name: + type: string + cases: + type: array + items: + $ref: '#/components/schemas/TestCase' + + TestCase: + properties: + name: + type: string + command: + type: string + + Cats: + type: object + properties: + box: + $ref: '#/components/schemas/CatBox' + + CatBox: + type: object + discriminator: + propertyName: "type" + oneOf: + - $ref: '#/components/schemas/CatAlive' + - $ref: '#/components/schemas/CatDead' + + Error: + properties: + code: + type: integer + format: int32 + message: + type: string + + CatAlive: + properties: + name: + type: string + alive_since: + type: string + format: date-time + + CatDead: + properties: + type: + type: string + enum: + - cat_dead + name: + type: string + dead_since: + type: string + format: date-time + cause: + type: string + enum: [car, dog, oldage] diff --git a/pkg/codegen/testdata/included.yaml b/pkg/codegen/testdata/included.yaml new file mode 100644 index 000000000..6bb4fd2c0 --- /dev/null +++ b/pkg/codegen/testdata/included.yaml @@ -0,0 +1,19 @@ +openapi: 3.0.1 + +info: + title: OpenAPI-CodeGen Test + description: 'This is a test OpenAPI Spec' + version: 1.0.0 + +servers: +- url: http://test.oapi-codegen.com/v2 + +paths: {} + +components: + schemas: + Verifier: + properties: + name: + type: string + diff --git a/pkg/codegen/testdata/pets.golden b/pkg/codegen/testdata/pets.golden new file mode 100644 index 000000000..11d1a0571 --- /dev/null +++ b/pkg/codegen/testdata/pets.golden @@ -0,0 +1,784 @@ +// Package testswagger provides primitives to interact the openapi HTTP API. +// +// Code generated by github.com/weberr13/oapi-codegen DO NOT EDIT. +package testswagger + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/base64" + "fmt" + "github.com/deepmap/oapi-codegen/pkg/runtime" + "github.com/getkin/kin-openapi/openapi3" + "github.com/labstack/echo/v4" + "github.com/weberr13/go-decode/decode" + "io" + "io/ioutil" + "net/http" + "strings" +) + +// Accommodation defines model for Accommodation. +type Accommodation struct { + Class interface{} `json:"class,omitempty"` + Title *string `json:"title,omitempty"` +} + +// Bark defines model for Bark. +type Bark struct { + Type *string `json:"type,omitempty"` + Volume *int `json:"volume,omitempty"` +} + +// Cat defines model for Cat. +type Cat struct { + FavSound interface{} `json:"favSound,omitempty"` + Mood *string `json:"mood,omitempty"` + Sound interface{} `json:"sound,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Cheetah defines model for Cheetah. +type Cheetah struct { + Echo *SchemaWithSound `json:"echo,omitempty"` + EchoChamber *struct { + Sound *string `json:"sound,omitempty"` + Type *string `json:"type,omitempty"` + } `json:"echoChamber,omitempty"` + EchoOneOf *SchemaWithOneOfSound `json:"echoOneOf,omitempty"` + FavSound interface{} `json:"favSound,omitempty"` + Sound interface{} `json:"sound,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Dog defines model for Dog. +type Dog struct { + Kind *string `json:"kind,omitempty"` + Sound interface{} `json:"sound,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Error defines model for Error. +type Error struct { + Code *string `json:"code,omitempty"` + Message *string `json:"message,omitempty"` +} + +// Growl defines model for Growl. +type Growl struct { + Severity *string `json:"severity,omitempty"` + Type *string `json:"type,omitempty"` +} + +// House defines model for House. +type House struct { + Name *string `json:"name,omitempty"` + Rooms *int `json:"rooms,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Kennel defines model for Kennel. +type Kennel struct { + Name *string `json:"name,omitempty"` + Rooms *int `json:"rooms,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Meow defines model for Meow. +type Meow struct { + Squeel *string `json:"squeel,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Palace defines model for Palace. +type Palace struct { + Halls *int `json:"Halls,omitempty"` + Name *string `json:"name,omitempty"` + Towers *int `json:"towers,omitempty"` + Type *string `json:"type,omitempty"` +} + +// PetOwner defines model for PetOwner. +type PetOwner struct { + Age *int `json:"age,omitempty"` + Dogs *[]Dog `json:"dogs,omitempty"` + Favorite interface{} `json:"favorite,omitempty"` + LivesIn interface{} `json:"livesIn,omitempty"` + Name *string `json:"name,omitempty"` + Owns *[]Accommodation `json:"owns,omitempty"` + PetLivesIn *Accommodation `json:"petLivesIn,omitempty"` +} + +// PetOwnerStatus defines model for PetOwnerStatus. +type PetOwnerStatus interface{} + +// Purr defines model for Purr. +type Purr struct { + Heritage *Accommodation `json:"heritage,omitempty"` + Type *string `json:"type,omitempty"` +} + +// SchemaWithOneOfSound defines model for SchemaWithOneOfSound. +type SchemaWithOneOfSound struct { + Sound interface{} `json:"sound,omitempty"` + Type *string `json:"type,omitempty"` +} + +// SchemaWithSound defines model for SchemaWithSound. +type SchemaWithSound struct { + Sound *string `json:"sound,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Shack defines model for Shack. +type Shack struct { + Material *string `json:"material,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` +} + +func factory(fm map[string]func() interface{}, path, dk string, o map[string]interface{}) (interface{}, error) { + var dp interface{} + var dv string + var ok bool + + if dp, ok = o[dk]; !ok { + return nil, fmt.Errorf("expecting OneOf object at path '%s' to to have a discriminator property '%s'", path, dk) + } + + if dv, ok = dp.(string); !ok { + return nil, fmt.Errorf("expecting OneOf field '%s's' discriminator property '%s' value to be a string", path, dk) + } + + f, ok := fm[dv] + if !ok { + return nil, fmt.Errorf("Unknown discriminator value '%s' when handling OneOf field '%s'", path, dv) + } + return f(), nil +} + +// Factory method for objects at path Accommodation.class +func Accommodation_class_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{}{ + "BARK": NewKennel, + "House": NewHouse, + "Palace": NewPalace, + "Shack": NewShack, + } + return factory(fm, "Accommodation.class", "type", o) +} + +// Factory method for objects at path Cat.favSound +func Cat_favSound_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{}{ + "MEOW": NewMeow, + "PURR": NewPurr, + } + return factory(fm, "Cat.favSound", "type", o) +} + +// Factory method for objects at path Cat.sound +func Cat_sound_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{}{ + "LOUD": NewMeow, + "PURR": NewPurr, + "WARN": NewGrowl, + } + return factory(fm, "Cat.sound", "type", o) +} + +// Factory method for objects at path Cheetah.favSound +func Cheetah_favSound_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{}{ + "MEOW": NewMeow, + "PURR": NewPurr, + } + return factory(fm, "Cheetah.favSound", "type", o) +} + +// Factory method for objects at path Cheetah.sound +func Cheetah_sound_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{}{ + "LOUD": NewMeow, + "PURR": NewPurr, + "WARN": NewGrowl, + } + return factory(fm, "Cheetah.sound", "type", o) +} + +// Factory method for objects at path Dog.sound +func Dog_sound_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{}{ + "BARK": NewBark, + } + return factory(fm, "Dog.sound", "type", o) +} + +// Factory method for objects at path PetOwner.favorite +func PetOwner_favorite_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{}{ + "Cat": NewCat, + "Dog": NewDog, + } + return factory(fm, "PetOwner.favorite", "type", o) +} + +// Factory method for objects at path PetOwner.livesIn +func PetOwner_livesIn_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{}{ + "House": NewHouse, + "Palace": NewPalace, + } + return factory(fm, "PetOwner.livesIn", "type", o) +} + +// Factory method for objects at path SchemaWithOneOfSound.sound +func SchemaWithOneOfSound_sound_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{}{ + "LOUD": NewMeow, + "PURR": NewPurr, + "WARN": NewGrowl, + } + return factory(fm, "SchemaWithOneOfSound.sound", "type", o) +} + +func SchemaPathFactory(path string) (func(map[string]interface{}) (interface{}, error), error) { + // Map StringPath => Factory + pathFactoryMap := map[string]func(map[string]interface{}) (interface{}, error){ + "Accommodation.class": Accommodation_class_Factory, + "Cat.favSound": Cat_favSound_Factory, + "Cat.sound": Cat_sound_Factory, + "Cheetah.favSound": Cheetah_favSound_Factory, + "Cheetah.sound": Cheetah_sound_Factory, + "Dog.sound": Dog_sound_Factory, + "PetOwner.favorite": PetOwner_favorite_Factory, + "PetOwner.livesIn": PetOwner_livesIn_Factory, + "SchemaWithOneOfSound.sound": SchemaWithOneOfSound_sound_Factory, + } + + return pathFactoryMap[path], nil +} + +func TypeFactory(kind string) (interface{}, error) { + // Map StringPath => Factory + var factoryMap = map[string]func() interface{}{ + "BARK": NewBark, + "Cat": NewCat, + "Dog": NewDog, + "WARN": NewGrowl, + "House": NewHouse, + "BARK": NewKennel, + "MEOW": NewMeow, + "Palace": NewPalace, + "PURR": NewPurr, + "Shack": NewShack, + } + f, ok := factoryMap[kind] + if !ok { + return nil, fmt.Errorf("cannot find type %s", kind) + } + return f(), nil +} + +func NewBark() interface{} { + _d := "BARK" + return &Bark{Type: &_d} +} + +func (r Bark) Discriminator() string { + return "type" +} + +func NewCat() interface{} { + _d := "Cat" + return &Cat{Type: &_d} +} + +func (r Cat) Discriminator() string { + return "type" +} + +func NewDog() interface{} { + _d := "Dog" + return &Dog{Type: &_d} +} + +func (r Dog) Discriminator() string { + return "type" +} + +func NewGrowl() interface{} { + _d := "WARN" + return &Growl{Type: &_d} +} + +func (r Growl) Discriminator() string { + return "type" +} + +func NewHouse() interface{} { + _d := "House" + return &House{Type: &_d} +} + +func (r House) Discriminator() string { + return "type" +} + +func NewKennel() interface{} { + _d := "BARK" + return &Kennel{Type: &_d} +} + +func (r Kennel) Discriminator() string { + return "type" +} + +func NewMeow() interface{} { + _d := "MEOW" + return &Meow{Type: &_d} +} + +func (r Meow) Discriminator() string { + return "type" +} + +func NewPalace() interface{} { + _d := "Palace" + return &Palace{Type: &_d} +} + +func (r Palace) Discriminator() string { + return "type" +} + +func NewPurr() interface{} { + _d := "PURR" + return &Purr{Type: &_d} +} + +func (r Purr) Discriminator() string { + return "type" +} + +func NewShack() interface{} { + _d := "Shack" + return &Shack{Type: &_d} +} + +func (r Shack) Discriminator() string { + return "type" +} + +// RequestEditorFn is the function signature for the RequestEditor callback function +type RequestEditorFn func(req *http.Request, ctx context.Context) 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 + + // HTTP client with any customized settings, such as certificate chains. + Client http.Client + + // A callback for modifying requests which are generated before sending over + // the network. + RequestEditor RequestEditorFn +} + +// The interface specification for the client above. +type ClientInterface interface { + // PutOwner request with any body + PutOwnerWithBody(ctx context.Context, contentType string, body io.Reader) (*http.Response, error) + + // GetOwnerStatus request + GetOwnerStatus(ctx context.Context) (*http.Response, error) + + // TestOwnerStatus request + TestOwnerStatus(ctx context.Context) (*http.Response, error) +} + +func (c *Client) PutOwnerWithBody(ctx context.Context, contentType string, body io.Reader) (*http.Response, error) { + req, err := NewPutOwnerRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if c.RequestEditor != nil { + err = c.RequestEditor(req, ctx) + if err != nil { + return nil, err + } + } + return c.Client.Do(req) +} + +func (c *Client) GetOwnerStatus(ctx context.Context) (*http.Response, error) { + req, err := NewGetOwnerStatusRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if c.RequestEditor != nil { + err = c.RequestEditor(req, ctx) + if err != nil { + return nil, err + } + } + return c.Client.Do(req) +} + +func (c *Client) TestOwnerStatus(ctx context.Context) (*http.Response, error) { + req, err := NewTestOwnerStatusRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if c.RequestEditor != nil { + err = c.RequestEditor(req, ctx) + if err != nil { + return nil, err + } + } + return c.Client.Do(req) +} + +// NewPutOwnerRequestWithBody generates requests for PutOwner with any type of body +func NewPutOwnerRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + queryUrl := fmt.Sprintf("%s/owner", server) + + req, err := http.NewRequest("PUT", queryUrl, body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + return req, nil +} + +// NewGetOwnerStatusRequest generates requests for GetOwnerStatus +func NewGetOwnerStatusRequest(server string) (*http.Request, error) { + var err error + + queryUrl := fmt.Sprintf("%s/owner/pets", server) + + req, err := http.NewRequest("GET", queryUrl, nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewTestOwnerStatusRequest generates requests for TestOwnerStatus +func NewTestOwnerStatusRequest(server string) (*http.Request, error) { + var err error + + queryUrl := fmt.Sprintf("%s/owner/testStatus", server) + + req, err := http.NewRequest("GET", queryUrl, nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// ClientWithResponses builds on ClientInterface to offer response payloads +type ClientWithResponses struct { + ClientInterface +} + +// NewClientWithResponses returns a ClientWithResponses with a default Client: +func NewClientWithResponses(server string) *ClientWithResponses { + return &ClientWithResponses{ + ClientInterface: &Client{ + Client: http.Client{}, + Server: server, + }, + } +} + +// NewClientWithResponsesAndRequestEditorFunc takes in a RequestEditorFn callback function and returns a ClientWithResponses with a default Client: +func NewClientWithResponsesAndRequestEditorFunc(server string, reqEditorFn RequestEditorFn) *ClientWithResponses { + return &ClientWithResponses{ + ClientInterface: &Client{ + Client: http.Client{}, + Server: server, + RequestEditor: reqEditorFn, + }, + } +} + +type putOwnerResponse struct { + Body []byte + HTTPResponse *http.Response +} + +// Status returns HTTPResponse.Status +func (r putOwnerResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r putOwnerResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type getOwnerStatusResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *PetOwnerStatus + XML200 *interface{} + YAML200 *interface{} + JSONDefault *Error +} + +// Status returns HTTPResponse.Status +func (r getOwnerStatusResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r getOwnerStatusResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type testOwnerStatusResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *interface{} +} + +// Status returns HTTPResponse.Status +func (r testOwnerStatusResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r testOwnerStatusResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +// PutOwnerWithBodyWithResponse request with arbitrary body returning *PutOwnerResponse +func (c *ClientWithResponses) PutOwnerWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader) (*putOwnerResponse, error) { + rsp, err := c.PutOwnerWithBody(ctx, contentType, body) + if err != nil { + return nil, err + } + return ParseputOwnerResponse(rsp) +} + +// GetOwnerStatusWithResponse request returning *GetOwnerStatusResponse +func (c *ClientWithResponses) GetOwnerStatusWithResponse(ctx context.Context) (*getOwnerStatusResponse, error) { + rsp, err := c.GetOwnerStatus(ctx) + if err != nil { + return nil, err + } + return ParsegetOwnerStatusResponse(rsp) +} + +// TestOwnerStatusWithResponse request returning *TestOwnerStatusResponse +func (c *ClientWithResponses) TestOwnerStatusWithResponse(ctx context.Context) (*testOwnerStatusResponse, error) { + rsp, err := c.TestOwnerStatus(ctx) + if err != nil { + return nil, err + } + return ParsetestOwnerStatusResponse(rsp) +} + +// ParseputOwnerResponse parses an HTTP response from a PutOwnerWithResponse call +func ParseputOwnerResponse(rsp *http.Response) (*putOwnerResponse, error) { + bodyBytes, err := ioutil.ReadAll(rsp.Body) + defer rsp.Body.Close() + if err != nil { + return nil, err + } + + response := &putOwnerResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + } + + return response, nil +} + +// ParsegetOwnerStatusResponse parses an HTTP response from a GetOwnerStatusWithResponse call +func ParsegetOwnerStatusResponse(rsp *http.Response) (*getOwnerStatusResponse, error) { + bodyBytes, err := ioutil.ReadAll(rsp.Body) + defer rsp.Body.Close() + if err != nil { + return nil, err + } + + response := &getOwnerStatusResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + response.JSON200 = &PetOwnerStatus{} + if _, err := decode.UnmarshalJSONInto(bodyBytes, response.JSON200, SchemaPathFactory); err != nil { + return nil, err + } + case strings.Contains(rsp.Header.Get("Content-Type"), "json"): + response.JSONDefault = &Error{} + if _, err := decode.UnmarshalJSONInto(bodyBytes, response.JSONDefault, SchemaPathFactory); err != nil { + return nil, err + } + } + + return response, nil +} + +// ParsetestOwnerStatusResponse parses an HTTP response from a TestOwnerStatusWithResponse call +func ParsetestOwnerStatusResponse(rsp *http.Response) (*testOwnerStatusResponse, error) { + bodyBytes, err := ioutil.ReadAll(rsp.Body) + defer rsp.Body.Close() + if err != nil { + return nil, err + } + + response := &testOwnerStatusResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + res, err := decode.UnmarshalJSONInto(bodyBytes, &Dog{}, SchemaPathFactory) + if err != nil { + return nil, err + } + response.JSON200 = &res + } + + return response, nil +} + +// ServerInterface represents all server handlers. +type ServerInterface interface { + // create pet owners// (PUT /owner) + PutOwner(ctx echo.Context) error + // Get owner pets// (GET /owner/pets) + GetOwnerStatus(ctx echo.Context) error + // Test Owner Status as OneOf// (GET /owner/testStatus) + TestOwnerStatus(ctx echo.Context) error +} + +// ServerInterfaceWrapper converts echo contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface +} + +// PutOwner converts echo context to params. +func (w *ServerInterfaceWrapper) PutOwner(ctx echo.Context) error { + var err error + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.PutOwner(ctx) + return err +} + +// GetOwnerStatus converts echo context to params. +func (w *ServerInterfaceWrapper) GetOwnerStatus(ctx echo.Context) error { + var err error + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetOwnerStatus(ctx) + return err +} + +// TestOwnerStatus converts echo context to params. +func (w *ServerInterfaceWrapper) TestOwnerStatus(ctx echo.Context) error { + var err error + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.TestOwnerStatus(ctx) + return err +} + +// RegisterHandlers adds each server route to the EchoRouter. +func RegisterHandlers(router runtime.EchoRouter, si ServerInterface) { + + wrapper := ServerInterfaceWrapper{ + Handler: si, + } + + router.PUT("/owner", wrapper.PutOwner) + router.GET("/owner/pets", wrapper.GetOwnerStatus) + router.GET("/owner/testStatus", wrapper.TestOwnerStatus) + +} + +// Base64 encoded, gzipped, json marshaled Swagger object +var swaggerSpec = []string{ + + "H4sIAAAAAAAC/+xYW2/iOBT+K9HZfcwWuvuwUt7awrTVMAXBVNWo4sGTHIinsZ2xHViE+O8r2ymXxiRh", + "imb3YZ5Aycm5fOf22WuIBcsFR64VRGtQcYqM2L9XcSwYEwnRVHDzIJciR6kp2tdxRpT9k1AVS8ooJ1rI", + "PbnVA2EIEehVjrAJQXAcziB6XsPvEmcQwW+dne1OabgzIhmJjXy92CQl8Uuj1J0oVLOuj8g5ZrCZbkLQ", + "VGdogrBeR6C0pHwOG/PKPRFfv2GsTUDXRL5UcXFia0BeMIie4fpq/BGm4VuFISxEVrB9W5RrnKP0G7sh", + "umprRhYTUfDk/Gn4hGLZCNyokNLBxoRI9oO+GgyHHyCED+P7/kNv8AVCmNx98cKgjgbASJ4boWgNg+Fj", + "r9bVEJ6uxg/HRG6lWGbG2M/CpEGo9Ge6TXSrertJETVJq2WAcSrMb23D2N8nqlNXMZvQfnaTEvYVZVXn", + "Ni2VhJ3gsbEwdNi29c6Kb1383xT4ryptm/OemFer6YXyg/lw+3jf69uh0B/d9cc9COHz8NT58C6Y7PA+", + "Nba+lMLTK7FI0NsqDJUi87baHd7VTsQFSqpXtc24BXY8fBp4cPTZc9uxYo8T5o9GCsGUb1+dhGG5bc9q", + "tmHX+tywbVLF+nuBzrlGpD/1h08tbZWcpmLtjmSZo1A4I0WmIfo79ER5FBktligPFVyG78vOCPVwyX0L", + "4bCO97QnYm4FqEaXp7q2M9NhZ5dISVblnBeSajx/nxve1DTorFNmFGR0geqen9+LdkT0lftO65Iulrw9", + "3Icc3gN8jnqwC/oEVXXFM9FEF+o929JkrX5ZloX082rDrsxKV6RmNJet8QOJ2I2T0eN43HKceMnScQL3", + "i7G0xrMJyvdwYXdirehmRKOkJDuY4qCpZeUeOnR8GbR1xTyifGZPDOVx13SughAWKJU97MPlRfeia1OY", + "Iyc5hQj+uuheXEIIOdGpdb0jtpuisIdTE5ct8PsEIvPQrZIQJH4vUOlrkawcX+Iauf2E5HlGY/vRH9+U", + "u2dw2WzqqO2msgElaIo8d1cVkFGlAzELZphRjkEskehCoipdoRITiLQs0PDLgjEiVxCBFcMgRx3YyJRF", + "z0XZydFdkMzRE+r8cPAZKyoXXLkU/9ntHo+682NRl5aMg/vK/mHZoS7CV+cdhG8Mrshbi2cfvdX0Too4", + "RqUs+XhtmTPh6xi+x+bri/2CuX2tlCB3/aOJoULP4Bpjulc+GpXerUVvERmRM1bRf0ajavJ1gN5nVDqw", + "AQcu4oCowN0WeJA0n6JcWL77PN38GwAA//9ZRzp4uBQAAA==", +} + +// 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 +} diff --git a/pkg/codegen/testdata/pets.yaml b/pkg/codegen/testdata/pets.yaml new file mode 100644 index 000000000..7a2a0dc54 --- /dev/null +++ b/pkg/codegen/testdata/pets.yaml @@ -0,0 +1,343 @@ +openapi: 3.0.1 +info: + title: Pets + version: 1.0.0 +servers: [] +paths: + /owner: + put: + summary: create pet owners + operationId: putOwner + requestBody: + description: list of feline creatures + required: true + content: + application-json: + schema: + $ref: '#/components/schemas/PetOwner' + + + /owner/testStatus: + get: + tags: + - owner + summary: Test Owner Status as OneOf + operationId: testOwnerStatus + responses: + 200: + description: Success + content: + application/json: + schema: +# $ref: '#/components/schemas/PetOwnerStatus' + discriminator: + propertyName: "type" + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + + /owner/pets: + get: + tags: + - owner + summary: Get owner pets + operationId: getOwnerStatus + responses: + 200: + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/PetOwnerStatus' +# discriminator: +# propertyName: "type" +# oneOf: +# - $ref: '#/components/schemas/Cat' +# - $ref: '#/components/schemas/Dog' + application/xml: + schema: + anyOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + application/yaml: + schema: + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + PetOwnerStatus: + discriminator: + propertyName: "type" + mapping: + LOUD: '#/components/schemas/Cat' + WARN: '#/components/schemas/Dog' + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + + + PetOwner: + type: object + properties: + name: + type: string + age: + type: integer + default: 7 + favorite: + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + discriminator: + propertyName: type + + + dogs: + type: array + default: [] + items: + $ref: '#/components/schemas/Dog' + + livesIn: + oneOf: + - $ref: '#/components/schemas/House' + - $ref: '#/components/schemas/Palace' + discriminator: + propertyName: type + + petLivesIn: + $ref: '#/components/schemas/Accommodation' + + owns: + type: array + items: + $ref: '#/components/schemas/Accommodation' + + Cheetah: + type: object + properties: + type: + type: string + default: black + + # refer to schema that has a oneOf + sound: + oneOf: + - $ref: '#/components/schemas/Meow' + - $ref: '#/components/schemas/Purr' + - $ref: '#/components/schemas/Growl' + discriminator: + propertyName: type + mapping: + LOUD: '#/components/schemas/Meow' + WARN: '#/components/schemas/Growl' + + # refer to schema that has the same property name as the oneOf above + echo: + $ref: '#/components/schemas/SchemaWithSound' + + # refer to schema that is a oneOf and has the same property name as the oneOf above + echoOneOf: + $ref: '#/components/schemas/SchemaWithOneOfSound' + + echoChamber: + type: object + properties: + type: + type: string + sound: + type: string + + favSound: + oneOf: + - $ref: '#/components/schemas/Meow' + - $ref: '#/components/schemas/Purr' + discriminator: + propertyName: type + + SchemaWithSound: + type: object + properties: + type: + type: string + sound: + type: string + + SchemaWithOneOfSound: + type: object + properties: + type: + type: string + sound: + oneOf: + - $ref: '#/components/schemas/Meow' + - $ref: '#/components/schemas/Purr' + - $ref: '#/components/schemas/Growl' + discriminator: + propertyName: type + mapping: + LOUD: '#/components/schemas/Meow' + WARN: '#/components/schemas/Growl' + + + + Dog: + type: object + properties: + type: + type: string + + kind: + type: string + enum: [GUIDE,SHEPHERD,TOY] + + sound: + oneOf: + - $ref: '#/components/schemas/Bark' + discriminator: + propertyName: type + + Cat: + type: object + properties: + type: + type: string + + mood: + type: string + enum: [ALOOF, FRIENDLY, SHY] + + sound: + oneOf: + - $ref: '#/components/schemas/Meow' + - $ref: '#/components/schemas/Purr' + - $ref: '#/components/schemas/Growl' + discriminator: + propertyName: type + mapping: + LOUD: '#/components/schemas/Meow' + WARN: '#/components/schemas/Growl' + + favSound: + oneOf: + - $ref: '#/components/schemas/Meow' + - $ref: '#/components/schemas/Purr' + discriminator: + propertyName: type + + Bark: + type: object + properties: + type: + type: string + enum: [BARK] + volume: + type: integer + + Meow: + type: object + properties: + type: + type: string + enum: [MEOW] + squeel: + type: string + + Purr: + type: object + properties: + type: + type: string + enum: [PURR] + heritage: + $ref: '#/components/schemas/Accommodation' + + Growl: + type: object + properties: + type: + type: string + enum: [GROWL] + severity: + type: string + + Accommodation: + type: object + properties: + title: + type: string + class: + oneOf: + - $ref: '#/components/schemas/Palace' + - $ref: '#/components/schemas/Shack' + - $ref: '#/components/schemas/House' + - $ref: '#/components/schemas/Kennel' + discriminator: + propertyName: type + + + Kennel: + type: object + properties: + type: + type: string + enum: [BARK] + name: + type: string + rooms: + type: integer + + + House: + type: object + properties: + type: + type: string + name: + type: string + rooms: + type: integer + + + Shack: + type: object + properties: + type: + type: string + name: + type: string + material: + type: string + default: timber + + + Palace: + type: object + properties: + type: + type: string + name: + type: string + Halls: + type: integer + default: 7 + towers: + type: integer + default: 1 + + Error: + type: object + properties: + code: + type: string + message: + type: string + diff --git a/pkg/codegen/testdata/testOpenAPIDefinition.golden b/pkg/codegen/testdata/testOpenAPIDefinition.golden new file mode 100644 index 000000000..3c2fa1e4d --- /dev/null +++ b/pkg/codegen/testdata/testOpenAPIDefinition.golden @@ -0,0 +1,399 @@ +// Package testswagger provides primitives to interact the openapi HTTP API. +// +// Code generated by github.com/weberr13/oapi-codegen DO NOT EDIT. +package testswagger + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/base64" + "encoding/json" + "encoding/xml" + "fmt" + "github.com/deepmap/oapi-codegen/pkg/runtime" + "github.com/getkin/kin-openapi/openapi3" + "github.com/labstack/echo/v4" + "gopkg.in/yaml.v2" + "io/ioutil" + "net/http" + "strings" + "time" +) + +// CatAlive defines model for CatAlive. +type CatAlive struct { + AliveSince *time.Time `json:"alive_since,omitempty"` + Name *string `json:"name,omitempty"` +} + +// CatDead defines model for CatDead. +type CatDead struct { + Cause *string `json:"cause,omitempty"` + DeadSince *time.Time `json:"dead_since,omitempty"` + Name *string `json:"name,omitempty"` +} + +// Error defines model for Error. +type Error struct { + Code *int32 `json:"code,omitempty"` + Message *string `json:"message,omitempty"` +} + +// Test defines model for Test. +type Test struct { + Cases *[]TestCase `json:"cases,omitempty"` + Name *string `json:"name,omitempty"` +} + +// TestCase defines model for TestCase. +type TestCase struct { + Command *string `json:"command,omitempty"` + Name *string `json:"name,omitempty"` +} + +// RequestEditorFn is the function signature for the RequestEditor callback function +type RequestEditorFn func(req *http.Request, ctx context.Context) 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 + + // HTTP client with any customized settings, such as certificate chains. + Client http.Client + + // A callback for modifying requests which are generated before sending over + // the network. + RequestEditor RequestEditorFn +} + +// The interface specification for the client above. +type ClientInterface interface { + // GetCatStatus request + GetCatStatus(ctx context.Context) (*http.Response, error) + + // GetTestByName request + GetTestByName(ctx context.Context, name string) (*http.Response, error) +} + +func (c *Client) GetCatStatus(ctx context.Context) (*http.Response, error) { + req, err := NewGetCatStatusRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if c.RequestEditor != nil { + err = c.RequestEditor(req, ctx) + if err != nil { + return nil, err + } + } + return c.Client.Do(req) +} + +func (c *Client) GetTestByName(ctx context.Context, name string) (*http.Response, error) { + req, err := NewGetTestByNameRequest(c.Server, name) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if c.RequestEditor != nil { + err = c.RequestEditor(req, ctx) + if err != nil { + return nil, err + } + } + return c.Client.Do(req) +} + +// NewGetCatStatusRequest generates requests for GetCatStatus +func NewGetCatStatusRequest(server string) (*http.Request, error) { + var err error + + queryUrl := fmt.Sprintf("%s/cat", server) + + req, err := http.NewRequest("GET", queryUrl, nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewGetTestByNameRequest generates requests for GetTestByName +func NewGetTestByNameRequest(server string, name string) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParam("simple", false, "name", name) + if err != nil { + return nil, err + } + + queryUrl := fmt.Sprintf("%s/test/%s", server, pathParam0) + + req, err := http.NewRequest("GET", queryUrl, nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// ClientWithResponses builds on ClientInterface to offer response payloads +type ClientWithResponses struct { + ClientInterface +} + +// NewClientWithResponses returns a ClientWithResponses with a default Client: +func NewClientWithResponses(server string) *ClientWithResponses { + return &ClientWithResponses{ + ClientInterface: &Client{ + Client: http.Client{}, + Server: server, + }, + } +} + +// NewClientWithResponsesAndRequestEditorFunc takes in a RequestEditorFn callback function and returns a ClientWithResponses with a default Client: +func NewClientWithResponsesAndRequestEditorFunc(server string, reqEditorFn RequestEditorFn) *ClientWithResponses { + return &ClientWithResponses{ + ClientInterface: &Client{ + Client: http.Client{}, + Server: server, + RequestEditor: reqEditorFn, + }, + } +} + +type getCatStatusResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *interface{} + XML200 *interface{} + YAML200 *struct { + // Embedded struct due to allOf(#/components/schemas/CatAlive) + CatAlive + // Embedded struct due to allOf(#/components/schemas/CatDead) + CatDead + } + JSONDefault *Error +} + +// Status returns HTTPResponse.Status +func (r getCatStatusResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r getCatStatusResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type getTestByNameResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *[]Test + XML200 *[]Test + JSONDefault *Error +} + +// Status returns HTTPResponse.Status +func (r getTestByNameResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r getTestByNameResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +// GetCatStatusWithResponse request returning *GetCatStatusResponse +func (c *ClientWithResponses) GetCatStatusWithResponse(ctx context.Context) (*getCatStatusResponse, error) { + rsp, err := c.GetCatStatus(ctx) + if err != nil { + return nil, err + } + return ParsegetCatStatusResponse(rsp) +} + +// GetTestByNameWithResponse request returning *GetTestByNameResponse +func (c *ClientWithResponses) GetTestByNameWithResponse(ctx context.Context, name string) (*getTestByNameResponse, error) { + rsp, err := c.GetTestByName(ctx, name) + if err != nil { + return nil, err + } + return ParsegetTestByNameResponse(rsp) +} + +// ParsegetCatStatusResponse parses an HTTP response from a GetCatStatusWithResponse call +func ParsegetCatStatusResponse(rsp *http.Response) (*getCatStatusResponse, error) { + bodyBytes, err := ioutil.ReadAll(rsp.Body) + defer rsp.Body.Close() + if err != nil { + return nil, err + } + + response := &getCatStatusResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "yaml") && rsp.StatusCode == 200: + response.YAML200 = &struct { + // Embedded struct due to allOf(#/components/schemas/CatAlive) + CatAlive + // Embedded struct due to allOf(#/components/schemas/CatDead) + CatDead + }{} + if err := yaml.Unmarshal(bodyBytes, response.YAML200); err != nil { + return nil, err + } + case strings.Contains(rsp.Header.Get("Content-Type"), "json"): + response.JSONDefault = &Error{} + if err := json.Unmarshal(bodyBytes, response.JSONDefault); err != nil { + return nil, err + } + } + + return response, nil +} + +// ParsegetTestByNameResponse parses an HTTP response from a GetTestByNameWithResponse call +func ParsegetTestByNameResponse(rsp *http.Response) (*getTestByNameResponse, error) { + bodyBytes, err := ioutil.ReadAll(rsp.Body) + defer rsp.Body.Close() + if err != nil { + return nil, err + } + + response := &getTestByNameResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + response.JSON200 = &[]Test{} + if err := json.Unmarshal(bodyBytes, response.JSON200); err != nil { + return nil, err + } + case strings.Contains(rsp.Header.Get("Content-Type"), "xml") && rsp.StatusCode == 200: + response.XML200 = &[]Test{} + if err := xml.Unmarshal(bodyBytes, response.XML200); err != nil { + return nil, err + } + case strings.Contains(rsp.Header.Get("Content-Type"), "json"): + response.JSONDefault = &Error{} + if err := json.Unmarshal(bodyBytes, response.JSONDefault); err != nil { + return nil, err + } + } + + return response, nil +} + +// ServerInterface represents all server handlers. +type ServerInterface interface { + // Get cat status// (GET /cat) + GetCatStatus(ctx echo.Context) error + // Get test// (GET /test/{name}) + GetTestByName(ctx echo.Context, name string) error +} + +// ServerInterfaceWrapper converts echo contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface +} + +// GetCatStatus converts echo context to params. +func (w *ServerInterfaceWrapper) GetCatStatus(ctx echo.Context) error { + var err error + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetCatStatus(ctx) + return err +} + +// GetTestByName converts echo context to params. +func (w *ServerInterfaceWrapper) GetTestByName(ctx echo.Context) error { + var err error + // ------------- Path parameter "name" ------------- + var name string + + err = runtime.BindStyledParameter("simple", false, "name", ctx.Param("name"), &name) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter name: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetTestByName(ctx, name) + return err +} + +// RegisterHandlers adds each server route to the EchoRouter. +func RegisterHandlers(router runtime.EchoRouter, si ServerInterface) { + + wrapper := ServerInterfaceWrapper{ + Handler: si, + } + + router.GET("/cat", wrapper.GetCatStatus) + router.GET("/test/:name", wrapper.GetTestByName) + +} + +// Base64 encoded, gzipped, json marshaled Swagger object +var swaggerSpec = []string{ + + "H4sIAAAAAAAC/8xVyW7bMBD9FWHao2I5yY231C2CXJoCyS0wigE5llmISzkjo0agfy9I2VkFu0XaoifR", + "XN6b5b3xPejgYvDkhUHdA+s1OSzLBcpFZzeU1zGFSEkslRPM21/Zel0OVyE5FFBgUOhErCOoQbaRQAFL", + "sr6FoQaPrtx+cTAMdWb6SGheE2nsuTwi3ztQd6AxQQ0mtFBD6Ay2BMsJLkNo/mB8n1IKaSK6YJ7jWy/n", + "Z4/Y1gu1lDK4I+Yc7DT+LbFMJc/jwgq5snifaAUK3jWPPWt2DWsyxgKZMtuOAlPC7ZHUHp5NZOccejPx", + "7gBghrR+FfKhIdbJRrHBg4LbteXKcoWVEEt1HclffLmqbiLpXDErXUbabZ8sgqFL8lWpTA0bSjzCnM7m", + "s3kOIUTyGC0oOJ/NZ6dQQ0RZl8gbjaWcLZVPTgpzFFcGVN5coNwISs9QQyKOwe8KfTafj5l7IV/eYoyd", + "1eV1841zBHuLFGRP1ytQd4c78+CjoT56sdhgWOYyPqX+4brnzOi3/4Z5i6+ou+5vURfnPhXNTa81MY+W", + "XmHfyW/15xDv6OkJzv1BDdw7h2kLCi5JKo1S8V42gi2P80ig1KzJqm7uszGGQ9rLgv6w/YxlBkVM6Ego", + "camnzfRZxbB32PjJKv3e20QGlKSe6icpvnTg8o2S/uVZ83rOHNPsW6D/a2XIOKT2mig/RzUzpc2+u33q", + "QMFaJLJqilxmAaM9yf8iLfmZDq7ZnBW/PF49eHM5/AwAAP//A0Q9R74HAAA=", +} + +// 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 +} diff --git a/pkg/codegen/testdata/testOpenAPIDefinition.yaml b/pkg/codegen/testdata/testOpenAPIDefinition.yaml new file mode 100644 index 000000000..bf46cd37e --- /dev/null +++ b/pkg/codegen/testdata/testOpenAPIDefinition.yaml @@ -0,0 +1,122 @@ +openapi: 3.0.1 + +info: + title: OpenAPI-CodeGen Test + description: 'This is a test OpenAPI Spec' + version: 1.0.0 + +servers: +- url: https://test.oapi-codegen.com/v2 +- url: http://test.oapi-codegen.com/v2 + +paths: + /test/{name}: + get: + tags: + - test + summary: Get test + operationId: getTestByName + parameters: + - name: name + in: path + required: true + schema: + type: string + responses: + 200: + description: Success + content: + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Test' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Test' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /cat: + + get: + tags: + - cat + summary: Get cat status + operationId: getCatStatus + responses: + 200: + description: Success + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/CatAlive' + - $ref: '#/components/schemas/CatDead' + application/xml: + schema: + anyOf: + - $ref: '#/components/schemas/CatAlive' + - $ref: '#/components/schemas/CatDead' + application/yaml: + schema: + allOf: + - $ref: '#/components/schemas/CatAlive' + - $ref: '#/components/schemas/CatDead' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + + Test: + properties: + name: + type: string + cases: + type: array + items: + $ref: '#/components/schemas/TestCase' + + TestCase: + properties: + name: + type: string + command: + type: string + + Error: + properties: + code: + type: integer + format: int32 + message: + type: string + + CatAlive: + properties: + name: + type: string + alive_since: + type: string + format: date-time + + CatDead: + properties: + name: + type: string + dead_since: + type: string + format: date-time + cause: + type: string + enum: [car, dog, oldage] diff --git a/pkg/codegen/testdata/testOpenAPIDefinitionWithOneOfDiscriminatorsAndEnums.golden b/pkg/codegen/testdata/testOpenAPIDefinitionWithOneOfDiscriminatorsAndEnums.golden new file mode 100644 index 000000000..4e3f02d7c --- /dev/null +++ b/pkg/codegen/testdata/testOpenAPIDefinitionWithOneOfDiscriminatorsAndEnums.golden @@ -0,0 +1,627 @@ +// Package testswagger provides primitives to interact the openapi HTTP API. +// +// Code generated by github.com/weberr13/oapi-codegen DO NOT EDIT. +package testswagger + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/base64" + "encoding/xml" + "fmt" + "github.com/deepmap/oapi-codegen/pkg/runtime" + "github.com/getkin/kin-openapi/openapi3" + "github.com/labstack/echo/v4" + "github.com/weberr13/go-decode/decode" + "gopkg.in/yaml.v2" + "io" + "io/ioutil" + "net/http" + "strings" + "time" +) + +// CatAlive defines model for CatAlive. +type CatAlive struct { + AliveSince *time.Time `json:"alive_since,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` +} + +// CatBreed defines model for CatBreed. +type CatBreed interface{} + +// CatDead defines model for CatDead. +type CatDead struct { + Cause *string `json:"cause,omitempty"` + DeadSince *time.Time `json:"dead_since,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Cats defines model for Cats. +type Cats struct { + Box interface{} `json:"box,omitempty"` + Breed CatBreed `json:"breed,omitempty"` +} + +// Error defines model for Error. +type Error struct { + Code *int32 `json:"code,omitempty"` + Message *string `json:"message,omitempty"` +} + +// MixedBreed defines model for MixedBreed. +type MixedBreed struct { + FurColor *string `json:"furColor,omitempty"` + FurLength *string `json:"furLength,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Purebred defines model for Purebred. +type Purebred struct { + Breed *string `json:"breed,omitempty"` + Breeder *string `json:"breeder,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Test defines model for Test. +type Test struct { + Cases *[]TestCase `json:"cases,omitempty"` + Name *string `json:"name,omitempty"` +} + +// TestCase defines model for TestCase. +type TestCase struct { + Command *string `json:"command,omitempty"` + Name *string `json:"name,omitempty"` +} + +func factory(fm map[string]func() interface{}, path, dk string, o map[string]interface{}) (interface{}, error) { + var dp interface{} + var dv string + var ok bool + + if dp, ok = o[dk]; !ok { + return nil, fmt.Errorf("expecting OneOf object at path '%s' to to have a discriminator property '%s'", path, dk) + } + + if dv, ok = dp.(string); !ok { + return nil, fmt.Errorf("expecting OneOf field '%s's' discriminator property '%s' value to be a string", path, dk) + } + + f, ok := fm[dv] + if !ok { + return nil, fmt.Errorf("Unknown discriminator value '%s' when handling OneOf field '%s'", path, dv) + } + return f(), nil +} + +// Factory method for objects at path Cats.box +func Cats_box_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{}{ + "cat_alive": NewCatAlive, + "cat_dead": NewCatDead, + } + return factory(fm, "Cats.box", "type", o) +} + +// Factory method for objects at path Cats.breed +func Cats_breed_Factory(o map[string]interface{}) (interface{}, error) { + fm := map[string]func() interface{}{ + "mixed_breed": NewMixedBreed, + "pure_breed": NewPurebred, + } + return factory(fm, "Cats.breed", "type", o) +} + +func SchemaPathFactory(path string) (func(map[string]interface{}) (interface{}, error), error) { + // Map StringPath => Factory + pathFactoryMap := map[string]func(map[string]interface{}) (interface{}, error){ + "Cats.box": Cats_box_Factory, + "Cats.breed": Cats_breed_Factory, + } + + return pathFactoryMap[path], nil +} + +func TypeFactory(kind string) (interface{}, error) { + // Map StringPath => Factory + var factoryMap = map[string]func() interface{}{ + "cat_alive": NewCatAlive, + "cat_dead": NewCatDead, + "mixed_breed": NewMixedBreed, + "pure_breed": NewPurebred, + } + f, ok := factoryMap[kind] + if !ok { + return nil, fmt.Errorf("cannot find type %s", kind) + } + return f(), nil +} + +func NewCatAlive() interface{} { + _d := "cat_alive" + return &CatAlive{Type: &_d} +} + +func (r CatAlive) Discriminator() string { + return "type" +} + +func NewCatDead() interface{} { + _d := "cat_dead" + return &CatDead{Type: &_d} +} + +func (r CatDead) Discriminator() string { + return "type" +} + +func NewMixedBreed() interface{} { + _d := "mixed_breed" + return &MixedBreed{Type: &_d} +} + +func (r MixedBreed) Discriminator() string { + return "type" +} + +func NewPurebred() interface{} { + _d := "pure_breed" + return &Purebred{Type: &_d} +} + +func (r Purebred) Discriminator() string { + return "type" +} + +// RequestEditorFn is the function signature for the RequestEditor callback function +type RequestEditorFn func(req *http.Request, ctx context.Context) 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 + + // HTTP client with any customized settings, such as certificate chains. + Client http.Client + + // A callback for modifying requests which are generated before sending over + // the network. + RequestEditor RequestEditorFn +} + +// The interface specification for the client above. +type ClientInterface interface { + // GetCatStatus request + GetCatStatus(ctx context.Context) (*http.Response, error) + + // PutCats request with any body + PutCatsWithBody(ctx context.Context, contentType string, body io.Reader) (*http.Response, error) + + // GetTestByName request + GetTestByName(ctx context.Context, name string) (*http.Response, error) +} + +func (c *Client) GetCatStatus(ctx context.Context) (*http.Response, error) { + req, err := NewGetCatStatusRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if c.RequestEditor != nil { + err = c.RequestEditor(req, ctx) + if err != nil { + return nil, err + } + } + return c.Client.Do(req) +} + +func (c *Client) PutCatsWithBody(ctx context.Context, contentType string, body io.Reader) (*http.Response, error) { + req, err := NewPutCatsRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if c.RequestEditor != nil { + err = c.RequestEditor(req, ctx) + if err != nil { + return nil, err + } + } + return c.Client.Do(req) +} + +func (c *Client) GetTestByName(ctx context.Context, name string) (*http.Response, error) { + req, err := NewGetTestByNameRequest(c.Server, name) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if c.RequestEditor != nil { + err = c.RequestEditor(req, ctx) + if err != nil { + return nil, err + } + } + return c.Client.Do(req) +} + +// NewGetCatStatusRequest generates requests for GetCatStatus +func NewGetCatStatusRequest(server string) (*http.Request, error) { + var err error + + queryUrl := fmt.Sprintf("%s/cat", server) + + req, err := http.NewRequest("GET", queryUrl, nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewPutCatsRequestWithBody generates requests for PutCats with any type of body +func NewPutCatsRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + queryUrl := fmt.Sprintf("%s/cat", server) + + req, err := http.NewRequest("PUT", queryUrl, body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + return req, nil +} + +// NewGetTestByNameRequest generates requests for GetTestByName +func NewGetTestByNameRequest(server string, name string) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParam("simple", false, "name", name) + if err != nil { + return nil, err + } + + queryUrl := fmt.Sprintf("%s/test/%s", server, pathParam0) + + req, err := http.NewRequest("GET", queryUrl, nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// ClientWithResponses builds on ClientInterface to offer response payloads +type ClientWithResponses struct { + ClientInterface +} + +// NewClientWithResponses returns a ClientWithResponses with a default Client: +func NewClientWithResponses(server string) *ClientWithResponses { + return &ClientWithResponses{ + ClientInterface: &Client{ + Client: http.Client{}, + Server: server, + }, + } +} + +// NewClientWithResponsesAndRequestEditorFunc takes in a RequestEditorFn callback function and returns a ClientWithResponses with a default Client: +func NewClientWithResponsesAndRequestEditorFunc(server string, reqEditorFn RequestEditorFn) *ClientWithResponses { + return &ClientWithResponses{ + ClientInterface: &Client{ + Client: http.Client{}, + Server: server, + RequestEditor: reqEditorFn, + }, + } +} + +type getCatStatusResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *interface{} + XML200 *interface{} + YAML200 *struct { + // Embedded struct due to allOf(#/components/schemas/CatAlive) + CatAlive + // Embedded struct due to allOf(#/components/schemas/CatDead) + CatDead + } + JSONDefault *Error +} + +// Status returns HTTPResponse.Status +func (r getCatStatusResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r getCatStatusResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type putCatsResponse struct { + Body []byte + HTTPResponse *http.Response +} + +// Status returns HTTPResponse.Status +func (r putCatsResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r putCatsResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type getTestByNameResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *[]Test + XML200 *[]Test + JSONDefault *Error +} + +// Status returns HTTPResponse.Status +func (r getTestByNameResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r getTestByNameResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +// GetCatStatusWithResponse request returning *GetCatStatusResponse +func (c *ClientWithResponses) GetCatStatusWithResponse(ctx context.Context) (*getCatStatusResponse, error) { + rsp, err := c.GetCatStatus(ctx) + if err != nil { + return nil, err + } + return ParsegetCatStatusResponse(rsp) +} + +// PutCatsWithBodyWithResponse request with arbitrary body returning *PutCatsResponse +func (c *ClientWithResponses) PutCatsWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader) (*putCatsResponse, error) { + rsp, err := c.PutCatsWithBody(ctx, contentType, body) + if err != nil { + return nil, err + } + return ParseputCatsResponse(rsp) +} + +// GetTestByNameWithResponse request returning *GetTestByNameResponse +func (c *ClientWithResponses) GetTestByNameWithResponse(ctx context.Context, name string) (*getTestByNameResponse, error) { + rsp, err := c.GetTestByName(ctx, name) + if err != nil { + return nil, err + } + return ParsegetTestByNameResponse(rsp) +} + +// ParsegetCatStatusResponse parses an HTTP response from a GetCatStatusWithResponse call +func ParsegetCatStatusResponse(rsp *http.Response) (*getCatStatusResponse, error) { + bodyBytes, err := ioutil.ReadAll(rsp.Body) + defer rsp.Body.Close() + if err != nil { + return nil, err + } + + response := &getCatStatusResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + res, err := decode.UnmarshalJSONInto(bodyBytes, &CatDead{}, SchemaPathFactory) + if err != nil { + return nil, err + } + response.JSON200 = &res + case strings.Contains(rsp.Header.Get("Content-Type"), "yaml") && rsp.StatusCode == 200: + response.YAML200 = &struct { + // Embedded struct due to allOf(#/components/schemas/CatAlive) + CatAlive + // Embedded struct due to allOf(#/components/schemas/CatDead) + CatDead + }{} + if err := yaml.Unmarshal(bodyBytes, response.YAML200); err != nil { + return nil, err + } + case strings.Contains(rsp.Header.Get("Content-Type"), "json"): + response.JSONDefault = &Error{} + if _, err := decode.UnmarshalJSONInto(bodyBytes, response.JSONDefault, SchemaPathFactory); err != nil { + return nil, err + } + } + + return response, nil +} + +// ParseputCatsResponse parses an HTTP response from a PutCatsWithResponse call +func ParseputCatsResponse(rsp *http.Response) (*putCatsResponse, error) { + bodyBytes, err := ioutil.ReadAll(rsp.Body) + defer rsp.Body.Close() + if err != nil { + return nil, err + } + + response := &putCatsResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + } + + return response, nil +} + +// ParsegetTestByNameResponse parses an HTTP response from a GetTestByNameWithResponse call +func ParsegetTestByNameResponse(rsp *http.Response) (*getTestByNameResponse, error) { + bodyBytes, err := ioutil.ReadAll(rsp.Body) + defer rsp.Body.Close() + if err != nil { + return nil, err + } + + response := &getTestByNameResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + response.JSON200 = &[]Test{} + if _, err := decode.UnmarshalJSONInto(bodyBytes, response.JSON200, SchemaPathFactory); err != nil { + return nil, err + } + case strings.Contains(rsp.Header.Get("Content-Type"), "xml") && rsp.StatusCode == 200: + response.XML200 = &[]Test{} + if err := xml.Unmarshal(bodyBytes, response.XML200); err != nil { + return nil, err + } + case strings.Contains(rsp.Header.Get("Content-Type"), "json"): + response.JSONDefault = &Error{} + if _, err := decode.UnmarshalJSONInto(bodyBytes, response.JSONDefault, SchemaPathFactory); err != nil { + return nil, err + } + } + + return response, nil +} + +// ServerInterface represents all server handlers. +type ServerInterface interface { + // Get cat status// (GET /cat) + GetCatStatus(ctx echo.Context) error + // deposit cats// (PUT /cat) + PutCats(ctx echo.Context) error + // Get test// (GET /test/{name}) + GetTestByName(ctx echo.Context, name string) error +} + +// ServerInterfaceWrapper converts echo contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface +} + +// GetCatStatus converts echo context to params. +func (w *ServerInterfaceWrapper) GetCatStatus(ctx echo.Context) error { + var err error + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetCatStatus(ctx) + return err +} + +// PutCats converts echo context to params. +func (w *ServerInterfaceWrapper) PutCats(ctx echo.Context) error { + var err error + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.PutCats(ctx) + return err +} + +// GetTestByName converts echo context to params. +func (w *ServerInterfaceWrapper) GetTestByName(ctx echo.Context) error { + var err error + // ------------- Path parameter "name" ------------- + var name string + + err = runtime.BindStyledParameter("simple", false, "name", ctx.Param("name"), &name) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter name: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.GetTestByName(ctx, name) + return err +} + +// RegisterHandlers adds each server route to the EchoRouter. +func RegisterHandlers(router runtime.EchoRouter, si ServerInterface) { + + wrapper := ServerInterfaceWrapper{ + Handler: si, + } + + router.GET("/cat", wrapper.GetCatStatus) + router.PUT("/cat", wrapper.PutCats) + router.GET("/test/:name", wrapper.GetTestByName) + +} + +// Base64 encoded, gzipped, json marshaled Swagger object +var swaggerSpec = []string{ + + "H4sIAAAAAAAC/8xWTW/bRhD9K8S0R1pUnBtvsVoEAdomgHMLDGNMDqkNuB/dmRUsCPzvxS7FSDJpyUGa", + "wCfR+zHzZt57s95BZbWzhowwlDvgak0a0+cK5V2nNhS/nbeOvChKOxiX71mZKm021msUKKFGoStRmiAH", + "2TqCEli8Mi30ORjU6fRkY1jYAZmgofwCFcp9ygB3kzB9n0dcN56ojndqxZVXWhkU64+Abv9J2YbrfQ7W", + "0McGyi87+N1TAyX8VhzqLvZFF5+CpwdPNfT5+YN/q0eqBxD9AaR9+EqVwADxD8J62rkKAz8p1kMOtW0h", + "B9vV2M5VnUNNWP/UhscEz/ebp5U82Mf/n4BvkrtEwNjg/q7P4WFUw4Ube8L6GcL+9P4E/kiXrU8broy8", + "vT40WxmhlnyMoIk5sjdteEx4JJhJkib4le2G9BOumuD/ItPK+kVM6pjmfujHPJnfJD4ldEQ3yZJ2yL8I", + "gQuezgL4TCxzvuDhQwlpvsRljLFCpgMAQO9xe0b1Y+p0bYZnrdHMV/9swBhSmcYmG1C0gRNlDZTwea04", + "U5xhJsSSfXRk3n36kN06qqJ2lHQx0n75amVrek8mS53JYUOehzBvFsvFMpnHkUGnoIS3i+XiDeTgUNYJ", + "eVFhamdL6ScWhRHFhxrKuLhCuRWUwJCDJ3bW7Bt9vVwOlRshk+6ic52q0u3iK0cE43PwOoze5ycQH3V3", + "ihDN9tdk3uIkddf9rNRp+B+L6zZUFTEPr0KDoZPv4vFc3mEKzuQcN3LgoDX6LZTwniSrUDIe5SXY8v45", + "gTiWXZiRpAuS3pOoxn8DsdzYevt8AVffV0AKPYO/UyyZbbKGOmUoqzyhBE8jDJUGovhAJxXW5CyrVCWn", + "4oto52IXJ0J/znTRyTeDMaJVPWoS8pwEoiKeaF8YR8vw8xRJflTy09Fz94NefvGQnQ7YSyb8kdCvWuoy", + "TOdR5OnPwZ5MfjOyG3wHJaxFHJdFksvColNX8R+JlsyisrrYXKcBcDh69uRd/18AAAD//3dwHcOjCwAA", +} + +// 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 +} diff --git a/pkg/codegen/testdata/testOpenAPIDefinitionWithOneOfDiscriminatorsAndEnums.yaml b/pkg/codegen/testdata/testOpenAPIDefinitionWithOneOfDiscriminatorsAndEnums.yaml new file mode 100644 index 000000000..94c8c9cf7 --- /dev/null +++ b/pkg/codegen/testdata/testOpenAPIDefinitionWithOneOfDiscriminatorsAndEnums.yaml @@ -0,0 +1,184 @@ +openapi: 3.0.1 + +info: + title: OpenAPI-CodeGen Test + description: 'This is a test OpenAPI Spec' + version: 1.0.0 + +servers: +- url: https://test.oapi-codegen.com/v2 +- url: http://test.oapi-codegen.com/v2 + +paths: + /test/{name}: + get: + tags: + - test + summary: Get test + operationId: getTestByName + parameters: + - name: name + in: path + required: true + schema: + type: string + responses: + 200: + description: Success + content: + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Test' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Test' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /cat: + put: + summary: deposit cats + operationId: putCats + requestBody: + description: list of feline creatures + required: true + content: + application-json: + schema: + $ref: '#/components/schemas/Cats' + + get: + tags: + - cat + summary: Get cat status + operationId: getCatStatus + responses: + 200: + description: Success + content: + application/json: + schema: + discriminator: + propertyName: "type" + oneOf: + - $ref: '#/components/schemas/CatAlive' + - $ref: '#/components/schemas/CatDead' + application/xml: + schema: + anyOf: + - $ref: '#/components/schemas/CatAlive' + - $ref: '#/components/schemas/CatDead' + application/yaml: + schema: + allOf: + - $ref: '#/components/schemas/CatAlive' + - $ref: '#/components/schemas/CatDead' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + + Test: + properties: + name: + type: string + cases: + type: array + items: + $ref: '#/components/schemas/TestCase' + + TestCase: + properties: + name: + type: string + command: + type: string + + Cats: + type: object + properties: + breed: + $ref: '#/components/schemas/CatBreed' + box: + discriminator: + propertyName: "type" + oneOf: + - $ref: '#/components/schemas/CatAlive' + - $ref: '#/components/schemas/CatDead' + + CatBreed: + type: object + discriminator: + propertyName: "type" + oneOf: + - $ref: '#/components/schemas/Purebred' + - $ref: '#/components/schemas/MixedBreed' + + Error: + properties: + code: + type: integer + format: int32 + message: + type: string + + Purebred: + properties: + type: + type: string + enum: + - pure_breed + breed: + type: string + breeder: + type: string + + MixedBreed: + properties: + type: + type: string + enum: + - mixed_breed + furColor: + type: string + furLength: + type: string + + CatAlive: + properties: + type: + type: string + enum: + - cat_alive + name: + type: string + alive_since: + type: string + format: date-time + + CatDead: + properties: + type: + type: string + enum: + - cat_dead + name: + type: string + dead_since: + type: string + format: date-time + cause: + type: string + enum: [car, dog, oldage] diff --git a/pkg/codegen/testdata/testResolvingSpec.json.golden b/pkg/codegen/testdata/testResolvingSpec.json.golden new file mode 100644 index 000000000..7d0b699cf --- /dev/null +++ b/pkg/codegen/testdata/testResolvingSpec.json.golden @@ -0,0 +1,114 @@ +{ + "components": { + "schemas": { + "Test": { + "properties": { + "cases": { + "items": { + "properties": { + "command": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "type": "array" + }, + "name": { + "type": "string" + }, + "verifier": { + "properties": { + "name": { + "type": "string" + } + } + } + } + }, + "TestCase": { + "properties": { + "command": { + "type": "string" + }, + "name": { + "type": "string" + } + } + } + } + }, + "info": { + "description": "This is a test OpenAPI Spec", + "title": "OpenAPI-CodeGen Test", + "version": "1.0.0" + }, + "openapi": "3.0.1", + "paths": { + "/test/{name}": { + "get": { + "operationId": "getTestByName", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "cases": { + "items": { + "properties": { + "command": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "type": "array" + }, + "name": { + "type": "string" + }, + "verifier": { + "properties": { + "name": { + "type": "string" + } + } + } + } + } + } + }, + "description": "Success" + } + }, + "summary": "Get test", + "tags": [ + "test" + ] + } + } + }, + "servers": [ + { + "url": "https://test.oapi-codegen.com/v2" + }, + { + "url": "http://test.oapi-codegen.com/v2" + } + ] +} diff --git a/pkg/codegen/testdata/testResolvingSpec.yaml b/pkg/codegen/testdata/testResolvingSpec.yaml new file mode 100644 index 000000000..0f393ab25 --- /dev/null +++ b/pkg/codegen/testdata/testResolvingSpec.yaml @@ -0,0 +1,52 @@ +openapi: 3.0.1 + +info: + title: OpenAPI-CodeGen Test + description: 'This is a test OpenAPI Spec' + version: 1.0.0 + +servers: +- url: https://test.oapi-codegen.com/v2 +- url: http://test.oapi-codegen.com/v2 + +paths: + /test/{name}: + get: + tags: + - test + summary: Get test + operationId: getTestByName + parameters: + - name: name + in: path + required: true + schema: + type: string + responses: + 200: + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Test' + +components: + schemas: + Test: + properties: + name: + type: string + verifier: + $ref: 'http://localhost:23456/included.yaml#/components/schemas/Verifier' + cases: + type: array + items: + $ref: '#/components/schemas/TestCase' + + TestCase: + properties: + name: + type: string + command: + type: string + diff --git a/pkg/codegen/utils.go b/pkg/codegen/utils.go index 2a35b0341..b6259a60f 100644 --- a/pkg/codegen/utils.go +++ b/pkg/codegen/utils.go @@ -15,6 +15,10 @@ package codegen import ( "fmt" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/pkg/errors" + "regexp" "sort" "strings" @@ -26,8 +30,12 @@ import ( var pathParamRE *regexp.Regexp +// list of valid word characters in an identifier (excluding '/') used by ToCamelCase +var separatorRE *regexp.Regexp + func init() { pathParamRE = regexp.MustCompile("{[.;?]?([^{}*]+)\\*?}") + separatorRE = regexp.MustCompile(`[^.+:;_~ (){}\[\]\-]+`) } // Uppercase the first character in a string. This assumes UTF-8, so we have @@ -65,7 +73,7 @@ func ToCamelCase(str string) string { if unicode.IsUpper(v) { n += string(v) } - if unicode.IsDigit(v) { + if unicode.IsDigit(v) { n += string(v) } if unicode.IsLower(v) { @@ -76,7 +84,7 @@ func ToCamelCase(str string) string { } } - if strings.ContainsRune(separators, v) { + if strings.ContainsRune(separators, v) { capNext = true } else { capNext = false @@ -197,20 +205,38 @@ func StringInArray(str string, array []string) bool { // #/components/schemas/Foo -> Foo // #/components/parameters/Bar -> Bar // #/components/responses/Baz -> Baz -// Remote components (document.json#/Foo) are not yet supported -// URL components (http://deepmap.com/schemas/document.json#Foo) are not yet -// supported -// We only support flat components for now, so no components in a schema under -// components. -func RefPathToGoType(refPath string) (string, error) { - pathParts := strings.Split(refPath, "/") - if pathParts[0] != "#" { - return "", errors.New("Only local document components are supported") +// +// To specify remote paths there must also be a typeImport map with the types +// mapped to import paths. +// https://foo.com/bar#/components/parameters/Bar -> packagename.Bar +// foo.json#/components/parameters/Bar -> packagename.Bar +func RefPathToGoType(refPath string, importedTypes map[string]TypeImportSpec) (string, error) { + s := strings.Split(refPath, "#") + if len(s) < 2 { + return "", errors.New("Missing fragment marker - this does not seem like a local or remote reference") + } else if len(s) > 2 { + return "", errors.New("Extra fragment marker") } + + pathParts := strings.Split(s[len(s)-1], "/") + if len(pathParts) != 4 { return "", errors.New("Parameter nesting is deeper than supported") } - return SchemaNameToTypeName(pathParts[3]), nil + schemaName := SchemaNameToTypeName(pathParts[len(pathParts)-1]) + + if s[0] != "" { + if importedTypes == nil { + return "", errors.New("detected remote document component but no TypeImports specified") + } + importedType, ok := importedTypes[schemaName] + if !ok { + return "", errors.New("detected remote document component not specified in TypeImports") + } + + return importedType.PackageName + "." + schemaName, nil + } + return schemaName, nil } // This function converts a swagger style path URI with parameters to a @@ -259,6 +285,12 @@ func ReplacePathParamsWithStr(uri string) string { return pathParamRE.ReplaceAllString(uri, "%s") } +// Replaces path parameters with Par1, Par2... +func ReplacePathParamsWithParNStr(uri string) string { + p := 0 + return pathParamRE.ReplaceAllStringFunc(uri, func(_ string) string { p++; return fmt.Sprintf("Par%d", p) }) +} + // Reorders the given parameter definitions to match those in the path URI. func SortParamsByPath(path string, in []ParameterDefinition) ([]ParameterDefinition, error) { pathParams := OrderedParamsFromUri(path) @@ -372,3 +404,13 @@ func StringToGoComment(in string) string { in = strings.TrimSuffix(in, "\n// ") return in } + +// This converts a path, like Object/field1/nestedField into a dot separated single string +func DotSeparatedPath(path []string) string { + return strings.Join(path, ".") +} + +// DotSeparatedPath converts a dot separated path string, like Object.field1 into a go identifier +func DottedStringToTypeName(path string) string { + return strings.ReplaceAll(path, ".", "_") +} diff --git a/pkg/codegen/utils_test.go b/pkg/codegen/utils_test.go index 589283248..c2efd48df 100644 --- a/pkg/codegen/utils_test.go +++ b/pkg/codegen/utils_test.go @@ -23,9 +23,20 @@ import ( func TestStringOps(t *testing.T) { // Test that each substitution works assert.Equal(t, "WordWordWORDWordWordWordWordWordWordWordWordWordWord", ToCamelCase("word.word-WORD+Word_word~word(Word)Word{Word}Word[Word]Word:Word;"), "Camel case conversion failed") + tests := []struct { + in, out, msg string + }{ + {in: "word.word-WORD_word~word", out: "WordWordWORDWordWord", msg: "Camel case conversion failed"}, + {in: "number-1234", out: "Number1234", msg: "Number Camelcasing not working."}, + {in: "path~to~res", out: "PathToRes", msg: "Failed converting path separator"}, + {in: "path-{pathName}", out: "PathPathName", msg: "Failed converting path parameter"}, + {in: "0-a.b+c:d;e_f~g(h)i{j}k[l]m", out: "0ABCDEFGHIJKLM", msg: "Separator test failed"}, + {in: "0-A.B+C:D;E_F~G(H)I{J}K[L]M", out: "0ABCDEFGHIJKLM", msg: "Separator test failed"}, + } - // Make sure numbers don't interact in a funny way. - assert.Equal(t, "Number1234", ToCamelCase("number-1234"), "Number Camelcasing not working.") + for _, test := range tests { + assert.Equal(t, test.out, ToCamelCase(test.in), test.msg) + } } func TestSortedSchemaKeys(t *testing.T) { @@ -134,22 +145,97 @@ func TestSortedRequestBodyKeys(t *testing.T) { } func TestRefPathToGoType(t *testing.T) { - goType, err := RefPathToGoType("#/components/schemas/Foo") - assert.Equal(t, "Foo", goType) - assert.NoError(t, err, "Expecting no error") - - goType, err = RefPathToGoType("#/components/parameters/foo_bar") - assert.Equal(t, "FooBar", goType) - assert.NoError(t, err, "Expecting no error") - - _, err = RefPathToGoType("http://deepmap.com/doc.json#/components/parameters/foo_bar") - assert.Errorf(t, err, "Expected an error on URL reference") - - _, err = RefPathToGoType("doc.json#/components/parameters/foo_bar") - assert.Errorf(t, err, "Expected an error on remote reference") + testTable := map[string]struct { + path string + importedTypes map[string]TypeImportSpec + goType string + isErr bool + }{ + "Pascal case": { + "#/components/schemas/Foo", + nil, + "Foo", + false, + }, + "Snake case": { + "#/components/parameters/foo_bar", + nil, + "FooBar", + false, + }, + "remote ref, no typemap": { + "http://deepmap.com/doc.json#/components/parameters/foo_bar", + nil, + "", + true, + }, + "path ref, no typemap": { + "doc.json#/components/parameters/foo_bar", + nil, + "", + true, + }, + "remote ref, matches typemap": { + "http://deepmap.com/doc.json#/components/parameters/foo_bar", + map[string]TypeImportSpec{"FooBar": TypeImportSpec{Name: "FooBar", PackageName: "mypkg", ImportPath: "github.com/me/mypkg"}}, + "mypkg.FooBar", + false, + }, + "remote ref, matches typemap, using PackageName": { + "http://deepmap.com/doc.json#/components/parameters/foo_bar", + map[string]TypeImportSpec{"FooBar": TypeImportSpec{Name: "FooBar", PackageName: "that_pkg", ImportPath: "github.com/me/mypkg"}}, + "that_pkg.FooBar", + false, + }, + "path ref, matches typemap": { + "doc.json#/components/parameters/foo_bar", + map[string]TypeImportSpec{"FooBar": TypeImportSpec{Name: "FooBar", PackageName: "mypkg", ImportPath: "github.com/me/mypkg"}}, + "mypkg.FooBar", + false, + }, + "remote ref, no match in typemap": { + "http://deepmap.com/doc.json#/components/parameters/foo_bar", + map[string]TypeImportSpec{"Foo": TypeImportSpec{Name: "Foo", PackageName: "mypkg", ImportPath: "github.com/me/mypkg"}}, + "", + true, + }, + "path ref, no match in typemap": { + "doc.json#/components/parameters/foo_bar", + map[string]TypeImportSpec{"Foo": TypeImportSpec{Name: "Foo", PackageName: "mypkg", ImportPath: "github.com/me/mypkg"}}, + "", + true, + }, + "reference depth incorrect": { + "#/components/parameters/foo/components/bar", + nil, + "", + true, + }, + "invalid path, too many #": { + "#/components/parameters/foo#", + nil, + "", + true, + }, + "invalid path, no #": { + "/components/parameters/foo", + nil, + "", + true, + }, + } + for name, test := range testTable { + t.Run(name, func(t *testing.T) { + goType, err := RefPathToGoType(test.path, test.importedTypes) + assert.Equal(t, test.goType, goType) + if test.isErr { + assert.Error(t, err, "Expected an error") + } else { + assert.NoError(t, err, "Expecting no error") + } + }) + } - _, err = RefPathToGoType("#/components/parameters/foo/components/bar") - assert.Errorf(t, err, "Expected an error on reference depth") } func TestSwaggerUriToEchoUri(t *testing.T) { @@ -231,5 +317,9 @@ Line assert.EqualValues(t, testCase.expected, result, testCase.message) }) } +} +func TestReplacePathParamsWithParNStr(t *testing.T) { + result := ReplacePathParamsWithParNStr("GET /path/{param1}/{.param2}/{;param3*}/foo") + assert.EqualValues(t, "GET /path/Par1/Par2/Par3/foo", result) } diff --git a/pkg/middleware/oapi_validate.go b/pkg/middleware/oapi_validate.go index 2cf2af643..a9745f7c5 100644 --- a/pkg/middleware/oapi_validate.go +++ b/pkg/middleware/oapi_validate.go @@ -135,8 +135,8 @@ func ValidateRequestFromContext(ctx echo.Context, router *openapi3filter.Router, // This should never happen today, but if our upstream code changes, // we don't want to crash the server, so handle the unexpected error. return &echo.HTTPError{ - Code: http.StatusInternalServerError, - Message: fmt.Sprintf("error validating request: %s", err), + Code: http.StatusInternalServerError, + Message: fmt.Sprintf("error validating request: %s", err), Internal: err, } } diff --git a/pkg/middleware/oapi_validate_test.go b/pkg/middleware/oapi_validate_test.go index aede2ff10..3679ea809 100644 --- a/pkg/middleware/oapi_validate_test.go +++ b/pkg/middleware/oapi_validate_test.go @@ -26,7 +26,7 @@ import ( "github.com/labstack/echo/v4" "github.com/stretchr/testify/assert" - "github.com/deepmap/oapi-codegen/pkg/testutil" + "github.com/weberr13/oapi-codegen/pkg/testutil" ) var testSchema = `openapi: "3.0.0" diff --git a/pkg/runtime/bindparam.go b/pkg/runtime/bindparam.go index 18a41300a..7556b8f62 100644 --- a/pkg/runtime/bindparam.go +++ b/pkg/runtime/bindparam.go @@ -28,8 +28,8 @@ import ( // This function binds a parameter as described in the Path Parameters // section here to a Go object: // https://swagger.io/docs/specification/serialization/ -func BindStyledParameter(style string, explode bool, paramName string, - value string, dest interface{}) error { +func BindStyledParameter(style string, explode bool, unescape func(string) (string, error), + paramName string, value string, dest interface{}) error { if value == "" { return echo.NewHTTPError(http.StatusBadRequest, "parameter '%s' is empty, can't bind its value", paramName) @@ -49,7 +49,7 @@ func BindStyledParameter(style string, explode bool, paramName string, return echo.NewHTTPError(http.StatusBadRequest, err.Error()) } - err = bindSplitPartsToDestinationStruct(paramName, parts, explode, dest) + err = bindSplitPartsToDestinationStruct(paramName, parts, explode, unescape, dest) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, err.Error()) } @@ -63,7 +63,7 @@ func BindStyledParameter(style string, explode bool, paramName string, return fmt.Errorf("error splitting input '%s' into parts: %s", value, err) } - err = bindSplitPartsToDestinationArray(parts, dest) + err = bindSplitPartsToDestinationArray(unescape, parts, dest) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, err.Error()) } @@ -71,7 +71,7 @@ func BindStyledParameter(style string, explode bool, paramName string, } // Try to bind the remaining types as a base type. - return BindStringToObject(value, dest) + return BindStringToObject(unescape, value, dest) } // This is a complex set of operations, but each given parameter style can be @@ -167,7 +167,7 @@ func splitStyledParameter(style string, explode bool, object bool, paramName str // Given a set of values as a slice, create a slice to hold them all, and // assign to each one by one. -func bindSplitPartsToDestinationArray(parts []string, dest interface{}) error { +func bindSplitPartsToDestinationArray(unescape func(string) (string, error), parts []string, dest interface{}) error { // Everything comes in by pointer, dereference it v := reflect.Indirect(reflect.ValueOf(dest)) @@ -179,7 +179,7 @@ func bindSplitPartsToDestinationArray(parts []string, dest interface{}) error { // hold all the parts. newArray := reflect.MakeSlice(t, len(parts), len(parts)) for i, p := range parts { - err := BindStringToObject(p, newArray.Index(i).Addr().Interface()) + err := BindStringToObject(unescape, p, newArray.Index(i).Addr().Interface()) if err != nil { return fmt.Errorf("error setting array element: %s", err) } @@ -200,7 +200,8 @@ func bindSplitPartsToDestinationArray(parts []string, dest interface{}) error { // We punt the hard work of binding these values to the object to the json // library. We'll turn those arrays into JSON strings, and unmarshal // into the struct. -func bindSplitPartsToDestinationStruct(paramName string, parts []string, explode bool, dest interface{}) error { +func bindSplitPartsToDestinationStruct(paramName string, parts []string, explode bool, + unescape func(string) (string, error), dest interface{}) error { // We've got a destination object, we'll create a JSON representation // of the input value, and let the json library deal with the unmarshaling var fields []string @@ -220,7 +221,13 @@ func bindSplitPartsToDestinationStruct(paramName string, parts []string, explode fields = make([]string, len(parts)/2) for i := 0; i < len(parts); i += 2 { key := parts[i] - value := parts[i+1] + if unescape == nil { + return fmt.Errorf("no unescape function provided") + } + value, err := unescape(parts[i+1]) + if err != nil { + return fmt.Errorf("error unescaping string parameter element: %s", parts[i+1]) + } fields[i/2] = "\"" + key + "\":\"" + value + "\"" } } @@ -313,7 +320,7 @@ func BindQueryParameter(style string, explode bool, required bool, paramName str return nil } } - err = bindSplitPartsToDestinationArray(values, output) + err = bindSplitPartsToDestinationArray(url.QueryUnescape, values, output) case reflect.Struct: // This case is really annoying, and error prone, but the // form style object binding doesn't tell us which arguments @@ -335,7 +342,7 @@ func BindQueryParameter(style string, explode bool, required bool, paramName str return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("multiple values for single value parameter '%s'", paramName)) } - err = BindStringToObject(values[0], output) + err = BindStringToObject(url.QueryUnescape, values[0], output) } if err != nil { return err @@ -365,9 +372,9 @@ func BindQueryParameter(style string, explode bool, required bool, paramName str var err error switch k { case reflect.Slice: - err = bindSplitPartsToDestinationArray(parts, output) + err = bindSplitPartsToDestinationArray(url.QueryUnescape, parts, output) case reflect.Struct: - err = bindSplitPartsToDestinationStruct(paramName, parts, explode, output) + err = bindSplitPartsToDestinationStruct(paramName, parts, explode, url.QueryUnescape, output) default: if len(parts) == 0 { if required { @@ -381,7 +388,7 @@ func BindQueryParameter(style string, explode bool, required bool, paramName str return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("multiple values for single value parameter '%s'", paramName)) } - err = BindStringToObject(parts[0], output) + err = BindStringToObject(url.QueryUnescape, parts[0], output) } if err != nil { return err @@ -404,7 +411,12 @@ func BindQueryParameter(style string, explode bool, required bool, paramName str } k = strings.TrimSuffix(split[1], "]") - objectMap[k] = v[0] + val, err := url.QueryUnescape(v[0]) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, + fmt.Sprintf("parameter '%s=%s' could not be unescaped", k, v)) + } + objectMap[k] = val } // Marshal and unmarshal the objectMap into dest @@ -473,7 +485,7 @@ func bindParamsToExplodedObject(paramName string, values url.Values, dest interf return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("field '%s' specified multiple times for param '%s'", fieldName, paramName)) } - err := BindStringToObject(fieldVal[0], v.Field(i).Addr().Interface()) + err := BindStringToObject(url.QueryUnescape, fieldVal[0], v.Field(i).Addr().Interface()) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("could not bind query arg '%s' to request object: %s", paramName, err)) diff --git a/pkg/runtime/bindparam_test.go b/pkg/runtime/bindparam_test.go index fcb827557..817b851d3 100644 --- a/pkg/runtime/bindparam_test.go +++ b/pkg/runtime/bindparam_test.go @@ -270,4 +270,97 @@ func TestBindQueryParameter(t *testing.T) { assert.NoError(t, err) assert.Equal(t, expected, birthday) }) + // ------------------------ deepObject style --------------------------------- + type ID struct { + FirstName *string `json:"firstName"` + LastName *string `json:"lastName"` + Role string `json:"role"` + } + + expectedName := "Alex" + expectedDeepObject := &ID{FirstName: &expectedName, Role: "admin?"} + + actualDeepObject := new(ID) + paramName := "id" + queryParams := url.Values{ + "id[firstName]": {"Alex"}, + "id[role]": {"admin%3F"}, + "foo": {"bar"}, + } + + err := BindQueryParameter("deepObject", true, false, paramName, queryParams, &actualDeepObject) + assert.NoError(t, err) + assert.Equal(t, expectedDeepObject, actualDeepObject) + + // ------------------------ form style --------------------------------- + // ----- slice, exploded=true ----- + expectedSlice := &[]string{"Alex", "Ben?", "Carl"} + + actualSlice := &[]string{} + paramName = "name" + queryParams = url.Values{ + "name": {"Alex", "Ben%3F", "Carl"}, + } + + err = BindQueryParameter("form", true, false, paramName, queryParams, &actualSlice) + assert.NoError(t, err) + assert.Equal(t, expectedSlice, actualSlice) + + // ----- slice, exploded=false ----- + expectedSlice = &[]string{"Ben?"} + + actualSlice = &[]string{} + paramName = "name" + queryParams = url.Values{ + "name": {"Ben%3F"}, + } + + err = BindQueryParameter("form", false, false, paramName, queryParams, &actualSlice) + assert.NoError(t, err) + assert.Equal(t, expectedSlice, actualSlice) + + // ----- struct, exploded=true ----- + type Name struct { + FirstName string `json:"firstName"` + LastName string `json:"lastName"` + } + + expectedStruct := &Name{FirstName: "Alex", LastName: "$mith"} + + actualStruct := new(Name) + paramName = "name" + queryParams = url.Values{ + "firstName": {"Alex"}, + "lastName": {"%24mith"}, + } + + err = BindQueryParameter("form", true, false, paramName, queryParams, &actualStruct) + assert.NoError(t, err) + assert.Equal(t, expectedStruct, actualStruct) + + // ----- struct, exploded=false ----- + expectedStruct = &Name{FirstName: "Alex", LastName: "$mith"} + + actualStruct = new(Name) + paramName = "name" + queryParams = url.Values{ + "name": {"firstname,Alex,lastName,%24mith"}, + } + + err = BindQueryParameter("form", false, false, paramName, queryParams, &actualStruct) + assert.NoError(t, err) + assert.Equal(t, expectedStruct, actualStruct) + + // ----- default ----- + expectedString := "$mith" + + actualString := new(string) + paramName = "name" + queryParams = url.Values{ + "name": {"%24mith"}, + } + + err = BindQueryParameter("form", true, false, paramName, queryParams, &actualString) + assert.NoError(t, err) + assert.Equal(t, &expectedString, actualString) } diff --git a/pkg/runtime/bindstring.go b/pkg/runtime/bindstring.go index f3397a2b0..c3a93c1f9 100644 --- a/pkg/runtime/bindstring.go +++ b/pkg/runtime/bindstring.go @@ -29,7 +29,7 @@ import ( // type aliases. This function was the easy way out, the better way, since we // know the destination type each place that we use this, is to generate code // to read each specific type. -func BindStringToObject(src string, dst interface{}) error { +func BindStringToObject(unescape func(string) (string, error), src string, dst interface{}) error { var err error v := reflect.ValueOf(dst) @@ -55,7 +55,16 @@ func BindStringToObject(src string, dst interface{}) error { v.SetInt(val) } case reflect.String: - v.SetString(src) + if unescape == nil { + return fmt.Errorf("no unescape function provided") + } + + var escaped string + escaped, err = unescape(src) + if err != nil { + return fmt.Errorf("error unescaping string parameter element: %s", src) + } + v.SetString(escaped) err = nil case reflect.Float64, reflect.Float32: var val float64 diff --git a/pkg/runtime/bindstring_test.go b/pkg/runtime/bindstring_test.go index 193f54e5b..95be392ed 100644 --- a/pkg/runtime/bindstring_test.go +++ b/pkg/runtime/bindstring_test.go @@ -14,79 +14,104 @@ package runtime import ( + "net/url" "testing" "time" "github.com/stretchr/testify/assert" ) +func unescapePassThrough(s string) (string, error) { + return s, nil +} + func TestBindStringToObject(t *testing.T) { + var s string + assert.NoError(t, BindStringToObject(url.PathUnescape, "foo", &s)) + assert.Equal(t, "foo", s) + assert.NoError(t, BindStringToObject(url.QueryUnescape, "foo", &s)) + assert.Equal(t, "foo", s) + assert.NoError(t, BindStringToObject(unescapePassThrough, "foo", &s)) + assert.Equal(t, "foo", s) + assert.NoError(t, BindStringToObject(url.PathUnescape, "foo%3Fbar", &s)) + assert.Equal(t, "foo?bar", s) + assert.NoError(t, BindStringToObject(url.QueryUnescape, "foo%3Fbar", &s)) + assert.Equal(t, "foo?bar", s) + assert.NoError(t, BindStringToObject(unescapePassThrough, "foo%3Fbar", &s)) + assert.Equal(t, "foo%3Fbar", s) + assert.NoError(t, BindStringToObject(url.PathUnescape, "foo+bar", &s)) + assert.Equal(t, "foo+bar", s) + assert.NoError(t, BindStringToObject(url.QueryUnescape, "foo+bar", &s)) + assert.Equal(t, "foo bar", s) + assert.NoError(t, BindStringToObject(unescapePassThrough, "foo+bar", &s)) + assert.Equal(t, "foo+bar", s) + var i int - assert.NoError(t, BindStringToObject("5", &i)) + assert.NoError(t, BindStringToObject(url.PathUnescape, "5", &i)) assert.Equal(t, 5, i) // Let's make sure we error out on things that can't be the correct // type. Since we're using reflect package setters, we'll have similar // unassignable type errors. - assert.Error(t, BindStringToObject("5.7", &i)) - assert.Error(t, BindStringToObject("foo", &i)) - assert.Error(t, BindStringToObject("1,2,3", &i)) + assert.Error(t, BindStringToObject(url.PathUnescape, "5.7", &i)) + assert.Error(t, BindStringToObject(url.PathUnescape, "foo", &i)) + assert.Error(t, BindStringToObject(url.PathUnescape, "1,2,3", &i)) var i64 int64 - assert.NoError(t, BindStringToObject("124", &i64)) + assert.NoError(t, BindStringToObject(url.PathUnescape, "124", &i64)) assert.Equal(t, int64(124), i64) - assert.Error(t, BindStringToObject("5.7", &i64)) - assert.Error(t, BindStringToObject("foo", &i64)) - assert.Error(t, BindStringToObject("1,2,3", &i64)) + assert.Error(t, BindStringToObject(url.PathUnescape, "5.7", &i64)) + assert.Error(t, BindStringToObject(url.PathUnescape, "foo", &i64)) + assert.Error(t, BindStringToObject(url.PathUnescape, "1,2,3", &i64)) var i32 int32 - assert.NoError(t, BindStringToObject("12", &i32)) + assert.NoError(t, BindStringToObject(url.PathUnescape, "12", &i32)) assert.Equal(t, int32(12), i32) - assert.Error(t, BindStringToObject("5.7", &i32)) - assert.Error(t, BindStringToObject("foo", &i32)) - assert.Error(t, BindStringToObject("1,2,3", &i32)) + assert.Error(t, BindStringToObject(url.PathUnescape, "5.7", &i32)) + assert.Error(t, BindStringToObject(url.PathUnescape, "foo", &i32)) + assert.Error(t, BindStringToObject(url.PathUnescape, "1,2,3", &i32)) var b bool - assert.NoError(t, BindStringToObject("True", &b)) + assert.NoError(t, BindStringToObject(url.PathUnescape, "True", &b)) assert.Equal(t, true, b) - assert.NoError(t, BindStringToObject("true", &b)) + assert.NoError(t, BindStringToObject(url.PathUnescape, "true", &b)) assert.Equal(t, true, b) - assert.NoError(t, BindStringToObject("1", &b)) + assert.NoError(t, BindStringToObject(url.PathUnescape, "1", &b)) assert.Equal(t, true, b) var f64 float64 - assert.NoError(t, BindStringToObject("1.25", &f64)) + assert.NoError(t, BindStringToObject(url.PathUnescape, "1.25", &f64)) assert.Equal(t, float64(1.25), f64) - assert.Error(t, BindStringToObject("foo", &f64)) - assert.Error(t, BindStringToObject("1,2,3", &f64)) + assert.Error(t, BindStringToObject(url.PathUnescape, "foo", &f64)) + assert.Error(t, BindStringToObject(url.PathUnescape, "1,2,3", &f64)) var f32 float32 - assert.NoError(t, BindStringToObject("3.125", &f32)) + assert.NoError(t, BindStringToObject(url.PathUnescape, "3.125", &f32)) assert.Equal(t, float32(3.125), f32) - assert.Error(t, BindStringToObject("foo", &f32)) - assert.Error(t, BindStringToObject("1,2,3", &f32)) + assert.Error(t, BindStringToObject(url.PathUnescape, "foo", &f32)) + assert.Error(t, BindStringToObject(url.PathUnescape, "1,2,3", &f32)) // This checks whether binding works through a type alias. type SomeType int var st SomeType - assert.NoError(t, BindStringToObject("5", &st)) + assert.NoError(t, BindStringToObject(url.PathUnescape, "5", &st)) assert.Equal(t, SomeType(5), st) // Check time binding now := time.Now().UTC() strTime := now.Format(time.RFC3339Nano) var parsedTime time.Time - assert.NoError(t, BindStringToObject(strTime, &parsedTime)) + assert.NoError(t, BindStringToObject(url.PathUnescape, strTime, &parsedTime)) parsedTime = parsedTime.UTC() assert.EqualValues(t, now, parsedTime) now = now.Truncate(time.Second) strTime = now.Format(time.RFC3339) - assert.NoError(t, BindStringToObject(strTime, &parsedTime)) + assert.NoError(t, BindStringToObject(url.PathUnescape, strTime, &parsedTime)) parsedTime = parsedTime.UTC() assert.EqualValues(t, now, parsedTime) } diff --git a/pkg/runtime/styleparam.go b/pkg/runtime/styleparam.go index 3edcce67d..5d940b394 100644 --- a/pkg/runtime/styleparam.go +++ b/pkg/runtime/styleparam.go @@ -25,7 +25,7 @@ import ( // Given an input value, such as a primitive type, array or object, turn it // into a parameter based on style/explode definition. -func StyleParam(style string, explode bool, paramName string, value interface{}) (string, error) { +func StyleParam(style string, explode bool, escape func(string) string, paramName string, value interface{}) (string, error) { t := reflect.TypeOf(value) v := reflect.ValueOf(value) @@ -46,17 +46,17 @@ func StyleParam(style string, explode bool, paramName string, value interface{}) for i := 0; i < n; i++ { sliceVal[i] = v.Index(i).Interface() } - return styleSlice(style, explode, paramName, sliceVal) + return styleSlice(style, explode, escape, paramName, sliceVal) case reflect.Struct: - return styleStruct(style, explode, paramName, value) + return styleStruct(style, explode, escape, paramName, value) case reflect.Map: return styleMap(style, explode, paramName, value) default: - return stylePrimitive(style, explode, paramName, value) + return stylePrimitive(style, explode, escape, paramName, value) } } -func styleSlice(style string, explode bool, paramName string, values []interface{}) (string, error) { +func styleSlice(style string, explode bool, escape func(string) string, paramName string, values []interface{}) (string, error) { var prefix string var separator string @@ -106,7 +106,7 @@ func styleSlice(style string, explode bool, paramName string, values []interface var err error parts := make([]string, len(values)) for i, v := range values { - parts[i], err = primitiveToString(v) + parts[i], err = primitiveToString(escape, v) if err != nil { return "", fmt.Errorf("error formatting '%s': %s", paramName, err) } @@ -125,7 +125,7 @@ func sortedKeys(strMap map[string]string) []string { return keys } -func styleStruct(style string, explode bool, paramName string, value interface{}) (string, error) { +func styleStruct(style string, explode bool, escape func(string) string, paramName string, value interface{}) (string, error) { // This is a special case. The struct may be a time, in which case, marshal // it in RFC3339 format. if timeVal, ok := value.(*time.Time); ok { @@ -157,7 +157,7 @@ func styleStruct(style string, explode bool, paramName string, value interface{} if f.Type().Kind() == reflect.Ptr && f.IsNil() { continue } - str, err := primitiveToString(f.Interface()) + str, err := primitiveToString(escape, f.Interface()) if err != nil { return "", fmt.Errorf("error formatting '%s': %s", paramName, err) } @@ -252,8 +252,8 @@ func processFieldDict(style string, explode bool, paramName string, fieldDict ma return prefix + strings.Join(parts, separator), nil } -func stylePrimitive(style string, explode bool, paramName string, value interface{}) (string, error) { - strVal, err := primitiveToString(value) +func stylePrimitive(style string, explode bool, escape func(string) string, paramName string, value interface{}) (string, error) { + strVal, err := primitiveToString(escape, value) if err != nil { return "", err } @@ -275,7 +275,7 @@ func stylePrimitive(style string, explode bool, paramName string, value interfac // Converts a primitive value to a string. We need to do this based on the // Kind of an interface, not the Type to work with aliased types. -func primitiveToString(value interface{}) (string, error) { +func primitiveToString(escape func(string) string, value interface{}) (string, error) { var output string // Values may come in by pointer for optionals, so make sure to dereferene. @@ -295,7 +295,10 @@ func primitiveToString(value interface{}) (string, error) { output = "false" } case reflect.String: - output = v.String() + if escape == nil { + return "", fmt.Errorf("no escape function provided") + } + output = escape(v.String()) default: return "", fmt.Errorf("unsupported type %s", reflect.TypeOf(value).String()) } diff --git a/pkg/runtime/styleparam_test.go b/pkg/runtime/styleparam_test.go index d908b59e2..72c2be2f4 100644 --- a/pkg/runtime/styleparam_test.go +++ b/pkg/runtime/styleparam_test.go @@ -14,14 +14,23 @@ package runtime import ( + "net/url" "testing" "github.com/stretchr/testify/assert" ) +func escapePassThrough(s string) string { + return s +} + func TestStyleParam(t *testing.T) { primitive := 5 + unescapedPrimitive := "foo=bar" + array := []int{3, 4, 5} + unescapedArray := []string{"test?", "Sm!th", "J+mes", "foo=bar"} + type TestObject struct { FirstName string `json:"firstName"` Role string `json:"role"` @@ -34,29 +43,66 @@ func TestStyleParam(t *testing.T) { dict["firstName"] = "Alex" dict["role"] = "admin" + unescapedObject := TestObject{ + FirstName: "Al=x", + Role: "adm;n", + } + // ---------------------------- Simple Style ------------------------------- - result, err := StyleParam("simple", false, "id", primitive) + result, err := StyleParam("simple", false, escapePassThrough, "id", primitive) assert.NoError(t, err) assert.EqualValues(t, "5", result) - result, err = StyleParam("simple", true, "id", primitive) + result, err = StyleParam("simple", true, escapePassThrough, "id", primitive) assert.NoError(t, err) assert.EqualValues(t, "5", result) - result, err = StyleParam("simple", false, "id", array) + result, err = StyleParam("simple", false, url.PathEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, "foo=bar", result) + + result, err = StyleParam("simple", true, url.PathEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, "foo=bar", result) + + result, err = StyleParam("simple", false, url.QueryEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, "foo%3Dbar", result) + + result, err = StyleParam("simple", true, url.QueryEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, "foo%3Dbar", result) + + result, err = StyleParam("simple", false, escapePassThrough, "id", array) assert.NoError(t, err) assert.EqualValues(t, "3,4,5", result) - result, err = StyleParam("simple", true, "id", array) + result, err = StyleParam("simple", true, escapePassThrough, "id", array) assert.NoError(t, err) assert.EqualValues(t, "3,4,5", result) - result, err = StyleParam("simple", false, "id", object) + result, err = StyleParam("simple", false, url.PathEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "test%3F,Sm%21th,J+mes,foo=bar", result) + + result, err = StyleParam("simple", true, url.PathEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "test%3F,Sm%21th,J+mes,foo=bar", result) + + result, err = StyleParam("simple", false, url.QueryEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "test%3F,Sm%21th,J%2Bmes,foo%3Dbar", result) + + result, err = StyleParam("simple", true, url.QueryEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "test%3F,Sm%21th,J%2Bmes,foo%3Dbar", result) + + result, err = StyleParam("simple", false, escapePassThrough, "id", object) assert.NoError(t, err) assert.EqualValues(t, "firstName,Alex,role,admin", result) - result, err = StyleParam("simple", true, "id", object) + result, err = StyleParam("simple", true, escapePassThrough, "id", object) assert.NoError(t, err) assert.EqualValues(t, "firstName=Alex,role=admin", result) @@ -67,30 +113,77 @@ func TestStyleParam(t *testing.T) { result, err = StyleParam("simple", true, "id", dict) assert.NoError(t, err) assert.EqualValues(t, "firstName=Alex,role=admin", result) + result, err = StyleParam("simple", false, url.PathEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, "firstName,Al=x,role,adm%3Bn", result) + + result, err = StyleParam("simple", true, url.PathEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, "firstName=Al=x,role=adm%3Bn", result) + + result, err = StyleParam("simple", false, url.QueryEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, "firstName,Al%3Dx,role,adm%3Bn", result) + + result, err = StyleParam("simple", true, url.QueryEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, "firstName=Al%3Dx,role=adm%3Bn", result) // ----------------------------- Label Style ------------------------------- - result, err = StyleParam("label", false, "id", primitive) + result, err = StyleParam("label", false, escapePassThrough, "id", primitive) assert.NoError(t, err) assert.EqualValues(t, ".5", result) - result, err = StyleParam("label", true, "id", primitive) + result, err = StyleParam("label", true, escapePassThrough, "id", primitive) assert.NoError(t, err) assert.EqualValues(t, ".5", result) - result, err = StyleParam("label", false, "id", array) + result, err = StyleParam("label", false, url.PathEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, ".foo=bar", result) + + result, err = StyleParam("label", true, url.PathEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, ".foo=bar", result) + + result, err = StyleParam("label", false, url.QueryEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, ".foo%3Dbar", result) + + result, err = StyleParam("label", true, url.QueryEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, ".foo%3Dbar", result) + + result, err = StyleParam("label", false, escapePassThrough, "id", array) assert.NoError(t, err) assert.EqualValues(t, ".3,4,5", result) - result, err = StyleParam("label", true, "id", array) + result, err = StyleParam("label", true, escapePassThrough, "id", array) assert.NoError(t, err) assert.EqualValues(t, ".3.4.5", result) - result, err = StyleParam("label", false, "id", object) + result, err = StyleParam("label", false, url.PathEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, ".test%3F,Sm%21th,J+mes,foo=bar", result) + + result, err = StyleParam("label", true, url.PathEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, ".test%3F.Sm%21th.J+mes.foo=bar", result) + + result, err = StyleParam("label", false, url.QueryEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, ".test%3F,Sm%21th,J%2Bmes,foo%3Dbar", result) + + result, err = StyleParam("label", true, url.QueryEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, ".test%3F.Sm%21th.J%2Bmes.foo%3Dbar", result) + + result, err = StyleParam("label", false, escapePassThrough, "id", object) assert.NoError(t, err) assert.EqualValues(t, ".firstName,Alex,role,admin", result) - result, err = StyleParam("label", true, "id", object) + result, err = StyleParam("label", true, escapePassThrough, "id", object) assert.NoError(t, err) assert.EqualValues(t, ".firstName=Alex.role=admin", result) @@ -101,30 +194,77 @@ func TestStyleParam(t *testing.T) { result, err = StyleParam("label", true, "id", dict) assert.NoError(t, err) assert.EqualValues(t, ".firstName=Alex.role=admin", result) + result, err = StyleParam("label", false, url.PathEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, ".firstName,Al=x,role,adm%3Bn", result) + + result, err = StyleParam("label", true, url.PathEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, ".firstName=Al=x.role=adm%3Bn", result) + + result, err = StyleParam("label", false, url.QueryEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, ".firstName,Al%3Dx,role,adm%3Bn", result) + + result, err = StyleParam("label", true, url.QueryEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, ".firstName=Al%3Dx.role=adm%3Bn", result) // ----------------------------- Matrix Style ------------------------------ - result, err = StyleParam("matrix", false, "id", primitive) + result, err = StyleParam("matrix", false, escapePassThrough, "id", primitive) assert.NoError(t, err) assert.EqualValues(t, ";id=5", result) - result, err = StyleParam("matrix", true, "id", primitive) + result, err = StyleParam("matrix", true, escapePassThrough, "id", primitive) assert.NoError(t, err) assert.EqualValues(t, ";id=5", result) - result, err = StyleParam("matrix", false, "id", array) + result, err = StyleParam("matrix", false, url.PathEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, ";id=foo=bar", result) + + result, err = StyleParam("matrix", true, url.PathEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, ";id=foo=bar", result) + + result, err = StyleParam("matrix", false, url.QueryEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, ";id=foo%3Dbar", result) + + result, err = StyleParam("matrix", true, url.QueryEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, ";id=foo%3Dbar", result) + + result, err = StyleParam("matrix", false, escapePassThrough, "id", array) assert.NoError(t, err) assert.EqualValues(t, ";id=3,4,5", result) - result, err = StyleParam("matrix", true, "id", array) + result, err = StyleParam("matrix", true, escapePassThrough, "id", array) assert.NoError(t, err) assert.EqualValues(t, ";id=3;id=4;id=5", result) - result, err = StyleParam("matrix", false, "id", object) + result, err = StyleParam("matrix", false, url.PathEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, ";id=test%3F,Sm%21th,J+mes,foo=bar", result) + + result, err = StyleParam("matrix", true, url.PathEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, ";id=test%3F;id=Sm%21th;id=J+mes;id=foo=bar", result) + + result, err = StyleParam("matrix", false, url.QueryEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, ";id=test%3F,Sm%21th,J%2Bmes,foo%3Dbar", result) + + result, err = StyleParam("matrix", true, url.QueryEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, ";id=test%3F;id=Sm%21th;id=J%2Bmes;id=foo%3Dbar", result) + + result, err = StyleParam("matrix", false, escapePassThrough, "id", object) assert.NoError(t, err) assert.EqualValues(t, ";id=firstName,Alex,role,admin", result) - result, err = StyleParam("matrix", true, "id", object) + result, err = StyleParam("matrix", true, escapePassThrough, "id", object) assert.NoError(t, err) assert.EqualValues(t, ";firstName=Alex;role=admin", result) @@ -135,29 +275,76 @@ func TestStyleParam(t *testing.T) { result, err = StyleParam("matrix", true, "id", dict) assert.NoError(t, err) assert.EqualValues(t, ";firstName=Alex;role=admin", result) + result, err = StyleParam("matrix", false, url.PathEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, ";id=firstName,Al=x,role,adm%3Bn", result) + + result, err = StyleParam("matrix", true, url.PathEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, ";firstName=Al=x;role=adm%3Bn", result) + + result, err = StyleParam("matrix", false, url.QueryEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, ";id=firstName,Al%3Dx,role,adm%3Bn", result) + + result, err = StyleParam("matrix", true, url.QueryEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, ";firstName=Al%3Dx;role=adm%3Bn", result) // ------------------------------ Form Style ------------------------------- - result, err = StyleParam("form", false, "id", primitive) + result, err = StyleParam("form", false, escapePassThrough, "id", primitive) assert.NoError(t, err) assert.EqualValues(t, "id=5", result) - result, err = StyleParam("form", true, "id", primitive) + result, err = StyleParam("form", true, escapePassThrough, "id", primitive) assert.NoError(t, err) assert.EqualValues(t, "id=5", result) - result, err = StyleParam("form", false, "id", array) + result, err = StyleParam("form", false, url.PathEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, "id=foo=bar", result) + + result, err = StyleParam("form", true, url.PathEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, "id=foo=bar", result) + + result, err = StyleParam("form", false, url.QueryEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, "id=foo%3Dbar", result) + + result, err = StyleParam("form", true, url.QueryEscape, "id", unescapedPrimitive) + assert.NoError(t, err) + assert.EqualValues(t, "id=foo%3Dbar", result) + + result, err = StyleParam("form", false, escapePassThrough, "id", array) assert.NoError(t, err) assert.EqualValues(t, "id=3,4,5", result) - result, err = StyleParam("form", true, "id", array) + result, err = StyleParam("form", true, escapePassThrough, "id", array) assert.NoError(t, err) assert.EqualValues(t, "id=3&id=4&id=5", result) - result, err = StyleParam("form", false, "id", object) + result, err = StyleParam("form", false, url.PathEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "id=test%3F,Sm%21th,J+mes,foo=bar", result) + + result, err = StyleParam("form", true, url.PathEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "id=test%3F&id=Sm%21th&id=J+mes&id=foo=bar", result) + + result, err = StyleParam("form", false, url.QueryEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "id=test%3F,Sm%21th,J%2Bmes,foo%3Dbar", result) + + result, err = StyleParam("form", true, url.QueryEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "id=test%3F&id=Sm%21th&id=J%2Bmes&id=foo%3Dbar", result) + + result, err = StyleParam("form", false, escapePassThrough, "id", object) assert.NoError(t, err) assert.EqualValues(t, "id=firstName,Alex,role,admin", result) - result, err = StyleParam("form", true, "id", object) + result, err = StyleParam("form", true, escapePassThrough, "id", object) assert.NoError(t, err) assert.EqualValues(t, "firstName=Alex&role=admin", result) @@ -168,27 +355,58 @@ func TestStyleParam(t *testing.T) { result, err = StyleParam("form", true, "id", dict) assert.NoError(t, err) assert.EqualValues(t, "firstName=Alex&role=admin", result) + result, err = StyleParam("form", false, url.PathEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, "id=firstName,Al=x,role,adm%3Bn", result) + + result, err = StyleParam("form", true, url.PathEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, "firstName=Al=x&role=adm%3Bn", result) + + result, err = StyleParam("form", false, url.QueryEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, "id=firstName,Al%3Dx,role,adm%3Bn", result) + + result, err = StyleParam("form", true, url.QueryEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, "firstName=Al%3Dx&role=adm%3Bn", result) // ------------------------ spaceDelimited Style -------------------------- - result, err = StyleParam("spaceDelimited", false, "id", primitive) + _, err = StyleParam("spaceDelimited", false, escapePassThrough, "id", primitive) assert.Error(t, err) - result, err = StyleParam("spaceDelimited", true, "id", primitive) + _, err = StyleParam("spaceDelimited", true, escapePassThrough, "id", primitive) assert.Error(t, err) - result, err = StyleParam("spaceDelimited", false, "id", array) + result, err = StyleParam("spaceDelimited", false, escapePassThrough, "id", array) assert.NoError(t, err) assert.EqualValues(t, "id=3 4 5", result) - result, err = StyleParam("spaceDelimited", true, "id", array) + result, err = StyleParam("spaceDelimited", true, escapePassThrough, "id", array) assert.NoError(t, err) assert.EqualValues(t, "id=3&id=4&id=5", result) - result, err = StyleParam("spaceDelimited", false, "id", object) + result, err = StyleParam("spaceDelimited", false, url.PathEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "id=test%3F Sm%21th J+mes foo=bar", result) + + result, err = StyleParam("spaceDelimited", true, url.PathEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "id=test%3F&id=Sm%21th&id=J+mes&id=foo=bar", result) + + result, err = StyleParam("spaceDelimited", false, url.QueryEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "id=test%3F Sm%21th J%2Bmes foo%3Dbar", result) + + result, err = StyleParam("spaceDelimited", true, url.QueryEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "id=test%3F&id=Sm%21th&id=J%2Bmes&id=foo%3Dbar", result) + + _, err = StyleParam("spaceDelimited", false, escapePassThrough, "id", object) assert.Error(t, err) - result, err = StyleParam("spaceDelimited", true, "id", object) + _, err = StyleParam("spaceDelimited", true, escapePassThrough, "id", object) assert.Error(t, err) result, err = StyleParam("spaceDelimited", false, "id", dict) @@ -198,24 +416,40 @@ func TestStyleParam(t *testing.T) { assert.Error(t, err) // ------------------------- pipeDelimited Style -------------------------- - result, err = StyleParam("pipeDelimited", false, "id", primitive) + _, err = StyleParam("pipeDelimited", false, escapePassThrough, "id", primitive) assert.Error(t, err) - result, err = StyleParam("pipeDelimited", true, "id", primitive) + _, err = StyleParam("pipeDelimited", true, escapePassThrough, "id", primitive) assert.Error(t, err) - result, err = StyleParam("pipeDelimited", false, "id", array) + result, err = StyleParam("pipeDelimited", false, escapePassThrough, "id", array) assert.NoError(t, err) assert.EqualValues(t, "id=3|4|5", result) - result, err = StyleParam("pipeDelimited", true, "id", array) + result, err = StyleParam("pipeDelimited", true, escapePassThrough, "id", array) assert.NoError(t, err) assert.EqualValues(t, "id=3&id=4&id=5", result) - result, err = StyleParam("pipeDelimited", false, "id", object) + result, err = StyleParam("pipeDelimited", false, url.PathEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "id=test%3F|Sm%21th|J+mes|foo=bar", result) + + result, err = StyleParam("pipeDelimited", true, url.PathEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "id=test%3F&id=Sm%21th&id=J+mes&id=foo=bar", result) + + result, err = StyleParam("pipeDelimited", false, url.QueryEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "id=test%3F|Sm%21th|J%2Bmes|foo%3Dbar", result) + + result, err = StyleParam("pipeDelimited", true, url.QueryEscape, "id", unescapedArray) + assert.NoError(t, err) + assert.EqualValues(t, "id=test%3F&id=Sm%21th&id=J%2Bmes&id=foo%3Dbar", result) + + _, err = StyleParam("pipeDelimited", false, escapePassThrough, "id", object) assert.Error(t, err) - result, err = StyleParam("pipeDelimited", true, "id", object) + _, err = StyleParam("pipeDelimited", true, escapePassThrough, "id", object) assert.Error(t, err) result, err = StyleParam("pipeDelimited", false, "id", dict) @@ -225,43 +459,50 @@ func TestStyleParam(t *testing.T) { assert.Error(t, err) // --------------------------- deepObject Style --------------------------- - result, err = StyleParam("deepObject", false, "id", primitive) + _, err = StyleParam("deepObject", false, escapePassThrough, "id", primitive) assert.Error(t, err) - result, err = StyleParam("deepObject", true, "id", primitive) + _, err = StyleParam("deepObject", true, escapePassThrough, "id", primitive) assert.Error(t, err) - result, err = StyleParam("deepObject", false, "id", array) + _, err = StyleParam("deepObject", false, escapePassThrough, "id", array) assert.Error(t, err) - result, err = StyleParam("deepObject", true, "id", array) + _, err = StyleParam("deepObject", true, escapePassThrough, "id", array) assert.Error(t, err) - result, err = StyleParam("deepObject", false, "id", object) + _, err = StyleParam("deepObject", false, escapePassThrough, "id", object) assert.Error(t, err) - result, err = StyleParam("deepObject", true, "id", object) + result, err = StyleParam("deepObject", true, escapePassThrough, "id", object) assert.NoError(t, err) assert.EqualValues(t, "id[firstName]=Alex&id[role]=admin", result) result, err = StyleParam("deepObject", true, "id", dict) assert.NoError(t, err) assert.EqualValues(t, "id[firstName]=Alex&id[role]=admin", result) + result, err = StyleParam("deepObject", true, url.PathEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, "id[firstName]=Al=x&id[role]=adm%3Bn", result) + + result, err = StyleParam("deepObject", true, url.QueryEscape, "id", unescapedObject) + assert.NoError(t, err) + assert.EqualValues(t, "id[firstName]=Al%3Dx&id[role]=adm%3Bn", result) // Misc tests // Test type aliases type StrType string - result, err = StyleParam("simple", false, "foo", StrType("test")) + result, err = StyleParam("simple", false, escapePassThrough, "foo", StrType("test")) assert.NoError(t, err) assert.EqualValues(t, "test", result) type IntType int32 - result, err = StyleParam("simple", false, "foo", IntType(7)) + result, err = StyleParam("simple", false, escapePassThrough, "foo", IntType(7)) assert.NoError(t, err) assert.EqualValues(t, "7", result) type FloatType float64 - result, err = StyleParam("simple", false, "foo", FloatType(7.5)) + result, err = StyleParam("simple", false, escapePassThrough, "foo", FloatType(7.5)) assert.NoError(t, err) assert.EqualValues(t, "7.5", result) @@ -276,13 +517,13 @@ func TestStyleParam(t *testing.T) { FirstName: &name, Role: &role, } - result, err = StyleParam("simple", false, "id", object2) + result, err = StyleParam("simple", false, escapePassThrough, "id", object2) assert.NoError(t, err) assert.EqualValues(t, "firstName,Alex,role,admin", result) // Nullable fields need to be excluded when null object2.Role = nil - result, err = StyleParam("simple", false, "id", object2) + result, err = StyleParam("simple", false, escapePassThrough, "id", object2) assert.NoError(t, err) assert.EqualValues(t, "firstName,Alex", result) } diff --git a/pkg/types/date_test.go b/pkg/types/date_test.go index 1369b1c4f..18bfd4b98 100644 --- a/pkg/types/date_test.go +++ b/pkg/types/date_test.go @@ -11,7 +11,7 @@ import ( func TestDate_MarshalJSON(t *testing.T) { testDate := time.Date(2019, 4, 1, 0, 0, 0, 0, time.UTC) b := struct { - DateField Date `json:"date"` + DateField Date `json:"date"` }{ DateField: Date{testDate}, } @@ -24,7 +24,7 @@ func TestDate_UnmarshalJSON(t *testing.T) { testDate := time.Date(2019, 4, 1, 0, 0, 0, 0, time.UTC) jsonStr := `{"date":"2019-04-01"}` b := struct { - DateField Date `json:"date"` + DateField Date `json:"date"` }{} err := json.Unmarshal([]byte(jsonStr), &b) assert.NoError(t, err) diff --git a/pkg/util/loader.go b/pkg/util/loader.go index 318342a6d..dbc814365 100644 --- a/pkg/util/loader.go +++ b/pkg/util/loader.go @@ -1,16 +1,19 @@ package util import ( + "crypto/tls" "encoding/json" "fmt" "io/ioutil" + "net/http" + "net/url" "path/filepath" "strings" "github.com/getkin/kin-openapi/openapi3" ) -func LoadSwagger(filePath string) (*openapi3.Swagger, error) { +func LoadSwagger(filePath string, allowRefs bool, insecure bool, clearRefs bool) (*openapi3.Swagger, error) { data, err := ioutil.ReadFile(filePath) if err != nil { return nil, err @@ -21,7 +24,12 @@ func LoadSwagger(filePath string) (*openapi3.Swagger, error) { ext = strings.ToLower(ext) switch ext { case ".yaml", ".yml": - swagger, err = openapi3.NewSwaggerLoader().LoadSwaggerFromData(data) + sl := openapi3.NewSwaggerLoader(openapi3.WithClearResolvedRefs(clearRefs)) + sl.IsExternalRefsAllowed = allowRefs + if insecure { + sl.LoadSwaggerFromURIFunc = insecureReadUrl + } + swagger, err = sl.LoadSwaggerFromFile(filePath) case ".json": swagger = &openapi3.Swagger{} err = json.Unmarshal(data, swagger) @@ -33,3 +41,58 @@ func LoadSwagger(filePath string) (*openapi3.Swagger, error) { } return swagger, nil } + +func LoadSwaggerFromURL(url *url.URL, allowRefs, insecure bool) (*openapi3.Swagger, error) { + var err error + var swagger *openapi3.Swagger + + ext := filepath.Ext(url.Path) + ext = strings.ToLower(ext) + switch ext { + case ".yaml", ".yml": + sl := openapi3.NewSwaggerLoader() + sl.IsExternalRefsAllowed = allowRefs + if insecure { + sl.LoadSwaggerFromURIFunc = insecureReadUrl + } + swagger, err = sl.LoadSwaggerFromURI(url) + + // enable support for loading remote JSON files later + //case ".json": + // swagger = &openapi3.Swagger{} + // err = json.Unmarshal(data, swagger) + default: + return nil, fmt.Errorf("%s is not a supported extension, use .yaml, .yml when specifying remote schemas", ext) + } + if err != nil { + return nil, err + } + return swagger, nil +} + +func insecureReadUrl(sl *openapi3.SwaggerLoader, location *url.URL) (*openapi3.Swagger, error) { + if location.Scheme != "" && location.Host != "" { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + cl := &http.Client{Transport: tr} + resp, err := cl.Get(location.String()) + if err != nil { + return nil, err + } + data, err := ioutil.ReadAll(resp.Body) + defer resp.Body.Close() + if err != nil { + return nil, err + } + return sl.LoadSwaggerFromDataWithPath(data, location) + } + if location.Scheme != "" || location.Host != "" || location.RawQuery != "" { + return nil, fmt.Errorf("Unsupported URI: '%s'", location.String()) + } + data, err := ioutil.ReadFile(location.Path) + if err != nil { + return nil, err + } + return sl.LoadSwaggerFromDataWithPath(data, location) +}