diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eeb0208241..b21f3f88ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,22 +1,24 @@ -name: Build project -on: [ push, pull_request ] - +name: CI +on: + push: {} + pull_request: {} + workflow_dispatch: {} permissions: contents: read - jobs: build: - name: Build + uses: oapi-codegen/actions/.github/workflows/ci.yml@75566d848d25021f137594c947f26171094fb511 # v0.5.0 + with: + lint_versions: '["1.25"]' + + build-binaries: runs-on: ubuntu-latest strategy: - fail-fast: false - # perform matrix testing to give us an earlier insight into issues with different versions of supported major versions of Go + fail-fast: true matrix: version: - - "1.22" - - "1.23" - - "1.24" - - "1.25" + - "stable" + - "oldstable" steps: - name: Check out source code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -26,25 +28,8 @@ jobs: with: go-version: ${{ matrix.version }} - - name: Test - run: make test + - name: Build + run: go build ./cmd/oapi-codegen env: # A combination of our GitHub Actions setup, with the Go toolchain, leads to inconsistencies in calling `go env`, in particular with Go 1.21, where having (the default) `GOTOOLCHAIN=auto` results in build failures GOTOOLCHAIN: local - - - name: Build - run: go build ./cmd/oapi-codegen - - results: - if: ${{ always() }} - runs-on: ubuntu-latest - name: Check build results - needs: [build] - steps: - - run: | - result="${{ needs.build.result }}" - if [[ $result == "success" || $result == "skipped" ]]; then - exit 0 - else - exit 1 - fi diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml deleted file mode 100644 index 4a0e5db377..0000000000 --- a/.github/workflows/generate.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Ensure generated files are up-to-date -on: [ push, pull_request ] - -permissions: - contents: read - -jobs: - build: - name: Build - runs-on: ubuntu-latest - strategy: - fail-fast: false - # perform matrix testing to give us an earlier insight into issues with different versions of supported major versions of Go - matrix: - version: - - "1.22" - - "1.23" - - "1.24" - - "1.25" - steps: - - name: Check out source code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Set up Go - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 - with: - go-version: ${{ matrix.version }} - - - name: Run `make generate` - run: make generate - env: - # A combination of our GitHub Actions setup, with the Go toolchain, leads to inconsistencies in calling `go env`, in particular with Go 1.21, where having (the default) `GOTOOLCHAIN=auto` results in build failures - GOTOOLCHAIN: local - - - name: Check for no untracked files - run: git status && git diff-index --exit-code -p HEAD -- - - results: - if: ${{ always() }} - runs-on: ubuntu-latest - name: Check generation results - needs: [build] - steps: - - run: | - result="${{ needs.build.result }}" - if [[ $result == "success" || $result == "skipped" ]]; then - exit 0 - else - exit 1 - fi diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 8246442b1e..0000000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Lint project -on: [push, pull_request] - -permissions: - contents: read - -jobs: - build: - name: Build - runs-on: ubuntu-latest - strategy: - fail-fast: false - # perform matrix testing to give us an earlier insight into issues with different versions of supported major versions of Go - matrix: - version: - - "1.22" - - "1.23" - - "1.24" - - "1.25" - steps: - - name: Check out source code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Set up Go - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 - with: - go-version: ${{ matrix.version }} - - - name: Run `make lint-ci` - run: make lint-ci - env: - # A combination of our GitHub Actions setup, with the Go toolchain, leads to inconsistencies in calling `go env`, in particular with Go 1.21, where having (the default) `GOTOOLCHAIN=auto` results in build failures - GOTOOLCHAIN: local - - results: - if: ${{ always() }} - runs-on: ubuntu-latest - name: Check linting results - needs: [build] - steps: - - run: | - result="${{ needs.build.result }}" - if [[ $result == "success" || $result == "skipped" ]]; then - exit 0 - else - exit 1 - fi diff --git a/.github/workflows/tidy.yml b/.github/workflows/tidy.yml deleted file mode 100644 index 4d5e66a992..0000000000 --- a/.github/workflows/tidy.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Ensure `go mod tidy` has been run -on: [ push, pull_request ] - -permissions: - contents: read - -jobs: - build: - name: Build - runs-on: ubuntu-latest - strategy: - fail-fast: false - # perform matrix testing to give us an earlier insight into issues with different versions of supported major versions of Go - matrix: - version: - - "1.22" - - "1.23" - - "1.24" - - "1.25" - steps: - - name: Check out source code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Set up Go - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 - with: - go-version: ${{ matrix.version }} - - - name: Install `tidied` - run: go install gitlab.com/jamietanna/tidied@latest - - - name: Check for no untracked files - run: make tidy-ci - env: - # A combination of our GitHub Actions setup, with the Go toolchain, leads to inconsistencies in calling `go env`, in particular with Go 1.21, where having (the default) `GOTOOLCHAIN=auto` results in build failures - GOTOOLCHAIN: local - - results: - if: ${{ always() }} - runs-on: ubuntu-latest - name: Check tidy results - needs: [build] - steps: - - run: | - result="${{ needs.build.result }}" - if [[ $result == "success" || $result == "skipped" ]]; then - exit 0 - else - exit 1 - fi diff --git a/README.md b/README.md index 6fc3846c97..af2c0ea7ae 100644 --- a/README.md +++ b/README.md @@ -421,6 +421,9 @@ Server generate flag to enable code generation +Required Go Version + + Example usage @@ -435,6 +438,9 @@ Example usage chi-server +1.22+ + + For a Chi server, you will want a configuration file such as: @@ -463,6 +469,9 @@ To implement this, check out [the Chi docs](#impl-chi). echo-server +1.22+ + + For an Echo server, you will want a configuration file such as: @@ -489,7 +498,9 @@ To implement this, check out [the Echo docs](#impl-echo). fiber-server - + +1.24+ + For a Fiber server, you will want a configuration file such as: @@ -519,6 +530,9 @@ To implement this, check out [the Fiber docs](#impl-fiber). gin-server +1.22+ + + For a Gin server, you will want a configuration file such as: @@ -546,7 +560,9 @@ To implement this, check out [the Gin docs](#impl-gin). gorilla-server - + +1.22+ + For a gorilla/mux server, you will want a configuration file such as: @@ -574,7 +590,9 @@ To implement this, check out [the gorilla/mux docs](#impl-gorillamux). iris-server - + +1.22+ + For a Iris server, you will want a configuration file such as: @@ -602,7 +620,9 @@ To implement this, check out [the Iris docs](#impl-iris). std-http-server - + +1.22+ + To use purely `net/http` (for Go 1.22+), you will want a configuration file such as: @@ -2487,17 +2507,6 @@ Explicitly order struct fields -`x-go-embedding` - - - -Embed referenced schema(s) into the generated struct when using `allOf` - - - - - - `x-oapi-codegen-only-honour-go-name` @@ -3165,53 +3174,6 @@ type ClientWithExtension struct { You can see this in more detail in [the example code](examples/extensions/xorder/). -### `x-go-embedding` - embed referenced schema(s) into the generated struct when using `allOf` - -When composing schemas with `allOf`, setting `x-go-embedding: true` on the composed type causes referenced schema(s) to be embedded in the generated Go struct. This results in Go field promotion for the embedded type(s). - -We can see this at play with the following schemas: - -```yaml -openapi: "3.0.1" -info: - version: 1.0.0 - title: x-go-embedding -components: - schemas: - response.Placeholder: - x-go-embedding: true - type: object - allOf: - - $ref: "#/components/schemas/Response" - - type: object - properties: - hello: - type: string - - Response: - x-go-name: Response - type: object - properties: - status: - type: integer -``` - -This will produce models similar to: - -```go -// Response defines model for Response. -type Response struct { - Status *int `json:"status,omitempty"` -} - -// ResponsePlaceholder defines model for response.Placeholder. -// Note the embedded Response, due to x-go-embedding: true -type ResponsePlaceholder struct { - Response - Hello *string `json:"hello,omitempty"` -} -``` - ### `x-oapi-codegen-only-honour-go-name` - only honour the `x-go-name` when generating field names @@ -4534,7 +4496,7 @@ Please consider sponsoring us through GitHub Sponsors either [on the organisatio See [this blog post from Tidelift](https://blog.tidelift.com/paying-maintainers-the-howto) for more details on how to talk to your company about sponsoring maintainers of (Open Source) projects you depend on. -In addition, we are also generously sponsored by the following folks, each of whom provide sponsorship for 1 hour of work a month: +We are also generously sponsored by the following folks, each of whom provide sponsorship for 1 hour of work a month:

@@ -4546,30 +4508,10 @@ In addition, we are also generously sponsored by the following folks, each of wh

-

- - - - - Speakeasy logo - - -

-

Cybozu logo

-

- - - - - Livepeer logo - - -

- (Note that the order of appearance the order in which sponsorship was received) diff --git a/cmd/oapi-codegen/oapi-codegen.go b/cmd/oapi-codegen/oapi-codegen.go index f0efc5f3a9..c5bd352251 100644 --- a/cmd/oapi-codegen/oapi-codegen.go +++ b/cmd/oapi-codegen/oapi-codegen.go @@ -29,7 +29,7 @@ import ( "github.com/livesession/oapi-codegen/v2/pkg/util" ) -func errExit(format string, args ...interface{}) { +func errExit(format string, args ...any) { if !strings.HasSuffix(format, "\n") { format = format + "\n" } @@ -272,12 +272,13 @@ func main() { } if warnings := opts.Generate.Warnings(); len(warnings) > 0 { - out := "WARNING: A number of warning(s) were returned when validating the GenerateOptions:" + var out strings.Builder + out.WriteString("WARNING: A number of warning(s) were returned when validating the GenerateOptions:") for k, v := range warnings { - out += "\n- " + k + ": " + v + out.WriteString("\n- " + k + ": " + v) } - _, _ = fmt.Fprint(os.Stderr, out) + _, _ = fmt.Fprint(os.Stderr, out.String()) } // If the user asked to output configuration, output it to stdout and exit diff --git a/configuration-schema.json b/configuration-schema.json index 0235e4c54f..4dd084a944 100644 --- a/configuration-schema.json +++ b/configuration-schema.json @@ -252,6 +252,30 @@ "type": "boolean", "description": "Allows disabling the generation of an 'optional pointer' for an optional field that is a container type (such as a slice or a map), which ends up requiring an additional, unnecessary, `... != nil` check. A field can set `x-go-type-skip-optional-pointer: false` to still require the optional pointer.", "default": false + }, + "resolve-type-name-collisions": { + "type": "boolean", + "description": "When set to true, automatically renames types that collide across different OpenAPI component sections (schemas, parameters, requestBodies, responses, headers) by appending a suffix based on the component section (e.g., 'Parameter', 'Response', 'RequestBody'). Without this, the codegen will error on duplicate type names, requiring manual resolution via x-go-name.", + "default": false + }, + "type-mapping": { + "type": "object", + "additionalProperties": false, + "description": "TypeMapping allows customizing OpenAPI type/format to Go type mappings. User-specified mappings are merged on top of the defaults, so you only need to specify the types you want to override.", + "properties": { + "integer": { + "$ref": "#/$defs/format-mapping" + }, + "number": { + "$ref": "#/$defs/format-mapping" + }, + "boolean": { + "$ref": "#/$defs/format-mapping" + }, + "string": { + "$ref": "#/$defs/format-mapping" + } + } } } }, @@ -289,5 +313,43 @@ "required": [ "package", "output" - ] + ], + "$defs": { + "simple-type-spec": { + "type": "object", + "additionalProperties": false, + "description": "Specifies a Go type and optional import path", + "properties": { + "type": { + "type": "string", + "description": "The Go type to use (e.g. \"int64\", \"time.Time\", \"github.com/shopspring/decimal.Decimal\")" + }, + "import": { + "type": "string", + "description": "The Go import path required for this type (e.g. \"time\", \"encoding/json\")" + } + }, + "required": [ + "type" + ] + }, + "format-mapping": { + "type": "object", + "additionalProperties": false, + "description": "Maps an OpenAPI type's formats to Go types", + "properties": { + "default": { + "$ref": "#/$defs/simple-type-spec", + "description": "The default Go type when no format is specified or the format is unrecognized" + }, + "formats": { + "type": "object", + "description": "Format-specific Go type overrides (e.g. \"int32\": {\"type\": \"int32\"}, \"double\": {\"type\": \"float64\"})", + "additionalProperties": { + "$ref": "#/$defs/simple-type-spec" + } + } + } + } + } } diff --git a/examples/authenticated-api/stdhttp/go.mod b/examples/authenticated-api/stdhttp/go.mod index 166b7d98c0..7be97cba4b 100644 --- a/examples/authenticated-api/stdhttp/go.mod +++ b/examples/authenticated-api/stdhttp/go.mod @@ -39,10 +39,10 @@ require ( github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/woodsbury/decimal128 v1.3.0 // indirect golang.org/x/crypto v0.22.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/sync v0.9.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect golang.org/x/text v0.20.0 // indirect - golang.org/x/tools v0.25.1 // indirect + golang.org/x/tools v0.30.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/examples/authenticated-api/stdhttp/go.sum b/examples/authenticated-api/stdhttp/go.sum index d38b743f8d..a6e130e447 100644 --- a/examples/authenticated-api/stdhttp/go.sum +++ b/examples/authenticated-api/stdhttp/go.sum @@ -37,6 +37,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= @@ -137,8 +139,8 @@ golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -151,15 +153,15 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -180,8 +182,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -202,8 +204,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.25.1 h1:YeIyhd0M7gStYR9jb2IFXVVT+QJhgXu1ZECOuRwofh4= -golang.org/x/tools v0.25.1/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/examples/extensions/xomitzero/go.mod b/examples/extensions/xomitzero/go.mod index 9ffad65ccd..9109cbb48e 100644 --- a/examples/extensions/xomitzero/go.mod +++ b/examples/extensions/xomitzero/go.mod @@ -26,10 +26,10 @@ require ( github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/woodsbury/decimal128 v1.3.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/sync v0.9.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect golang.org/x/text v0.20.0 // indirect - golang.org/x/tools v0.25.1 // indirect + golang.org/x/tools v0.30.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/examples/extensions/xomitzero/go.sum b/examples/extensions/xomitzero/go.sum index 2319ae885e..fdce2066b1 100644 --- a/examples/extensions/xomitzero/go.sum +++ b/examples/extensions/xomitzero/go.sum @@ -32,6 +32,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -95,8 +97,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -104,13 +106,13 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -125,8 +127,8 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -138,8 +140,8 @@ golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.25.1 h1:YeIyhd0M7gStYR9jb2IFXVVT+QJhgXu1ZECOuRwofh4= -golang.org/x/tools v0.25.1/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/examples/generate/serverurls/gen.go b/examples/generate/serverurls/gen.go index e217e7675e..cd3d34e923 100644 --- a/examples/generate/serverurls/gen.go +++ b/examples/generate/serverurls/gen.go @@ -9,25 +9,18 @@ import ( ) // ServerUrlDevelopmentServer defines the Server URL for Development server -const ServerUrlDevelopmentServer = "https://development.gigantic-server.com/v1" // ServerUrlDevelopmentServer1 defines the Server URL for Development server -const ServerUrlDevelopmentServer1 = "http://localhost:80" // ServerUrlDevelopmentServer2 defines the Server URL for Development server -const ServerUrlDevelopmentServer2 = "http://localhost:80" -// ServerUrlHttplocalhost443 defines the Server URL for -const ServerUrlHttplocalhost443 = "http://localhost:443" +// ServerUrlHttplocalhost443 defines the Server URL for http://localhost:443 // ServerUrlProductionServer defines the Server URL for Production server -const ServerUrlProductionServer = "https://api.gigantic-server.com/v1" // ServerUrlSomeLowercaseName defines the Server URL for some lowercase name -const ServerUrlSomeLowercaseName = "http://localhost:80" // ServerUrlStagingServer defines the Server URL for Staging server -const ServerUrlStagingServer = "https://staging.gigantic-server.com/v1" // ServerUrlTheProductionAPIServerBasePathVariable is the `basePath` variable for ServerUrlTheProductionAPIServer type ServerUrlTheProductionAPIServerBasePathVariable string diff --git a/examples/go.mod b/examples/go.mod index eb7d5aaa4b..6019c40e5a 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -8,15 +8,13 @@ require ( github.com/getkin/kin-openapi v0.133.0 github.com/gin-gonic/gin v1.10.0 github.com/go-chi/chi/v5 v5.0.10 - github.com/gofiber/fiber/v2 v2.52.4 - github.com/google/uuid v1.5.0 + github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.1 github.com/kataras/iris/v12 v12.2.6-0.20230908161203-24ba4e8933b9 github.com/labstack/echo/v4 v4.12.0 github.com/lestrrat-go/jwx v1.2.26 github.com/livesession/oapi-codegen/v2 v2.0.0-00010101000000-000000000000 github.com/oapi-codegen/echo-middleware v1.0.2 - github.com/oapi-codegen/fiber-middleware v1.0.2 github.com/oapi-codegen/gin-middleware v1.0.2 github.com/oapi-codegen/iris-middleware v1.0.5 github.com/oapi-codegen/nethttp-middleware v1.0.2 @@ -32,7 +30,7 @@ require ( github.com/CloudyKit/jet/v6 v6.2.0 // indirect github.com/Joker/jade v1.1.3 // indirect github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect - github.com/andybalholm/brotli v1.0.5 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/bytedance/sonic v1.11.6 // indirect @@ -64,7 +62,7 @@ require ( github.com/kataras/pio v0.0.12 // indirect github.com/kataras/sitemap v0.0.6 // indirect github.com/kataras/tunnel v0.0.4 // indirect - github.com/klauspost/compress v1.17.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/leodido/go-urn v1.4.0 // indirect @@ -77,7 +75,6 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect github.com/microcosm-cc/bluemonday v1.0.25 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -88,7 +85,6 @@ require ( github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rivo/uniseg v0.4.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/schollz/closestmatch v2.1.0+incompatible // indirect github.com/sirupsen/logrus v1.8.1 // indirect @@ -99,23 +95,21 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.51.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect - github.com/valyala/tcplisten v1.0.0 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/woodsbury/decimal128 v1.3.0 // indirect github.com/yosssi/ace v0.0.5 // indirect golang.org/x/arch v0.8.0 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.29.0 // indirect - golang.org/x/sync v0.9.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.20.0 // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.25.1 // indirect + golang.org/x/tools v0.30.0 // indirect google.golang.org/protobuf v1.34.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/examples/go.sum b/examples/go.sum index 97e7e8ae43..d7a256ee0e 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -13,8 +13,8 @@ github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= -github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= @@ -79,8 +79,6 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM= -github.com/gofiber/fiber/v2 v2.52.4/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -106,8 +104,8 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= @@ -139,8 +137,8 @@ github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -180,8 +178,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg= github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= @@ -199,8 +195,6 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oapi-codegen/echo-middleware v1.0.2 h1:oNBqiE7jd/9bfGNk/bpbX2nqWrtPc+LL4Boya8Wl81U= github.com/oapi-codegen/echo-middleware v1.0.2/go.mod h1:5J6MFcGqrpWLXpbKGZtRPZViLIHyyyUHlkqg6dT2R4E= -github.com/oapi-codegen/fiber-middleware v1.0.2 h1:f4KPdjyRTYh2GyAv9wsDP+Q9akOND17wuMSbmMwDkJI= -github.com/oapi-codegen/fiber-middleware v1.0.2/go.mod h1:+lGj+802Ajp/+fQG9d8t1SuYP8r7lnOc6wnOwwRArYg= github.com/oapi-codegen/gin-middleware v1.0.2 h1:/H99UzvHQAUxXK8pzdcGAZgjCVeXdFDAUUWaJT0k0eI= github.com/oapi-codegen/gin-middleware v1.0.2/go.mod h1:2HJDQjH8jzK2/k/VKcWl+/T41H7ai2bKa6dN3AA2GpA= github.com/oapi-codegen/iris-middleware v1.0.5 h1:eO33pCvapaf1Xa0esEP0PYcdqPZSeq1eze4mamhT5hU= @@ -235,9 +229,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -284,12 +275,8 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= -github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= -github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= @@ -323,8 +310,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= @@ -332,8 +319,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -347,16 +334,16 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -379,8 +366,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -391,8 +378,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -402,8 +389,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.25.1 h1:YeIyhd0M7gStYR9jb2IFXVVT+QJhgXu1ZECOuRwofh4= -golang.org/x/tools v0.25.1/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/examples/minimal-server/fiber/Makefile b/examples/minimal-server/fiber/Makefile new file mode 100644 index 0000000000..bb37d63394 --- /dev/null +++ b/examples/minimal-server/fiber/Makefile @@ -0,0 +1,36 @@ +SHELL:=/bin/bash + +YELLOW := \e[0;33m +RESET := \e[0;0m + +GOVER := $(shell go env GOVERSION) +GOMINOR := $(shell bash -c "cut -f1 -d' ' <<< \"$(GOVER)\" | cut -f2 -d.") + +define execute-if-go-124 +@{ \ +if [[ 24 -le $(GOMINOR) ]]; then \ + $1; \ +else \ + echo -e "$(YELLOW)Skipping task as you're running Go v1.$(GOMINOR).x which is < Go 1.24, which this module requires$(RESET)"; \ +fi \ +} +endef + +lint: + $(call execute-if-go-124,$(GOBIN)/golangci-lint run ./...) + +lint-ci: + + $(call execute-if-go-124,$(GOBIN)/golangci-lint run ./... --output.text.path=stdout --timeout=5m) + +generate: + $(call execute-if-go-124,go generate ./...) + +test: + $(call execute-if-go-124,go test -cover ./...) + +tidy: + $(call execute-if-go-124,go mod tidy) + +tidy-ci: + $(call execute-if-go-124,tidied -verbose) diff --git a/examples/minimal-server/fiber/go.mod b/examples/minimal-server/fiber/go.mod new file mode 100644 index 0000000000..721afc5e52 --- /dev/null +++ b/examples/minimal-server/fiber/go.mod @@ -0,0 +1,44 @@ +module github.com/livesession/oapi-codegen/v2/examples/minimal-server/fiber + +go 1.24.0 + +replace github.com/livesession/oapi-codegen/v2 => ../../../ + +tool github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen + +require github.com/gofiber/fiber/v2 v2.52.11 + +require ( + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect + github.com/getkin/kin-openapi v0.133.0 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/livesession/oapi-codegen/v2 v2.0.0-00010101000000-000000000000 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect + github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect + github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/speakeasy-api/jsonpath v0.6.0 // indirect + github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.51.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect + github.com/woodsbury/decimal128 v1.3.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/tools v0.30.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/examples/minimal-server/fiber/go.sum b/examples/minimal-server/fiber/go.sum new file mode 100644 index 0000000000..e2954b1efc --- /dev/null +++ b/examples/minimal-server/fiber/go.sum @@ -0,0 +1,198 @@ +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +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/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= +github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= +github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ= +github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= +github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/gofiber/fiber/v2 v2.52.11 h1:5f4yzKLcBcF8ha1GQTWB+mpblWz3Vz6nSAbTL31HkWs= +github.com/gofiber/fiber/v2 v2.52.11/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= +github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/speakeasy-api/jsonpath v0.6.0 h1:IhtFOV9EbXplhyRqsVhHoBmmYjblIRh5D1/g8DHMXJ8= +github.com/speakeasy-api/jsonpath v0.6.0/go.mod h1:ymb2iSkyOycmzKwbEAYPJV/yi2rSmvBCLZJcyD+VVWw= +github.com/speakeasy-api/openapi-overlay v0.10.2 h1:VOdQ03eGKeiHnpb1boZCGm7x8Haj6gST0P3SGTX95GU= +github.com/speakeasy-api/openapi-overlay v0.10.2/go.mod h1:n0iOU7AqKpNFfEt6tq7qYITC4f0yzVVdFw0S7hukemg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= +github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= +github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= +github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0= +github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/minimal-server/stdhttp-go-tool/go.mod b/examples/minimal-server/stdhttp-go-tool/go.mod index 361ba8a7dd..0334737a79 100644 --- a/examples/minimal-server/stdhttp-go-tool/go.mod +++ b/examples/minimal-server/stdhttp-go-tool/go.mod @@ -22,10 +22,10 @@ require ( github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/woodsbury/decimal128 v1.3.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/sync v0.9.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect golang.org/x/text v0.20.0 // indirect - golang.org/x/tools v0.25.1 // indirect + golang.org/x/tools v0.30.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/examples/minimal-server/stdhttp-go-tool/go.sum b/examples/minimal-server/stdhttp-go-tool/go.sum index 2319ae885e..fdce2066b1 100644 --- a/examples/minimal-server/stdhttp-go-tool/go.sum +++ b/examples/minimal-server/stdhttp-go-tool/go.sum @@ -32,6 +32,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -95,8 +97,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -104,13 +106,13 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -125,8 +127,8 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -138,8 +140,8 @@ golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.25.1 h1:YeIyhd0M7gStYR9jb2IFXVVT+QJhgXu1ZECOuRwofh4= -golang.org/x/tools v0.25.1/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/examples/minimal-server/stdhttp/go.mod b/examples/minimal-server/stdhttp/go.mod index aa9f7fe9e5..cb5ad005eb 100644 --- a/examples/minimal-server/stdhttp/go.mod +++ b/examples/minimal-server/stdhttp/go.mod @@ -21,10 +21,10 @@ require ( github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/woodsbury/decimal128 v1.3.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/sync v0.9.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect golang.org/x/text v0.20.0 // indirect - golang.org/x/tools v0.25.1 // indirect + golang.org/x/tools v0.30.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/examples/minimal-server/stdhttp/go.sum b/examples/minimal-server/stdhttp/go.sum index 2319ae885e..fdce2066b1 100644 --- a/examples/minimal-server/stdhttp/go.sum +++ b/examples/minimal-server/stdhttp/go.sum @@ -32,6 +32,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -95,8 +97,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -104,13 +106,13 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -125,8 +127,8 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -138,8 +140,8 @@ golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.25.1 h1:YeIyhd0M7gStYR9jb2IFXVVT+QJhgXu1ZECOuRwofh4= -golang.org/x/tools v0.25.1/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/examples/output-options/preferskipoptionalpointerwithomitzero/go.mod b/examples/output-options/preferskipoptionalpointerwithomitzero/go.mod index 03d3b98fcc..8bf88defe2 100644 --- a/examples/output-options/preferskipoptionalpointerwithomitzero/go.mod +++ b/examples/output-options/preferskipoptionalpointerwithomitzero/go.mod @@ -26,10 +26,10 @@ require ( github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/woodsbury/decimal128 v1.3.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/sync v0.9.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect golang.org/x/text v0.20.0 // indirect - golang.org/x/tools v0.25.1 // indirect + golang.org/x/tools v0.30.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/examples/output-options/preferskipoptionalpointerwithomitzero/go.sum b/examples/output-options/preferskipoptionalpointerwithomitzero/go.sum index 2319ae885e..fdce2066b1 100644 --- a/examples/output-options/preferskipoptionalpointerwithomitzero/go.sum +++ b/examples/output-options/preferskipoptionalpointerwithomitzero/go.sum @@ -32,6 +32,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -95,8 +97,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -104,13 +106,13 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -125,8 +127,8 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -138,8 +140,8 @@ golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.25.1 h1:YeIyhd0M7gStYR9jb2IFXVVT+QJhgXu1ZECOuRwofh4= -golang.org/x/tools v0.25.1/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/examples/output-options/type-mapping/config.yaml b/examples/output-options/type-mapping/config.yaml new file mode 100644 index 0000000000..7a1af00d54 --- /dev/null +++ b/examples/output-options/type-mapping/config.yaml @@ -0,0 +1,14 @@ +# yaml-language-server: $schema=../../configuration-schema.json +package: typemapping +generate: + models: true +output-options: + skip-prune: true + type-mapping: + number: + default: + type: int64 + formats: + date: + type: CustomDateHandler +output: typemapping.gen.go diff --git a/examples/output-options/type-mapping/customdate.go b/examples/output-options/type-mapping/customdate.go new file mode 100644 index 0000000000..fda97a2d3e --- /dev/null +++ b/examples/output-options/type-mapping/customdate.go @@ -0,0 +1,3 @@ +package typemapping + +type CustomDateHandler struct{} diff --git a/examples/output-options/type-mapping/generate.go b/examples/output-options/type-mapping/generate.go new file mode 100644 index 0000000000..0110b3dc62 --- /dev/null +++ b/examples/output-options/type-mapping/generate.go @@ -0,0 +1,6 @@ +package typemapping + +// The configuration in this directory overrides the default handling of +// "type: number" from producing an `int` to producing an `int64`, and we +// override `type: string, format: date` to be a custom type in this package. +//go:generate go run github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml diff --git a/examples/output-options/type-mapping/spec.yaml b/examples/output-options/type-mapping/spec.yaml new file mode 100644 index 0000000000..2c8f63487a --- /dev/null +++ b/examples/output-options/type-mapping/spec.yaml @@ -0,0 +1,18 @@ +openapi: "3.0.1" +info: + version: 1.0.0 + title: Type mapping test +paths: {} +components: + schemas: + EmployeeDatabaseRecord: + type: object + required: + - ID + - DateHired + properties: + ID: + type: number + DateHired: + type: number + format: date diff --git a/examples/output-options/type-mapping/typemapping.gen.go b/examples/output-options/type-mapping/typemapping.gen.go new file mode 100644 index 0000000000..66b1f69f94 --- /dev/null +++ b/examples/output-options/type-mapping/typemapping.gen.go @@ -0,0 +1,10 @@ +// Package typemapping provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/livesession/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT. +package typemapping + +// EmployeeDatabaseRecord defines model for EmployeeDatabaseRecord. +type EmployeeDatabaseRecord struct { + DateHired CustomDateHandler `json:"DateHired"` + ID int64 `json:"ID"` +} diff --git a/examples/petstore-expanded/fiber/Makefile b/examples/petstore-expanded/fiber/Makefile new file mode 100644 index 0000000000..bb37d63394 --- /dev/null +++ b/examples/petstore-expanded/fiber/Makefile @@ -0,0 +1,36 @@ +SHELL:=/bin/bash + +YELLOW := \e[0;33m +RESET := \e[0;0m + +GOVER := $(shell go env GOVERSION) +GOMINOR := $(shell bash -c "cut -f1 -d' ' <<< \"$(GOVER)\" | cut -f2 -d.") + +define execute-if-go-124 +@{ \ +if [[ 24 -le $(GOMINOR) ]]; then \ + $1; \ +else \ + echo -e "$(YELLOW)Skipping task as you're running Go v1.$(GOMINOR).x which is < Go 1.24, which this module requires$(RESET)"; \ +fi \ +} +endef + +lint: + $(call execute-if-go-124,$(GOBIN)/golangci-lint run ./...) + +lint-ci: + + $(call execute-if-go-124,$(GOBIN)/golangci-lint run ./... --output.text.path=stdout --timeout=5m) + +generate: + $(call execute-if-go-124,go generate ./...) + +test: + $(call execute-if-go-124,go test -cover ./...) + +tidy: + $(call execute-if-go-124,go mod tidy) + +tidy-ci: + $(call execute-if-go-124,tidied -verbose) diff --git a/examples/petstore-expanded/fiber/go.mod b/examples/petstore-expanded/fiber/go.mod new file mode 100644 index 0000000000..e8f8060406 --- /dev/null +++ b/examples/petstore-expanded/fiber/go.mod @@ -0,0 +1,53 @@ +module github.com/livesession/oapi-codegen/v2/examples/petstore-expanded/fiber + +go 1.24.0 + +replace github.com/livesession/oapi-codegen/v2 => ../../../ + +tool github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen + +require ( + github.com/getkin/kin-openapi v0.133.0 + github.com/gofiber/fiber/v2 v2.52.11 + github.com/oapi-codegen/fiber-middleware v1.0.2 + github.com/oapi-codegen/runtime v1.1.0 + github.com/stretchr/testify v1.11.1 +) + +require ( + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/mux v1.8.1 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/livesession/oapi-codegen/v2 v2.0.0-00010101000000-000000000000 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect + github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect + github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rivo/uniseg v0.4.4 // indirect + github.com/speakeasy-api/jsonpath v0.6.0 // indirect + github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.51.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect + github.com/woodsbury/decimal128 v1.3.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/tools v0.30.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/examples/petstore-expanded/fiber/go.sum b/examples/petstore-expanded/fiber/go.sum new file mode 100644 index 0000000000..62ff2f51fd --- /dev/null +++ b/examples/petstore-expanded/fiber/go.sum @@ -0,0 +1,212 @@ +github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= +github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= +github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +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/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= +github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= +github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ= +github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= +github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/gofiber/fiber/v2 v2.52.11 h1:5f4yzKLcBcF8ha1GQTWB+mpblWz3Vz6nSAbTL31HkWs= +github.com/gofiber/fiber/v2 v2.52.11/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oapi-codegen/fiber-middleware v1.0.2 h1:f4KPdjyRTYh2GyAv9wsDP+Q9akOND17wuMSbmMwDkJI= +github.com/oapi-codegen/fiber-middleware v1.0.2/go.mod h1:+lGj+802Ajp/+fQG9d8t1SuYP8r7lnOc6wnOwwRArYg= +github.com/oapi-codegen/runtime v1.1.0 h1:rJpoNUawn5XTvekgfkvSZr0RqEnoYpFkyvrzfWeFKWM= +github.com/oapi-codegen/runtime v1.1.0/go.mod h1:BeSfBkWWWnAnGdyS+S/GnlbmHKzf8/hwkvelJZDeKA8= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= +github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/speakeasy-api/jsonpath v0.6.0 h1:IhtFOV9EbXplhyRqsVhHoBmmYjblIRh5D1/g8DHMXJ8= +github.com/speakeasy-api/jsonpath v0.6.0/go.mod h1:ymb2iSkyOycmzKwbEAYPJV/yi2rSmvBCLZJcyD+VVWw= +github.com/speakeasy-api/openapi-overlay v0.10.2 h1:VOdQ03eGKeiHnpb1boZCGm7x8Haj6gST0P3SGTX95GU= +github.com/speakeasy-api/openapi-overlay v0.10.2/go.mod h1:n0iOU7AqKpNFfEt6tq7qYITC4f0yzVVdFw0S7hukemg= +github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= +github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= +github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= +github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0= +github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/petstore-expanded/stdhttp/go.mod b/examples/petstore-expanded/stdhttp/go.mod index 2064588bc6..1f87be29f3 100644 --- a/examples/petstore-expanded/stdhttp/go.mod +++ b/examples/petstore-expanded/stdhttp/go.mod @@ -32,10 +32,10 @@ require ( github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/woodsbury/decimal128 v1.3.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/sync v0.9.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect golang.org/x/text v0.20.0 // indirect - golang.org/x/tools v0.25.1 // indirect + golang.org/x/tools v0.30.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/examples/petstore-expanded/stdhttp/go.sum b/examples/petstore-expanded/stdhttp/go.sum index 458fbf7291..7bf494f54d 100644 --- a/examples/petstore-expanded/stdhttp/go.sum +++ b/examples/petstore-expanded/stdhttp/go.sum @@ -36,6 +36,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -112,8 +114,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -121,13 +123,13 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -142,8 +144,8 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -155,8 +157,8 @@ golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.25.1 h1:YeIyhd0M7gStYR9jb2IFXVVT+QJhgXu1ZECOuRwofh4= -golang.org/x/tools v0.25.1/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/go.mod b/go.mod index 015fb413b1..a2efa0d625 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,9 @@ require ( github.com/getkin/kin-openapi v0.133.0 github.com/speakeasy-api/openapi-overlay v0.10.2 github.com/stretchr/testify v1.11.1 - golang.org/x/mod v0.21.0 + golang.org/x/mod v0.23.0 golang.org/x/text v0.20.0 - golang.org/x/tools v0.25.1 + golang.org/x/tools v0.30.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -29,5 +29,5 @@ require ( github.com/ugorji/go/codec v1.2.11 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/woodsbury/decimal128 v1.3.0 // indirect - golang.org/x/sync v0.9.0 // indirect + golang.org/x/sync v0.11.0 // indirect ) diff --git a/go.sum b/go.sum index 2319ae885e..fdce2066b1 100644 --- a/go.sum +++ b/go.sum @@ -32,6 +32,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -95,8 +97,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -104,13 +106,13 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -125,8 +127,8 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -138,8 +140,8 @@ golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.25.1 h1:YeIyhd0M7gStYR9jb2IFXVVT+QJhgXu1ZECOuRwofh4= -golang.org/x/tools v0.25.1/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/greptile.json b/greptile.json new file mode 100644 index 0000000000..bc3cc79fc0 --- /dev/null +++ b/greptile.json @@ -0,0 +1,4 @@ +{ + "skipReview": "AUTOMATIC", + "ignorePatterns": "**/*.gen.go" +} diff --git a/internal/test/all_of/openapi.yaml b/internal/test/all_of/openapi.yaml index f73a8e5f1b..4c1cc2948c 100644 --- a/internal/test/all_of/openapi.yaml +++ b/internal/test/all_of/openapi.yaml @@ -51,3 +51,15 @@ components: type: integer format: int64 required: [ ID ] + PersonWithRole: + type: object + description: | + This tests a schema that has both its own properties and an allOf reference. + The generated code should embed the allOf ref and inline the own properties. + properties: + Role: + type: string + allOf: + - $ref: "#/components/schemas/Person" + required: + - Role diff --git a/internal/test/all_of/v1/openapi.gen.go b/internal/test/all_of/v1/openapi.gen.go index b7cfc03d97..0bff97c7cf 100644 --- a/internal/test/all_of/v1/openapi.gen.go +++ b/internal/test/all_of/v1/openapi.gen.go @@ -38,20 +38,30 @@ type PersonWithID struct { ID int64 `json:"ID"` } +// PersonWithRole defines model for PersonWithRole. +type PersonWithRole struct { + // Embedded struct due to allOf(#/components/schemas/Person) + Person `yaml:",inline"` + // Embedded fields due to inline allOf schema + Role string `json:"Role"` +} + // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/5SUT2/bOBDFv8qAu0dBTrCLPegWrNtAQJEaaNIc4gAZSyOLKTVkyVEMwfB3L0jJ/+AW", - "aX0awOTjvDe/0VZVtnOWiSWoYqtC1VKHqVyQD5ZjhcZ8blTxtFV/e2pUof6aHW/Npiuz8fzCW0deNAW1", - "y7bK0/dee6pV8aQ+ah/kDjtSmfqEU/m8e85UTaHy2omO76n7VgfQARBcksxgo6WFDrlGsX6AJgoBcg0G", - "gwBjRxmsegGbJNBAOV8y992KfA5JbmN7U8OKwJP0nqmG1QAIL7ckLxBkMAQ3izKHR4KO/JpAWpqeX7I7", - "eBo7QbbSkocvyTlsWl21YNkM4Lx90zUF2PuGRpOpQ75klSkZHKlC2dUrVaJ2mbqIrNheZEGBAD1NQiAt", - "CgRHlW6GQ0LRJA3pGBpziCGLGS354L0Pk2+Glw+1PnUOxLWzmiWDTUuegLBq4xD2WqMDd9bqcaDFdm8u", - "iNe8juZu7Rt57oilnN+lWcRjjfUdiiqUZvnv32MomoXW5OPFAxuXqrtfhviopS3nf0prYvTc1Cjybpu7", - "7Iztcv47JIOnyvoaMBw5bLztAOF/Tyh0GEMOpUBlWVBzWHKcaiRygsA2gLA4XQ5kwLrWE/6egu19RfDw", - "UM5/yl7sX3NjU8ZaTPzvnoIEuInxQUosJD2VqTfyYXR0nV/lVzF164jRaVWof/Kr/DqygdKmBGfOYEWt", - "NfU48jXJJdhf0ei0zgE2yAIoYChus2WCKJVBsCAxwA6/UQSfOmjRuWE0FGeGUaysVaEWJ0/GyQRnOewX", - "qsHepBZioMSpROeMrpLA7HX6zo1sxOp9cibeUpDnzk7d79LvRwAAAP//lzc18GUFAAA=", + "H4sIAAAAAAAC/5RVTY/jNgz9K4Tao+HMokUPvi2adhGg2AbtbPewGWAYi460lSlVoicwgvz3QrLzhWy7", + "Oz7xQD3yPT7SB9X6PngmlqSag0qtoR5LuKaYPOcInfu9U82ng/o+Uqca9d3i8moxP1lM+evoA0WxlNSx", + "OqhI/ww2klbNJ/WrjUneY0+qUr/hHD4dnyqlKbXRBrG5nno0NoFNgBAKZAV7KwZ6ZI3i4whdBgJkDQ6T", + "AGNPFWwHAV8g0MFquWEe+i3FGgrc3g9Ow5YgkgyRScN2BITndyTPkGR0BG/Xqxo+EvQUdwRiaC6/4XDm", + "NHWC7MVQhD8Lc9gb2xrw7EYI0b9YTQlOvKGz5HSqN6wqJWMg1Si//UytqGOl7iRrDndaUCLASDMQiEGB", + "FKi13XhWKJOksaShc2cZqqzRhs/chzTzZnj+Rdtr5kCsg7csFewNRQLC1uQhnLAmBuGm1ctAm8OJXJJo", + "eZfJvfMvFLknltXyfZlFTut87FFUoyzLTz9eRLEstKOYH569cY96/E8RP1oxq+Vr3Vo8ektqAvlqm8fq", + "xtur5bc4GSK1PmrAdPFhF30PCD9HQqHzGGpYCbSeBS2nDeepZkfOJvAdIKyvlwMZUGs72z9S8kNsCT58", + "WC3/13tZtj+8o9cL92WyQkky3yl7cqvBBFsvBqwk8HuGq33KS5x7z6UhUkeRuKV6w4+GYEdMEYU0tF4T", + "JFOMTP2WdFHj/KrAWHaWp8W9LfIl65443/vreqol6+lOvJxmufMFwEpGUo+F+NvSUVEtlWGoSr1QTJNC", + "b+qH+iFr7wMxBqsa9UP9UL/J3aGY0tgiOGzJeKenfdmR3F+Fv9DZcgsT7JEFUMBRPoWeCTJUBcmD5IH0", + "+Dflq0E9GAxhnMTIUmAGW2nVqPVVySxACp7T6Rp1OLjSQnYjcQkxBGfbArD4PP8kponn6OvumZe1CHnL", + "7Jr9sXz/BgAA//+GXQSVogYAAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/test/all_of/v2/openapi.gen.go b/internal/test/all_of/v2/openapi.gen.go index 912ce6e919..a9c4aa012a 100644 --- a/internal/test/all_of/v2/openapi.gen.go +++ b/internal/test/all_of/v2/openapi.gen.go @@ -38,20 +38,30 @@ type PersonWithID struct { LastName string `json:"LastName"` } +// PersonWithRole defines model for PersonWithRole. +type PersonWithRole struct { + // Embedded struct due to allOf(#/components/schemas/Person) + Person `yaml:",inline"` + // Embedded fields due to inline allOf schema + Role string `json:"Role"` +} + // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/5SUT2/bOBDFv8qAu0dBTrCLPegWrNtAQJEaaNIc4gAZSyOLKTVkyVEMwfB3L0jJ/+AW", - "aX0awOTjvDe/0VZVtnOWiSWoYqtC1VKHqVyQD5ZjhcZ8blTxtFV/e2pUof6aHW/Npiuz8fzCW0deNAW1", - "y7bK0/dee6pV8aQ+ah/kDjtSmfqEU/m8e85UTaHy2omO76n7VgfQARBcksxgo6WFDrlGsX6AJgoBcg0G", - "gwBjRxmsegGbJNBAOV8y992KfA5JbmN7U8OKwJP0nqmG1QAIL7ckLxBkMAQ3izKHR4KO/JpAWpqeX7I7", - "eBo7QbbSkocvyTlsWl21YNkM4Lx90zUF2PuGRpOpQ75klSkZHKlC2dUrVaJ2mbqIrNheZEGBAD1NQiAt", - "CgRHlW6GQ0LRJA3pGBpziCGLGS354L0Pk2+Glw+1PnUOxLWzmiWDTUuegLBq4xD2WqMDd9bqcaDFdm8u", - "iNe8juZu7Rt57oilnN+lWcRjjfUdiiqUZvnv32MomoXW5OPFAxuXqrtfhviopS3nf0prYvTc1Cjybpu7", - "7Iztcv47JIOnyvoaMBw5bLztAOF/Tyh0GEMOpUBlWVBzWHKcaiRygsA2gLA4XQ5kwLrWE/6egu19RfDw", - "UM5/yl7sX3NjU8ZaTPzvnoIEuInxQUosJD2VqTfyYXR0nV/lVzF164jRaVWof/Kr/DqygdKmBGfOYEWt", - "NfU48jXJJdhf0ei0zgE2yAIoYChus2WCKJVBsCAxwA6/UQSfOmjRuWE0FGeGUaysVaEWJ0/GyQRnOewX", - "qsHepBZioMSpROeMrpLA7HX6zo1sxOp9cibeUpDnzk7d79LvRwAAAP//lzc18GUFAAA=", + "H4sIAAAAAAAC/5RVTY/jNgz9K4Tao+HMokUPvi2adhGg2AbtbPewGWAYi460lSlVoicwgvz3QrLzhWy7", + "Oz7xQD3yPT7SB9X6PngmlqSag0qtoR5LuKaYPOcInfu9U82ng/o+Uqca9d3i8moxP1lM+evoA0WxlNSx", + "OqhI/ww2klbNJ/WrjUneY0+qUr/hHD4dnyqlKbXRBrG5nno0NoFNgBAKZAV7KwZ6ZI3i4whdBgJkDQ6T", + "AGNPFWwHAV8g0MFquWEe+i3FGgrc3g9Ow5YgkgyRScN2BITndyTPkGR0BG/Xqxo+EvQUdwRiaC6/4XDm", + "NHWC7MVQhD8Lc9gb2xrw7EYI0b9YTQlOvKGz5HSqN6wqJWMg1Si//UytqGOl7iRrDndaUCLASDMQiEGB", + "FKi13XhWKJOksaShc2cZqqzRhs/chzTzZnj+Rdtr5kCsg7csFewNRQLC1uQhnLAmBuGm1ctAm8OJXJJo", + "eZfJvfMvFLknltXyfZlFTut87FFUoyzLTz9eRLEstKOYH569cY96/E8RP1oxq+Vr3Vo8ektqAvlqm8fq", + "xtur5bc4GSK1PmrAdPFhF30PCD9HQqHzGGpYCbSeBS2nDeepZkfOJvAdIKyvlwMZUGs72z9S8kNsCT58", + "WC3/13tZtj+8o9cL92WyQkky3yl7cqvBBFsvBqwk8HuGq33KS5x7z6UhUkeRuKV6w4+GYEdMEYU0tF4T", + "JFOMTP2WdFHj/KrAWHaWp8W9LfIl65443/vreqol6+lOvJxmufMFwEpGUo+F+NvSUVEtlWGoSr1QTJNC", + "b+qH+iFr7wMxBqsa9UP9UL/J3aGY0tgiOGzJeKenfdmR3F+Fv9DZcgsT7JEFUMBRPoWeCTJUBcmD5IH0", + "+Dflq0E9GAxhnMTIUmAGW2nVqPVVySxACp7T6Rp1OLjSQnYjcQkxBGfbArD4PP8kponn6OvumZe1CHnL", + "7Jr9sXz/BgAA//+GXQSVogYAAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/test/array_pointer/array_pointer.gen.go b/internal/test/array_pointer/array_pointer.gen.go index c35f91b7f7..7841fceb95 100644 --- a/internal/test/array_pointer/array_pointer.gen.go +++ b/internal/test/array_pointer/array_pointer.gen.go @@ -7,7 +7,7 @@ package array_pointer type DateHistogram struct { DocCount *int `json:"doc_count,omitempty"` Key *string `json:"key,omitempty"` - KeyAsString *string `json:"key_as_string"` + KeyAsString *string `json:"key_as_string,omitempty"` } // Response defines model for Response. @@ -20,6 +20,6 @@ type ResponsePlaceholder struct { // Embedded struct due to allOf(#/components/schemas/Response) Response `yaml:",inline"` // Embedded fields due to inline allOf schema - Hello *string `json:"hello,omitempty"` - Past7DaysHistogram []*DateHistogram `json:"past_7_days_histogram"` + Hello *string `json:"hello,omitempty"` + Past7DaysHistogram []DateHistogram `json:"past_7_days_histogram,omitempty"` } diff --git a/internal/test/components/components.gen.go b/internal/test/components/components.gen.go index 61bf300d95..f3dbab3f6e 100644 --- a/internal/test/components/components.gen.go +++ b/internal/test/components/components.gen.go @@ -18,6 +18,20 @@ const ( Enum1Two Enum1 = "Two" ) +// Valid indicates whether the value is a known member of the Enum1 enum. +func (e Enum1) Valid() bool { + switch e { + case Enum1One: + return true + case Enum1Three: + return true + case Enum1Two: + return true + default: + return false + } +} + // Defines values for Enum2. const ( Enum2Four Enum2 = "Four" @@ -25,6 +39,20 @@ const ( Enum2Two Enum2 = "Two" ) +// Valid indicates whether the value is a known member of the Enum2 enum. +func (e Enum2) Valid() bool { + switch e { + case Enum2Four: + return true + case Enum2Three: + return true + case Enum2Two: + return true + default: + return false + } +} + // Defines values for Enum3. const ( Enum3Bar Enum3 = "Bar" @@ -32,6 +60,20 @@ const ( Enum3Foo Enum3 = "Foo" ) +// Valid indicates whether the value is a known member of the Enum3 enum. +func (e Enum3) Valid() bool { + switch e { + case Enum3Bar: + return true + case Enum3Enum1One: + return true + case Enum3Foo: + return true + default: + return false + } +} + // Defines values for Enum4. const ( Cat Enum4 = "Cat" @@ -39,6 +81,20 @@ const ( Mouse Enum4 = "Mouse" ) +// Valid indicates whether the value is a known member of the Enum4 enum. +func (e Enum4) Valid() bool { + switch e { + case Cat: + return true + case Dog: + return true + case Mouse: + return true + default: + return false + } +} + // Defines values for Enum5. const ( Enum5N5 Enum5 = 5 @@ -46,6 +102,20 @@ const ( Enum5N7 Enum5 = 7 ) +// Valid indicates whether the value is a known member of the Enum5 enum. +func (e Enum5) Valid() bool { + switch e { + case Enum5N5: + return true + case Enum5N6: + return true + case Enum5N7: + return true + default: + return false + } +} + // Defines values for EnumUnion. const ( EnumUnionFour EnumUnion = "Four" @@ -54,6 +124,22 @@ const ( EnumUnionTwo EnumUnion = "Two" ) +// Valid indicates whether the value is a known member of the EnumUnion enum. +func (e EnumUnion) Valid() bool { + switch e { + case EnumUnionFour: + return true + case EnumUnionOne: + return true + case EnumUnionThree: + return true + case EnumUnionTwo: + return true + default: + return false + } +} + // Defines values for EnumUnion2. const ( EnumUnion2One EnumUnion2 = "One" @@ -62,6 +148,22 @@ const ( EnumUnion2Two EnumUnion2 = "Two" ) +// Valid indicates whether the value is a known member of the EnumUnion2 enum. +func (e EnumUnion2) Valid() bool { + switch e { + case EnumUnion2One: + return true + case EnumUnion2Seven: + return true + case EnumUnion2Three: + return true + case EnumUnion2Two: + return true + default: + return false + } +} + // Defines values for FunnyValues. const ( FunnyValuesAnd FunnyValues = "&" @@ -71,6 +173,24 @@ const ( FunnyValuesPercent FunnyValues = "%" ) +// Valid indicates whether the value is a known member of the FunnyValues enum. +func (e FunnyValues) Valid() bool { + switch e { + case FunnyValuesAnd: + return true + case FunnyValuesAsterisk: + return true + case FunnyValuesEmpty: + return true + case FunnyValuesN5: + return true + case FunnyValuesPercent: + return true + default: + return false + } +} + // Defines values for EnumParam1. const ( EnumParam1Both EnumParam1 = "both" @@ -78,6 +198,20 @@ const ( EnumParam1On EnumParam1 = "on" ) +// Valid indicates whether the value is a known member of the EnumParam1 enum. +func (e EnumParam1) Valid() bool { + switch e { + case EnumParam1Both: + return true + case EnumParam1Off: + return true + case EnumParam1On: + return true + default: + return false + } +} + // Defines values for EnumParam2. const ( EnumParam2Both EnumParam2 = "both" @@ -85,6 +219,20 @@ const ( EnumParam2On EnumParam2 = "on" ) +// Valid indicates whether the value is a known member of the EnumParam2 enum. +func (e EnumParam2) Valid() bool { + switch e { + case EnumParam2Both: + return true + case EnumParam2Off: + return true + case EnumParam2On: + return true + default: + return false + } +} + // Defines values for EnumParam3. const ( Alice EnumParam3 = "alice" @@ -92,6 +240,20 @@ const ( Eve EnumParam3 = "eve" ) +// Valid indicates whether the value is a known member of the EnumParam3 enum. +func (e EnumParam3) Valid() bool { + switch e { + case Alice: + return true + case Bob: + return true + case Eve: + return true + default: + return false + } +} + // AdditionalPropertiesObject1 Has additional properties of type int type AdditionalPropertiesObject1 struct { Id int `json:"id"` diff --git a/internal/test/externalref/externalref.cfg.yaml b/internal/test/externalref/externalref.cfg.yaml index d5a201d4b8..c7c7bb9d49 100644 --- a/internal/test/externalref/externalref.cfg.yaml +++ b/internal/test/externalref/externalref.cfg.yaml @@ -5,7 +5,7 @@ generate: embedded-spec: true import-mapping: ./packageA/spec.yaml: github.com/livesession/oapi-codegen/v2/internal/test/externalref/packageA - ./packageB/spec.yaml: github.com/livesession/oapi-codegen/v2/internal/test/externalref/packageB + ./packageB/spec.yaml: package_b github.com/livesession/oapi-codegen/v2/internal/test/externalref/packageB https://petstore3.swagger.io/api/v3/openapi.json: github.com/livesession/oapi-codegen/v2/internal/test/externalref/petstore output: externalref.gen.go output-options: diff --git a/internal/test/externalref/externalref.gen.go b/internal/test/externalref/externalref.gen.go index ac6f9da58d..fb0e412bd0 100644 --- a/internal/test/externalref/externalref.gen.go +++ b/internal/test/externalref/externalref.gen.go @@ -14,16 +14,16 @@ import ( "github.com/getkin/kin-openapi/openapi3" externalRef0 "github.com/livesession/oapi-codegen/v2/internal/test/externalref/packageA" - externalRef1 "github.com/livesession/oapi-codegen/v2/internal/test/externalref/packageB" - externalRef2 "github.com/livesession/oapi-codegen/v2/internal/test/externalref/petstore" + package_b "github.com/livesession/oapi-codegen/v2/internal/test/externalref/packageB" + externalRef1 "github.com/livesession/oapi-codegen/v2/internal/test/externalref/petstore" ) // Container defines model for Container. type Container struct { ObjectA *externalRef0.ObjectA `json:"object_a,omitempty"` - ObjectB *externalRef1.ObjectB `json:"object_b,omitempty"` + ObjectB *package_b.ObjectB `json:"object_b,omitempty"` ObjectC *map[string]interface{} `json:"object_c,omitempty"` - Pet *externalRef2.Pet `json:"pet,omitempty"` + Pet *externalRef1.Pet `json:"pet,omitempty"` } // Base64 encoded, gzipped, json marshaled Swagger object @@ -82,13 +82,13 @@ func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { } res[rawPath] = rawFunc } - for rawPath, rawFunc := range externalRef1.PathToRawSpec(path.Join(path.Dir(pathToFile), "./packageB/spec.yaml")) { + for rawPath, rawFunc := range package_b.PathToRawSpec(path.Join(path.Dir(pathToFile), "./packageB/spec.yaml")) { if _, ok := res[rawPath]; ok { // it is not possible to compare functions in golang, so always overwrite the old value } res[rawPath] = rawFunc } - for rawPath, rawFunc := range externalRef2.PathToRawSpec(path.Join(path.Dir(pathToFile), "https://petstore3.swagger.io/api/v3/openapi.json")) { + for rawPath, rawFunc := range externalRef1.PathToRawSpec(path.Join(path.Dir(pathToFile), "https://petstore3.swagger.io/api/v3/openapi.json")) { if _, ok := res[rawPath]; ok { // it is not possible to compare functions in golang, so always overwrite the old value } diff --git a/internal/test/externalref/petstore/externalref.gen.go b/internal/test/externalref/petstore/externalref.gen.go index dc8206c635..f312e00ce1 100644 --- a/internal/test/externalref/petstore/externalref.gen.go +++ b/internal/test/externalref/petstore/externalref.gen.go @@ -29,6 +29,20 @@ const ( Placed OrderStatus = "placed" ) +// Valid indicates whether the value is a known member of the OrderStatus enum. +func (e OrderStatus) Valid() bool { + switch e { + case Approved: + return true + case Delivered: + return true + case Placed: + return true + default: + return false + } +} + // Defines values for PetStatus. const ( PetStatusAvailable PetStatus = "available" @@ -36,6 +50,20 @@ const ( PetStatusSold PetStatus = "sold" ) +// Valid indicates whether the value is a known member of the PetStatus enum. +func (e PetStatus) Valid() bool { + switch e { + case PetStatusAvailable: + return true + case PetStatusPending: + return true + case PetStatusSold: + return true + default: + return false + } +} + // Defines values for FindPetsByStatusParamsStatus. const ( FindPetsByStatusParamsStatusAvailable FindPetsByStatusParamsStatus = "available" @@ -43,6 +71,20 @@ const ( FindPetsByStatusParamsStatusSold FindPetsByStatusParamsStatus = "sold" ) +// Valid indicates whether the value is a known member of the FindPetsByStatusParamsStatus enum. +func (e FindPetsByStatusParamsStatus) Valid() bool { + switch e { + case FindPetsByStatusParamsStatusAvailable: + return true + case FindPetsByStatusParamsStatusPending: + return true + case FindPetsByStatusParamsStatusSold: + return true + default: + return false + } +} + // Address defines model for Address. type Address struct { City *string `json:"city,omitempty"` diff --git a/internal/test/go.mod b/internal/test/go.mod index feb431497f..a0801d1d98 100644 --- a/internal/test/go.mod +++ b/internal/test/go.mod @@ -8,7 +8,6 @@ require ( github.com/getkin/kin-openapi v0.133.0 github.com/gin-gonic/gin v1.9.1 github.com/go-chi/chi/v5 v5.0.10 - github.com/gofiber/fiber/v2 v2.49.1 github.com/google/uuid v1.4.0 github.com/gorilla/mux v1.8.1 github.com/kataras/iris/v12 v12.2.6-0.20230908161203-24ba4e8933b9 @@ -65,7 +64,6 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect github.com/microcosm-cc/bluemonday v1.0.25 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -75,7 +73,6 @@ require ( github.com/pelletier/go-toml/v2 v2.0.9 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rivo/uniseg v0.4.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/schollz/closestmatch v2.1.0+incompatible // indirect github.com/sirupsen/logrus v1.8.1 // indirect @@ -87,23 +84,21 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.49.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect - github.com/valyala/tcplisten v1.0.0 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/woodsbury/decimal128 v1.3.0 // indirect github.com/yosssi/ace v0.0.5 // indirect golang.org/x/arch v0.4.0 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.29.0 // indirect - golang.org/x/sync v0.9.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.20.0 // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.25.1 // indirect + golang.org/x/tools v0.30.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/internal/test/go.sum b/internal/test/go.sum index ca696cc621..994b539a63 100644 --- a/internal/test/go.sum +++ b/internal/test/go.sum @@ -78,8 +78,6 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/gofiber/fiber/v2 v2.49.1 h1:0W2DRWevSirc8pJl4o8r8QejDR8TV6ZUCawHxwbIdOk= -github.com/gofiber/fiber/v2 v2.49.1/go.mod h1:nPUeEBUeeYGgwbDm59Gp7vS8MDyScL6ezr/Np9A13WU= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -168,8 +166,6 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg= github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= @@ -213,9 +209,6 @@ github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -263,13 +256,9 @@ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4d github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.49.0 h1:9FdvCpmxB74LH4dPb7IJ1cOSsluR07XG3I1txXWwJpE= -github.com/valyala/fasthttp v1.49.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= -github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= @@ -300,12 +289,12 @@ golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -315,14 +304,14 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -345,24 +334,24 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.25.1 h1:YeIyhd0M7gStYR9jb2IFXVVT+QJhgXu1ZECOuRwofh4= -golang.org/x/tools v0.25.1/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/test/issues/issue-1039/defaultbehaviour/types.gen.go b/internal/test/issues/issue-1039/defaultbehaviour/types.gen.go index 35459335bc..68c0aadce0 100644 --- a/internal/test/issues/issue-1039/defaultbehaviour/types.gen.go +++ b/internal/test/issues/issue-1039/defaultbehaviour/types.gen.go @@ -6,7 +6,7 @@ package defaultbehaviour // PatchRequest A request to patch an existing user object. type PatchRequest struct { // ComplexOptionalNullable Complex, optional and nullable - ComplexOptionalNullable *ComplexOptionalNullable `json:"complex_optional_nullable"` + ComplexOptionalNullable *ComplexOptionalNullable `json:"complex_optional_nullable,omitempty"` // ComplexRequiredNullable Complex required and nullable ComplexRequiredNullable *ComplexRequiredNullable `json:"complex_required_nullable"` @@ -15,7 +15,7 @@ type PatchRequest struct { SimpleOptionalNonNullable *SimpleOptionalNonNullable `json:"simple_optional_non_nullable,omitempty"` // SimpleOptionalNullable Simple optional and nullable - SimpleOptionalNullable *SimpleOptionalNullable `json:"simple_optional_nullable"` + SimpleOptionalNullable *SimpleOptionalNullable `json:"simple_optional_nullable,omitempty"` // SimpleRequiredNullable Simple required and nullable SimpleRequiredNullable *SimpleRequiredNullable `json:"simple_required_nullable"` @@ -24,7 +24,7 @@ type PatchRequest struct { // ComplexOptionalNullable Complex, optional and nullable type ComplexOptionalNullable struct { // AliasName Optional and nullable - AliasName *string `json:"alias_name"` + AliasName *string `json:"alias_name,omitempty"` // Name Optional and non nullable Name *string `json:"name,omitempty"` diff --git a/internal/test/issues/issue-1087/deps/deps.gen.go b/internal/test/issues/issue-1087/deps/deps.gen.go index e58ed37ea6..50e091b827 100644 --- a/internal/test/issues/issue-1087/deps/deps.gen.go +++ b/internal/test/issues/issue-1087/deps/deps.gen.go @@ -31,7 +31,13 @@ type BaseError struct { } // Error defines model for Error. -type Error = BaseError +type Error struct { + // Embedded struct due to allOf(#/components/schemas/BaseError) + BaseError `yaml:",inline"` + // Embedded fields due to inline allOf schema + // Reason A reason code specific to the service and can be used to identify the exact issue. Should be unique within a domain + Reason string `json:"reason"` +} // N401 defines model for 401. type N401 = Error diff --git a/internal/test/issues/issue-1189/issue1189.gen.go b/internal/test/issues/issue-1189/issue1189.gen.go index 9b5d6f6216..0f1d57dc14 100644 --- a/internal/test/issues/issue-1189/issue1189.gen.go +++ b/internal/test/issues/issue-1189/issue1189.gen.go @@ -27,18 +27,54 @@ const ( TestFieldA1Foo TestFieldA1 = "foo" ) +// Valid indicates whether the value is a known member of the TestFieldA1 enum. +func (e TestFieldA1) Valid() bool { + switch e { + case TestFieldA1Bar: + return true + case TestFieldA1Foo: + return true + default: + return false + } +} + // Defines values for TestFieldB. const ( TestFieldBBar TestFieldB = "bar" TestFieldBFoo TestFieldB = "foo" ) +// Valid indicates whether the value is a known member of the TestFieldB enum. +func (e TestFieldB) Valid() bool { + switch e { + case TestFieldBBar: + return true + case TestFieldBFoo: + return true + default: + return false + } +} + // Defines values for TestFieldC1. const ( Bar TestFieldC1 = "bar" Foo TestFieldC1 = "foo" ) +// Valid indicates whether the value is a known member of the TestFieldC1 enum. +func (e TestFieldC1) Valid() bool { + switch e { + case Bar: + return true + case Foo: + return true + default: + return false + } +} + // Test defines model for test. type Test struct { FieldA *Test_FieldA `json:"fieldA,omitempty"` diff --git a/internal/test/issues/issue-1298/issue1298.gen.go b/internal/test/issues/issue-1298/issue1298.gen.go index a95d9918ed..16f31e3275 100644 --- a/internal/test/issues/issue-1298/issue1298.gen.go +++ b/internal/test/issues/issue-1298/issue1298.gen.go @@ -7,6 +7,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -372,11 +373,14 @@ func (sh *strictHandler) Test(ctx *gin.Context) { var body TestApplicationTestPlusJSONRequestBody if err := ctx.ShouldBindJSON(&body); err != nil { - ctx.Status(http.StatusBadRequest) - ctx.Error(err) - return + if !errors.Is(err, io.EOF) { + ctx.Status(http.StatusBadRequest) + ctx.Error(err) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { return sh.ssi.Test(ctx, request.(TestRequestObject)) diff --git a/internal/test/issues/issue-1397/issue1397.gen.go b/internal/test/issues/issue-1397/issue1397.gen.go index bd37242ab0..e425a8fee4 100644 --- a/internal/test/issues/issue-1397/issue1397.gen.go +++ b/internal/test/issues/issue-1397/issue1397.gen.go @@ -26,6 +26,18 @@ const ( Option2 TestField1 = "option2" ) +// Valid indicates whether the value is a known member of the TestField1 enum. +func (e TestField1) Valid() bool { + switch e { + case Option1: + return true + case Option2: + return true + default: + return false + } +} + // Test defines model for Test. type Test = MyTestRequest diff --git a/internal/test/issues/issue-1529/strict-echo/config.yaml b/internal/test/issues/issue-1529/strict-echo/config.yaml new file mode 100644 index 0000000000..56abc0bee7 --- /dev/null +++ b/internal/test/issues/issue-1529/strict-echo/config.yaml @@ -0,0 +1,9 @@ +# yaml-language-server: $schema=../../../../../configuration-schema.json +package: issue1529 +generate: + client: true + models: true + embedded-spec: true + echo-server: true + strict-server: true +output: issue1529.gen.go diff --git a/internal/test/issues/issue-1529/strict-echo/doc.go b/internal/test/issues/issue-1529/strict-echo/doc.go new file mode 100644 index 0000000000..ee9c68d2b3 --- /dev/null +++ b/internal/test/issues/issue-1529/strict-echo/doc.go @@ -0,0 +1,3 @@ +package issue1529 + +//go:generate go run github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml diff --git a/internal/test/issues/issue-1529/strict-echo/issue1529.gen.go b/internal/test/issues/issue-1529/strict-echo/issue1529.gen.go new file mode 100644 index 0000000000..b281e47c12 --- /dev/null +++ b/internal/test/issues/issue-1529/strict-echo/issue1529.gen.go @@ -0,0 +1,471 @@ +// Package issue1529 provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/livesession/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT. +package issue1529 + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "path" + "strings" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/labstack/echo/v4" + strictecho "github.com/oapi-codegen/runtime/strictmiddleware/echo" +) + +// Test defines model for Test. +type Test = map[string]interface{} + +// RequestEditorFn is the function signature for the RequestEditor callback function +type RequestEditorFn func(ctx context.Context, req *http.Request) error + +// Doer performs HTTP requests. +// +// The standard http.Client implements this interface. +type HttpRequestDoer interface { + Do(req *http.Request) (*http.Response, error) +} + +// Client which conforms to the OpenAPI3 specification for this service. +type Client struct { + // The endpoint of the server conforming to this interface, with scheme, + // https://api.deepmap.com for example. This can contain a path relative + // to the server, such as https://api.deepmap.com/dev-test, and all the + // paths in the swagger spec will be appended to the server. + Server string + + // Doer for performing requests, typically a *http.Client with any + // customized settings, such as certificate chains. + Client HttpRequestDoer + + // A list of callbacks for modifying requests which are generated before sending over + // the network. + RequestEditors []RequestEditorFn +} + +// ClientOption allows setting custom parameters during construction +type ClientOption func(*Client) error + +// Creates a new Client, with reasonable defaults +func NewClient(server string, opts ...ClientOption) (*Client, error) { + // create a client with sane default values + client := Client{ + Server: server, + } + // mutate client and add all optional params + for _, o := range opts { + if err := o(&client); err != nil { + return nil, err + } + } + // ensure the server URL always has a trailing slash + if !strings.HasSuffix(client.Server, "/") { + client.Server += "/" + } + // create httpClient, if not already present + if client.Client == nil { + client.Client = &http.Client{} + } + 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.RequestEditors = append(c.RequestEditors, fn) + return nil + } +} + +// The interface specification for the client above. +type ClientInterface interface { + // Test request + Test(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) +} + +func (c *Client) Test(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewTestRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +// NewTestRequest generates requests for Test +func NewTestRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/test") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { + for _, r := range c.RequestEditors { + if err := r(ctx, req); err != nil { + return err + } + } + for _, r := range additionalEditors { + if err := r(ctx, req); err != nil { + return err + } + } + return 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 { + newBaseURL, err := url.Parse(baseURL) + if err != nil { + return err + } + c.Server = newBaseURL.String() + return nil + } +} + +// ClientWithResponsesInterface is the interface specification for the client with responses above. +type ClientWithResponsesInterface interface { + // TestWithResponse request + TestWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*TestResponse, error) +} + +type TestResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Test + ApplicationjsonProfileBar200 *Test + ApplicationjsonProfileFoo200 *Test +} + +// Status returns HTTPResponse.Status +func (r TestResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r TestResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +// TestWithResponse request returning *TestResponse +func (c *ClientWithResponses) TestWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*TestResponse, error) { + rsp, err := c.Test(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParseTestResponse(rsp) +} + +// ParseTestResponse parses an HTTP response from a TestWithResponse call +func ParseTestResponse(rsp *http.Response) (*TestResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &TestResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case rsp.Header.Get("Content-Type") == "application/json" && rsp.StatusCode == 200: + var dest Test + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case rsp.Header.Get("Content-Type") == "application/json; profile=\"Bar\"" && rsp.StatusCode == 200: + var dest Test + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.ApplicationjsonProfileBar200 = &dest + + case rsp.Header.Get("Content-Type") == "application/json; profile=\"Foo\"" && rsp.StatusCode == 200: + var dest Test + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.ApplicationjsonProfileFoo200 = &dest + + } + + return response, nil +} + +// ServerInterface represents all server handlers. +type ServerInterface interface { + + // (GET /test) + Test(ctx echo.Context) error +} + +// ServerInterfaceWrapper converts echo contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface +} + +// Test converts echo context to params. +func (w *ServerInterfaceWrapper) Test(ctx echo.Context) error { + var err error + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.Test(ctx) + return err +} + +// This is a simple interface which specifies echo.Route addition functions which +// are present on both echo.Echo and echo.Group, since we want to allow using +// either of them for path registration +type EchoRouter interface { + CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route + TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route +} + +// RegisterHandlers adds each server route to the EchoRouter. +func RegisterHandlers(router EchoRouter, si ServerInterface) { + RegisterHandlersWithBaseURL(router, si, "") +} + +// Registers handlers, and prepends BaseURL to the paths, so that the paths +// can be served under a prefix. +func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) { + + wrapper := ServerInterfaceWrapper{ + Handler: si, + } + + router.GET(baseURL+"/test", wrapper.Test) + +} + +type TestRequestObject struct { +} + +type TestResponseObject interface { + VisitTestResponse(w http.ResponseWriter) error +} + +type Test200JSONResponse Test + +func (response Test200JSONResponse) VisitTestResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type Test200ApplicationJSONProfileBarResponse Test + +func (response Test200ApplicationJSONProfileBarResponse) VisitTestResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json; profile=\"Bar\"") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type Test200ApplicationJSONProfileFooResponse Test + +func (response Test200ApplicationJSONProfileFooResponse) VisitTestResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json; profile=\"Foo\"") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +// StrictServerInterface represents all server handlers. +type StrictServerInterface interface { + + // (GET /test) + Test(ctx context.Context, request TestRequestObject) (TestResponseObject, error) +} + +type StrictHandlerFunc = strictecho.StrictEchoHandlerFunc +type StrictMiddlewareFunc = strictecho.StrictEchoMiddlewareFunc + +func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface { + return &strictHandler{ssi: ssi, middlewares: middlewares} +} + +type strictHandler struct { + ssi StrictServerInterface + middlewares []StrictMiddlewareFunc +} + +// Test operation middleware +func (sh *strictHandler) Test(ctx echo.Context) error { + var request TestRequestObject + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.Test(ctx.Request().Context(), request.(TestRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "Test") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(TestResponseObject); ok { + return validResponse.VisitTestResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("unexpected response type: %T", response) + } + return nil +} + +// Base64 encoded, gzipped, json marshaled Swagger object +var swaggerSpec = []string{ + + "H4sIAAAAAAAC/6zPMUsEMRAF4L8iT8twWbWL2FgI9pbXxDjr5cjNDMlYyLL/XRIXFizFad4072NmQZKL", + "ChNbQ1jQ0okucayv1KynfSkhQN7OlAzrujpkngWBP0txECWOmhFwf5gOt3DQaKcheNuIDxohSjVaFn55", + "R/jxHSo1FW40GnfT1CMJG/HoRNWS02j5cxPej+zbTaUZAdd+/8JvL/jh92t/Ew9XWmXOhR6PeIr1iH82", + "n0X+YG7zHQAA//9fnz6pkQEAAA==", +} + +// GetSwagger returns the content of the embedded swagger specification file +// or error if failed to decode +func decodeSpec() ([]byte, error) { + zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) + if err != nil { + return nil, fmt.Errorf("error base64 decoding spec: %w", err) + } + zr, err := gzip.NewReader(bytes.NewReader(zipped)) + if err != nil { + return nil, fmt.Errorf("error decompressing spec: %w", err) + } + var buf bytes.Buffer + _, err = buf.ReadFrom(zr) + if err != nil { + return nil, fmt.Errorf("error decompressing spec: %w", err) + } + + return buf.Bytes(), nil +} + +var rawSpec = decodeSpecCached() + +// a naive cached of a decoded swagger spec +func decodeSpecCached() func() ([]byte, error) { + data, err := decodeSpec() + return func() ([]byte, error) { + return data, err + } +} + +// Constructs a synthetic filesystem for resolving external references when loading openapi specifications. +func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { + res := make(map[string]func() ([]byte, error)) + if len(pathToFile) > 0 { + res[pathToFile] = rawSpec + } + + return res +} + +// GetSwagger returns the Swagger specification corresponding to the generated code +// in this file. The external references of Swagger specification are resolved. +// The logic of resolving external references is tightly connected to "import-mapping" feature. +// Externally referenced files must be embedded in the corresponding golang packages. +// Urls can be supported but this task was out of the scope. +func GetSwagger() (swagger *openapi3.T, err error) { + resolvePath := PathToRawSpec("") + + loader := openapi3.NewLoader() + loader.IsExternalRefsAllowed = true + loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) { + pathToFile := url.String() + pathToFile = path.Clean(pathToFile) + getSpec, ok := resolvePath[pathToFile] + if !ok { + err1 := fmt.Errorf("path not found: %s", pathToFile) + return nil, err1 + } + return getSpec() + } + var specData []byte + specData, err = rawSpec() + if err != nil { + return + } + swagger, err = loader.LoadFromData(specData) + if err != nil { + return + } + return +} diff --git a/internal/test/issues/issue-1529/strict-echo/spec.yaml b/internal/test/issues/issue-1529/strict-echo/spec.yaml new file mode 100644 index 0000000000..ca7aae80a3 --- /dev/null +++ b/internal/test/issues/issue-1529/strict-echo/spec.yaml @@ -0,0 +1,21 @@ +openapi: "3.0.1" +components: + schemas: + Test: + type: object +paths: + /test: + get: + operationId: test + responses: + 200: + content: + application/json: + schema: + $ref: "#/components/schemas/Test" + application/json; profile="Foo": + schema: + $ref: "#/components/schemas/Test" + application/json; profile="Bar": + schema: + $ref: "#/components/schemas/Test" diff --git a/internal/test/issues/issue-1529/strict-fiber/Makefile b/internal/test/issues/issue-1529/strict-fiber/Makefile new file mode 100644 index 0000000000..bb37d63394 --- /dev/null +++ b/internal/test/issues/issue-1529/strict-fiber/Makefile @@ -0,0 +1,36 @@ +SHELL:=/bin/bash + +YELLOW := \e[0;33m +RESET := \e[0;0m + +GOVER := $(shell go env GOVERSION) +GOMINOR := $(shell bash -c "cut -f1 -d' ' <<< \"$(GOVER)\" | cut -f2 -d.") + +define execute-if-go-124 +@{ \ +if [[ 24 -le $(GOMINOR) ]]; then \ + $1; \ +else \ + echo -e "$(YELLOW)Skipping task as you're running Go v1.$(GOMINOR).x which is < Go 1.24, which this module requires$(RESET)"; \ +fi \ +} +endef + +lint: + $(call execute-if-go-124,$(GOBIN)/golangci-lint run ./...) + +lint-ci: + + $(call execute-if-go-124,$(GOBIN)/golangci-lint run ./... --output.text.path=stdout --timeout=5m) + +generate: + $(call execute-if-go-124,go generate ./...) + +test: + $(call execute-if-go-124,go test -cover ./...) + +tidy: + $(call execute-if-go-124,go mod tidy) + +tidy-ci: + $(call execute-if-go-124,tidied -verbose) diff --git a/internal/test/issues/issue-1529/strict-fiber/config.yaml b/internal/test/issues/issue-1529/strict-fiber/config.yaml new file mode 100644 index 0000000000..e03a3f678b --- /dev/null +++ b/internal/test/issues/issue-1529/strict-fiber/config.yaml @@ -0,0 +1,9 @@ +# yaml-language-server: $schema=../../../../../configuration-schema.json +package: issue1529 +generate: + client: true + models: true + embedded-spec: true + fiber-server: true + strict-server: true +output: issue1529.gen.go diff --git a/internal/test/issues/issue-1529/strict-fiber/doc.go b/internal/test/issues/issue-1529/strict-fiber/doc.go new file mode 100644 index 0000000000..ee9c68d2b3 --- /dev/null +++ b/internal/test/issues/issue-1529/strict-fiber/doc.go @@ -0,0 +1,3 @@ +package issue1529 + +//go:generate go run github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml diff --git a/internal/test/issues/issue-1529/strict-fiber/go.mod b/internal/test/issues/issue-1529/strict-fiber/go.mod new file mode 100644 index 0000000000..b043118b0d --- /dev/null +++ b/internal/test/issues/issue-1529/strict-fiber/go.mod @@ -0,0 +1,46 @@ +module github.com/livesession/oapi-codegen/v2/internal/test/issues/issue-1529/strict-fiber + +go 1.24.0 + +replace github.com/livesession/oapi-codegen/v2 => ../../../../../ + +tool github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen + +require ( + github.com/getkin/kin-openapi v0.133.0 + github.com/gofiber/fiber/v2 v2.52.11 +) + +require ( + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/livesession/oapi-codegen/v2 v2.5.1 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect + github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect + github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/speakeasy-api/jsonpath v0.6.0 // indirect + github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.51.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect + github.com/woodsbury/decimal128 v1.3.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/tools v0.30.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/internal/test/issues/issue-1529/strict-fiber/go.sum b/internal/test/issues/issue-1529/strict-fiber/go.sum new file mode 100644 index 0000000000..e2954b1efc --- /dev/null +++ b/internal/test/issues/issue-1529/strict-fiber/go.sum @@ -0,0 +1,198 @@ +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +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/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= +github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= +github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ= +github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= +github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/gofiber/fiber/v2 v2.52.11 h1:5f4yzKLcBcF8ha1GQTWB+mpblWz3Vz6nSAbTL31HkWs= +github.com/gofiber/fiber/v2 v2.52.11/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= +github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/speakeasy-api/jsonpath v0.6.0 h1:IhtFOV9EbXplhyRqsVhHoBmmYjblIRh5D1/g8DHMXJ8= +github.com/speakeasy-api/jsonpath v0.6.0/go.mod h1:ymb2iSkyOycmzKwbEAYPJV/yi2rSmvBCLZJcyD+VVWw= +github.com/speakeasy-api/openapi-overlay v0.10.2 h1:VOdQ03eGKeiHnpb1boZCGm7x8Haj6gST0P3SGTX95GU= +github.com/speakeasy-api/openapi-overlay v0.10.2/go.mod h1:n0iOU7AqKpNFfEt6tq7qYITC4f0yzVVdFw0S7hukemg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= +github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= +github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= +github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0= +github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/test/issues/issue-1529/strict-fiber/issue1529.gen.go b/internal/test/issues/issue-1529/strict-fiber/issue1529.gen.go new file mode 100644 index 0000000000..95e48effe4 --- /dev/null +++ b/internal/test/issues/issue-1529/strict-fiber/issue1529.gen.go @@ -0,0 +1,465 @@ +// Package issue1529 provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/livesession/oapi-codegen/v2 version v2.5.1 DO NOT EDIT. +package issue1529 + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "path" + "strings" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/gofiber/fiber/v2" +) + +// Test defines model for Test. +type Test = map[string]interface{} + +// RequestEditorFn is the function signature for the RequestEditor callback function +type RequestEditorFn func(ctx context.Context, req *http.Request) error + +// Doer performs HTTP requests. +// +// The standard http.Client implements this interface. +type HttpRequestDoer interface { + Do(req *http.Request) (*http.Response, error) +} + +// Client which conforms to the OpenAPI3 specification for this service. +type Client struct { + // The endpoint of the server conforming to this interface, with scheme, + // https://api.deepmap.com for example. This can contain a path relative + // to the server, such as https://api.deepmap.com/dev-test, and all the + // paths in the swagger spec will be appended to the server. + Server string + + // Doer for performing requests, typically a *http.Client with any + // customized settings, such as certificate chains. + Client HttpRequestDoer + + // A list of callbacks for modifying requests which are generated before sending over + // the network. + RequestEditors []RequestEditorFn +} + +// ClientOption allows setting custom parameters during construction +type ClientOption func(*Client) error + +// Creates a new Client, with reasonable defaults +func NewClient(server string, opts ...ClientOption) (*Client, error) { + // create a client with sane default values + client := Client{ + Server: server, + } + // mutate client and add all optional params + for _, o := range opts { + if err := o(&client); err != nil { + return nil, err + } + } + // ensure the server URL always has a trailing slash + if !strings.HasSuffix(client.Server, "/") { + client.Server += "/" + } + // create httpClient, if not already present + if client.Client == nil { + client.Client = &http.Client{} + } + 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.RequestEditors = append(c.RequestEditors, fn) + return nil + } +} + +// The interface specification for the client above. +type ClientInterface interface { + // Test request + Test(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) +} + +func (c *Client) Test(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewTestRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +// NewTestRequest generates requests for Test +func NewTestRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/test") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { + for _, r := range c.RequestEditors { + if err := r(ctx, req); err != nil { + return err + } + } + for _, r := range additionalEditors { + if err := r(ctx, req); err != nil { + return err + } + } + return 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 { + newBaseURL, err := url.Parse(baseURL) + if err != nil { + return err + } + c.Server = newBaseURL.String() + return nil + } +} + +// ClientWithResponsesInterface is the interface specification for the client with responses above. +type ClientWithResponsesInterface interface { + // TestWithResponse request + TestWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*TestResponse, error) +} + +type TestResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Test + ApplicationjsonProfileBar200 *Test + ApplicationjsonProfileFoo200 *Test +} + +// Status returns HTTPResponse.Status +func (r TestResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r TestResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +// TestWithResponse request returning *TestResponse +func (c *ClientWithResponses) TestWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*TestResponse, error) { + rsp, err := c.Test(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParseTestResponse(rsp) +} + +// ParseTestResponse parses an HTTP response from a TestWithResponse call +func ParseTestResponse(rsp *http.Response) (*TestResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &TestResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case rsp.Header.Get("Content-Type") == "application/json" && rsp.StatusCode == 200: + var dest Test + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case rsp.Header.Get("Content-Type") == "application/json; profile=\"Bar\"" && rsp.StatusCode == 200: + var dest Test + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.ApplicationjsonProfileBar200 = &dest + + case rsp.Header.Get("Content-Type") == "application/json; profile=\"Foo\"" && rsp.StatusCode == 200: + var dest Test + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.ApplicationjsonProfileFoo200 = &dest + + } + + return response, nil +} + +// ServerInterface represents all server handlers. +type ServerInterface interface { + + // (GET /test) + Test(c *fiber.Ctx) error +} + +// ServerInterfaceWrapper converts contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface +} + +type MiddlewareFunc fiber.Handler + +// Test operation middleware +func (siw *ServerInterfaceWrapper) Test(c *fiber.Ctx) error { + + return siw.Handler.Test(c) +} + +// FiberServerOptions provides options for the Fiber server. +type FiberServerOptions struct { + BaseURL string + Middlewares []MiddlewareFunc +} + +// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. +func RegisterHandlers(router fiber.Router, si ServerInterface) { + RegisterHandlersWithOptions(router, si, FiberServerOptions{}) +} + +// RegisterHandlersWithOptions creates http.Handler with additional options +func RegisterHandlersWithOptions(router fiber.Router, si ServerInterface, options FiberServerOptions) { + wrapper := ServerInterfaceWrapper{ + Handler: si, + } + + for _, m := range options.Middlewares { + router.Use(fiber.Handler(m)) + } + + router.Get(options.BaseURL+"/test", wrapper.Test) + +} + +type TestRequestObject struct { +} + +type TestResponseObject interface { + VisitTestResponse(ctx *fiber.Ctx) error +} + +type Test200JSONResponse Test + +func (response Test200JSONResponse) VisitTestResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/json") + ctx.Status(200) + + return ctx.JSON(&response) +} + +type Test200ApplicationJSONProfileBarResponse Test + +func (response Test200ApplicationJSONProfileBarResponse) VisitTestResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/json; profile=\"Bar\"") + ctx.Status(200) + + return ctx.JSON(&response) +} + +type Test200ApplicationJSONProfileFooResponse Test + +func (response Test200ApplicationJSONProfileFooResponse) VisitTestResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/json; profile=\"Foo\"") + ctx.Status(200) + + return ctx.JSON(&response) +} + +// StrictServerInterface represents all server handlers. +type StrictServerInterface interface { + + // (GET /test) + Test(ctx context.Context, request TestRequestObject) (TestResponseObject, error) +} + +type StrictHandlerFunc func(ctx *fiber.Ctx, args interface{}) (interface{}, error) + +type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc + +func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface { + return &strictHandler{ssi: ssi, middlewares: middlewares} +} + +type strictHandler struct { + ssi StrictServerInterface + middlewares []StrictMiddlewareFunc +} + +// Test operation middleware +func (sh *strictHandler) Test(ctx *fiber.Ctx) error { + var request TestRequestObject + + handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) { + return sh.ssi.Test(ctx.UserContext(), request.(TestRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "Test") + } + + response, err := handler(ctx, request) + + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } else if validResponse, ok := response.(TestResponseObject); ok { + if err := validResponse.VisitTestResponse(ctx); err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + } else if response != nil { + return fmt.Errorf("unexpected response type: %T", response) + } + return nil +} + +// Base64 encoded, gzipped, json marshaled Swagger object +var swaggerSpec = []string{ + + "H4sIAAAAAAAC/6zPMUsEMRAF4L8iT8twWbWL2FgI9pbXxDjr5cjNDMlYyLL/XRIXFizFad4072NmQZKL", + "ChNbQ1jQ0okucayv1KynfSkhQN7OlAzrujpkngWBP0txECWOmhFwf5gOt3DQaKcheNuIDxohSjVaFn55", + "R/jxHSo1FW40GnfT1CMJG/HoRNWS02j5cxPej+zbTaUZAdd+/8JvL/jh92t/Ew9XWmXOhR6PeIr1iH82", + "n0X+YG7zHQAA//9fnz6pkQEAAA==", +} + +// GetSwagger returns the content of the embedded swagger specification file +// or error if failed to decode +func decodeSpec() ([]byte, error) { + zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) + if err != nil { + return nil, fmt.Errorf("error base64 decoding spec: %w", err) + } + zr, err := gzip.NewReader(bytes.NewReader(zipped)) + if err != nil { + return nil, fmt.Errorf("error decompressing spec: %w", err) + } + var buf bytes.Buffer + _, err = buf.ReadFrom(zr) + if err != nil { + return nil, fmt.Errorf("error decompressing spec: %w", err) + } + + return buf.Bytes(), nil +} + +var rawSpec = decodeSpecCached() + +// a naive cached of a decoded swagger spec +func decodeSpecCached() func() ([]byte, error) { + data, err := decodeSpec() + return func() ([]byte, error) { + return data, err + } +} + +// Constructs a synthetic filesystem for resolving external references when loading openapi specifications. +func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { + res := make(map[string]func() ([]byte, error)) + if len(pathToFile) > 0 { + res[pathToFile] = rawSpec + } + + return res +} + +// GetSwagger returns the Swagger specification corresponding to the generated code +// in this file. The external references of Swagger specification are resolved. +// The logic of resolving external references is tightly connected to "import-mapping" feature. +// Externally referenced files must be embedded in the corresponding golang packages. +// Urls can be supported but this task was out of the scope. +func GetSwagger() (swagger *openapi3.T, err error) { + resolvePath := PathToRawSpec("") + + loader := openapi3.NewLoader() + loader.IsExternalRefsAllowed = true + loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) { + pathToFile := url.String() + pathToFile = path.Clean(pathToFile) + getSpec, ok := resolvePath[pathToFile] + if !ok { + err1 := fmt.Errorf("path not found: %s", pathToFile) + return nil, err1 + } + return getSpec() + } + var specData []byte + specData, err = rawSpec() + if err != nil { + return + } + swagger, err = loader.LoadFromData(specData) + if err != nil { + return + } + return +} diff --git a/internal/test/issues/issue-1529/strict-fiber/spec.yaml b/internal/test/issues/issue-1529/strict-fiber/spec.yaml new file mode 100644 index 0000000000..ca7aae80a3 --- /dev/null +++ b/internal/test/issues/issue-1529/strict-fiber/spec.yaml @@ -0,0 +1,21 @@ +openapi: "3.0.1" +components: + schemas: + Test: + type: object +paths: + /test: + get: + operationId: test + responses: + 200: + content: + application/json: + schema: + $ref: "#/components/schemas/Test" + application/json; profile="Foo": + schema: + $ref: "#/components/schemas/Test" + application/json; profile="Bar": + schema: + $ref: "#/components/schemas/Test" diff --git a/internal/test/issues/issue-1529/strict-iris/config.yaml b/internal/test/issues/issue-1529/strict-iris/config.yaml new file mode 100644 index 0000000000..835b035300 --- /dev/null +++ b/internal/test/issues/issue-1529/strict-iris/config.yaml @@ -0,0 +1,9 @@ +# yaml-language-server: $schema=../../../../../configuration-schema.json +package: issue1529 +generate: + client: true + models: true + embedded-spec: true + iris-server: true + strict-server: true +output: issue1529.gen.go diff --git a/internal/test/issues/issue-1529/strict-iris/doc.go b/internal/test/issues/issue-1529/strict-iris/doc.go new file mode 100644 index 0000000000..ee9c68d2b3 --- /dev/null +++ b/internal/test/issues/issue-1529/strict-iris/doc.go @@ -0,0 +1,3 @@ +package issue1529 + +//go:generate go run github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml diff --git a/internal/test/issues/issue-1529/strict-iris/issue1529.gen.go b/internal/test/issues/issue-1529/strict-iris/issue1529.gen.go new file mode 100644 index 0000000000..6cc09c4c2f --- /dev/null +++ b/internal/test/issues/issue-1529/strict-iris/issue1529.gen.go @@ -0,0 +1,466 @@ +// Package issue1529 provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/livesession/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT. +package issue1529 + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "path" + "strings" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/kataras/iris/v12" + strictiris "github.com/oapi-codegen/runtime/strictmiddleware/iris" +) + +// Test defines model for Test. +type Test = map[string]interface{} + +// RequestEditorFn is the function signature for the RequestEditor callback function +type RequestEditorFn func(ctx context.Context, req *http.Request) error + +// Doer performs HTTP requests. +// +// The standard http.Client implements this interface. +type HttpRequestDoer interface { + Do(req *http.Request) (*http.Response, error) +} + +// Client which conforms to the OpenAPI3 specification for this service. +type Client struct { + // The endpoint of the server conforming to this interface, with scheme, + // https://api.deepmap.com for example. This can contain a path relative + // to the server, such as https://api.deepmap.com/dev-test, and all the + // paths in the swagger spec will be appended to the server. + Server string + + // Doer for performing requests, typically a *http.Client with any + // customized settings, such as certificate chains. + Client HttpRequestDoer + + // A list of callbacks for modifying requests which are generated before sending over + // the network. + RequestEditors []RequestEditorFn +} + +// ClientOption allows setting custom parameters during construction +type ClientOption func(*Client) error + +// Creates a new Client, with reasonable defaults +func NewClient(server string, opts ...ClientOption) (*Client, error) { + // create a client with sane default values + client := Client{ + Server: server, + } + // mutate client and add all optional params + for _, o := range opts { + if err := o(&client); err != nil { + return nil, err + } + } + // ensure the server URL always has a trailing slash + if !strings.HasSuffix(client.Server, "/") { + client.Server += "/" + } + // create httpClient, if not already present + if client.Client == nil { + client.Client = &http.Client{} + } + 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.RequestEditors = append(c.RequestEditors, fn) + return nil + } +} + +// The interface specification for the client above. +type ClientInterface interface { + // Test request + Test(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) +} + +func (c *Client) Test(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewTestRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +// NewTestRequest generates requests for Test +func NewTestRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/test") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { + for _, r := range c.RequestEditors { + if err := r(ctx, req); err != nil { + return err + } + } + for _, r := range additionalEditors { + if err := r(ctx, req); err != nil { + return err + } + } + return 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 { + newBaseURL, err := url.Parse(baseURL) + if err != nil { + return err + } + c.Server = newBaseURL.String() + return nil + } +} + +// ClientWithResponsesInterface is the interface specification for the client with responses above. +type ClientWithResponsesInterface interface { + // TestWithResponse request + TestWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*TestResponse, error) +} + +type TestResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Test + ApplicationjsonProfileBar200 *Test + ApplicationjsonProfileFoo200 *Test +} + +// Status returns HTTPResponse.Status +func (r TestResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r TestResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +// TestWithResponse request returning *TestResponse +func (c *ClientWithResponses) TestWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*TestResponse, error) { + rsp, err := c.Test(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParseTestResponse(rsp) +} + +// ParseTestResponse parses an HTTP response from a TestWithResponse call +func ParseTestResponse(rsp *http.Response) (*TestResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &TestResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case rsp.Header.Get("Content-Type") == "application/json" && rsp.StatusCode == 200: + var dest Test + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case rsp.Header.Get("Content-Type") == "application/json; profile=\"Bar\"" && rsp.StatusCode == 200: + var dest Test + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.ApplicationjsonProfileBar200 = &dest + + case rsp.Header.Get("Content-Type") == "application/json; profile=\"Foo\"" && rsp.StatusCode == 200: + var dest Test + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.ApplicationjsonProfileFoo200 = &dest + + } + + return response, nil +} + +// ServerInterface represents all server handlers. +type ServerInterface interface { + + // (GET /test) + Test(ctx iris.Context) +} + +// ServerInterfaceWrapper converts echo contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface +} + +type MiddlewareFunc iris.Handler + +// Test converts iris context to params. +func (w *ServerInterfaceWrapper) Test(ctx iris.Context) { + + // Invoke the callback with all the unmarshaled arguments + w.Handler.Test(ctx) +} + +// IrisServerOption is the option for iris server +type IrisServerOptions struct { + BaseURL string + Middlewares []MiddlewareFunc +} + +// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. +func RegisterHandlers(router *iris.Application, si ServerInterface) { + RegisterHandlersWithOptions(router, si, IrisServerOptions{}) +} + +// RegisterHandlersWithOptions creates http.Handler with additional options +func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, options IrisServerOptions) { + + wrapper := ServerInterfaceWrapper{ + Handler: si, + } + + router.Get(options.BaseURL+"/test", wrapper.Test) + + router.Build() +} + +type TestRequestObject struct { +} + +type TestResponseObject interface { + VisitTestResponse(ctx iris.Context) error +} + +type Test200JSONResponse Test + +func (response Test200JSONResponse) VisitTestResponse(ctx iris.Context) error { + ctx.ResponseWriter().Header().Set("Content-Type", "application/json") + ctx.StatusCode(200) + + return ctx.JSON(&response) +} + +type Test200ApplicationJSONProfileBarResponse Test + +func (response Test200ApplicationJSONProfileBarResponse) VisitTestResponse(ctx iris.Context) error { + ctx.ResponseWriter().Header().Set("Content-Type", "application/json; profile=\"Bar\"") + ctx.StatusCode(200) + + return ctx.JSON(&response) +} + +type Test200ApplicationJSONProfileFooResponse Test + +func (response Test200ApplicationJSONProfileFooResponse) VisitTestResponse(ctx iris.Context) error { + ctx.ResponseWriter().Header().Set("Content-Type", "application/json; profile=\"Foo\"") + ctx.StatusCode(200) + + return ctx.JSON(&response) +} + +// StrictServerInterface represents all server handlers. +type StrictServerInterface interface { + + // (GET /test) + Test(ctx context.Context, request TestRequestObject) (TestResponseObject, error) +} + +type StrictHandlerFunc = strictiris.StrictIrisHandlerFunc +type StrictMiddlewareFunc = strictiris.StrictIrisMiddlewareFunc + +func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface { + return &strictHandler{ssi: ssi, middlewares: middlewares} +} + +type strictHandler struct { + ssi StrictServerInterface + middlewares []StrictMiddlewareFunc +} + +// Test operation middleware +func (sh *strictHandler) Test(ctx iris.Context) { + var request TestRequestObject + + handler := func(ctx iris.Context, request interface{}) (interface{}, error) { + return sh.ssi.Test(ctx, request.(TestRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "Test") + } + + response, err := handler(ctx, request) + + if err != nil { + ctx.StopWithError(http.StatusBadRequest, err) + return + } else if validResponse, ok := response.(TestResponseObject); ok { + if err := validResponse.VisitTestResponse(ctx); err != nil { + ctx.StopWithError(http.StatusBadRequest, err) + return + } + } else if response != nil { + ctx.Writef("Unexpected response type: %T", response) + return + } +} + +// Base64 encoded, gzipped, json marshaled Swagger object +var swaggerSpec = []string{ + + "H4sIAAAAAAAC/6zPMUsEMRAF4L8iT8twWbWL2FgI9pbXxDjr5cjNDMlYyLL/XRIXFizFad4072NmQZKL", + "ChNbQ1jQ0okucayv1KynfSkhQN7OlAzrujpkngWBP0txECWOmhFwf5gOt3DQaKcheNuIDxohSjVaFn55", + "R/jxHSo1FW40GnfT1CMJG/HoRNWS02j5cxPej+zbTaUZAdd+/8JvL/jh92t/Ew9XWmXOhR6PeIr1iH82", + "n0X+YG7zHQAA//9fnz6pkQEAAA==", +} + +// GetSwagger returns the content of the embedded swagger specification file +// or error if failed to decode +func decodeSpec() ([]byte, error) { + zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) + if err != nil { + return nil, fmt.Errorf("error base64 decoding spec: %w", err) + } + zr, err := gzip.NewReader(bytes.NewReader(zipped)) + if err != nil { + return nil, fmt.Errorf("error decompressing spec: %w", err) + } + var buf bytes.Buffer + _, err = buf.ReadFrom(zr) + if err != nil { + return nil, fmt.Errorf("error decompressing spec: %w", err) + } + + return buf.Bytes(), nil +} + +var rawSpec = decodeSpecCached() + +// a naive cached of a decoded swagger spec +func decodeSpecCached() func() ([]byte, error) { + data, err := decodeSpec() + return func() ([]byte, error) { + return data, err + } +} + +// Constructs a synthetic filesystem for resolving external references when loading openapi specifications. +func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { + res := make(map[string]func() ([]byte, error)) + if len(pathToFile) > 0 { + res[pathToFile] = rawSpec + } + + return res +} + +// GetSwagger returns the Swagger specification corresponding to the generated code +// in this file. The external references of Swagger specification are resolved. +// The logic of resolving external references is tightly connected to "import-mapping" feature. +// Externally referenced files must be embedded in the corresponding golang packages. +// Urls can be supported but this task was out of the scope. +func GetSwagger() (swagger *openapi3.T, err error) { + resolvePath := PathToRawSpec("") + + loader := openapi3.NewLoader() + loader.IsExternalRefsAllowed = true + loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) { + pathToFile := url.String() + pathToFile = path.Clean(pathToFile) + getSpec, ok := resolvePath[pathToFile] + if !ok { + err1 := fmt.Errorf("path not found: %s", pathToFile) + return nil, err1 + } + return getSpec() + } + var specData []byte + specData, err = rawSpec() + if err != nil { + return + } + swagger, err = loader.LoadFromData(specData) + if err != nil { + return + } + return +} diff --git a/internal/test/issues/issue-1529/strict-iris/spec.yaml b/internal/test/issues/issue-1529/strict-iris/spec.yaml new file mode 100644 index 0000000000..ca7aae80a3 --- /dev/null +++ b/internal/test/issues/issue-1529/strict-iris/spec.yaml @@ -0,0 +1,21 @@ +openapi: "3.0.1" +components: + schemas: + Test: + type: object +paths: + /test: + get: + operationId: test + responses: + 200: + content: + application/json: + schema: + $ref: "#/components/schemas/Test" + application/json; profile="Foo": + schema: + $ref: "#/components/schemas/Test" + application/json; profile="Bar": + schema: + $ref: "#/components/schemas/Test" diff --git a/internal/test/issues/issue-1530/config.yaml b/internal/test/issues/issue-1530/config.yaml new file mode 100644 index 0000000000..3cb9f3dd04 --- /dev/null +++ b/internal/test/issues/issue-1530/config.yaml @@ -0,0 +1,4 @@ +package: issue1530 +generate: + models: true +output: issue1530.gen.go \ No newline at end of file diff --git a/internal/test/issues/issue-1530/doc.go b/internal/test/issues/issue-1530/doc.go new file mode 100644 index 0000000000..f5cfb66d39 --- /dev/null +++ b/internal/test/issues/issue-1530/doc.go @@ -0,0 +1,3 @@ +package issue1530 + +//go:generate go run github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml issue1530.yaml diff --git a/internal/test/issues/issue-1530/issue1530.gen.go b/internal/test/issues/issue-1530/issue1530.gen.go new file mode 100644 index 0000000000..54a1368bd6 --- /dev/null +++ b/internal/test/issues/issue-1530/issue1530.gen.go @@ -0,0 +1,126 @@ +// Package issue1530 provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/livesession/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT. +package issue1530 + +import ( + "encoding/json" + "errors" + + "github.com/oapi-codegen/runtime" +) + +// ConfigHttp defines model for ConfigHttp. +type ConfigHttp struct { + ConfigType string `json:"config_type"` + Host string `json:"host"` + Password *string `json:"password,omitempty"` + Port int `json:"port"` + User *string `json:"user,omitempty"` +} + +// ConfigSaveReq defines model for ConfigSaveReq. +type ConfigSaveReq struct { + union json.RawMessage +} + +// ConfigSsh defines model for ConfigSsh. +type ConfigSsh struct { + ConfigType string `json:"config_type"` + Host *string `json:"host,omitempty"` + Port *int `json:"port,omitempty"` + PrivateKey *string `json:"private_key,omitempty"` + User *string `json:"user,omitempty"` +} + +// PostConfigJSONRequestBody defines body for PostConfig for application/json ContentType. +type PostConfigJSONRequestBody = ConfigSaveReq + +// AsConfigHttp returns the union data inside the ConfigSaveReq as a ConfigHttp +func (t ConfigSaveReq) AsConfigHttp() (ConfigHttp, error) { + var body ConfigHttp + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromConfigHttp overwrites any union data inside the ConfigSaveReq as the provided ConfigHttp +func (t *ConfigSaveReq) FromConfigHttp(v ConfigHttp) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeConfigHttp performs a merge with any union data inside the ConfigSaveReq, using the provided ConfigHttp +func (t *ConfigSaveReq) MergeConfigHttp(v ConfigHttp) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsConfigSsh returns the union data inside the ConfigSaveReq as a ConfigSsh +func (t ConfigSaveReq) AsConfigSsh() (ConfigSsh, error) { + var body ConfigSsh + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromConfigSsh overwrites any union data inside the ConfigSaveReq as the provided ConfigSsh +func (t *ConfigSaveReq) FromConfigSsh(v ConfigSsh) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeConfigSsh performs a merge with any union data inside the ConfigSaveReq, using the provided ConfigSsh +func (t *ConfigSaveReq) MergeConfigSsh(v ConfigSsh) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t ConfigSaveReq) Discriminator() (string, error) { + var discriminator struct { + Discriminator string `json:"config_type"` + } + err := json.Unmarshal(t.union, &discriminator) + return discriminator.Discriminator, err +} + +func (t ConfigSaveReq) ValueByDiscriminator() (interface{}, error) { + discriminator, err := t.Discriminator() + if err != nil { + return nil, err + } + switch discriminator { + case "another_server": + return t.AsConfigHttp() + case "apache_server": + return t.AsConfigHttp() + case "ssh_server": + return t.AsConfigSsh() + case "web_server": + return t.AsConfigHttp() + default: + return nil, errors.New("unknown discriminator value: " + discriminator) + } +} + +func (t ConfigSaveReq) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *ConfigSaveReq) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/internal/test/issues/issue-1530/issue1530.yaml b/internal/test/issues/issue-1530/issue1530.yaml new file mode 100644 index 0000000000..222d074b7b --- /dev/null +++ b/internal/test/issues/issue-1530/issue1530.yaml @@ -0,0 +1,57 @@ +paths: + /config: + post: + summary: Save configuration + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ConfigSaveReq" + responses: + "200": + description: Configuration saved successfully +components: + schemas: + ConfigHttp: + type: object + properties: + config_type: + type: string + host: + type: string + port: + type: integer + user: + type: string + password: + type: string + required: + - config_type + - host + - port + ConfigSaveReq: + oneOf: + - $ref: "#/components/schemas/ConfigHttp" + - $ref: "#/components/schemas/ConfigSsh" + discriminator: + propertyName: config_type + mapping: + ssh_server: "#/components/schemas/ConfigSsh" + apache_server: "#/components/schemas/ConfigHttp" + web_server: "#/components/schemas/ConfigHttp" + another_server: "#/components/schemas/ConfigHttp" + ConfigSsh: + type: object + properties: + config_type: + type: string + host: + type: string + port: + type: integer + user: + type: string + private_key: + type: string + required: + - config_type \ No newline at end of file diff --git a/internal/test/issues/issue-1530/issue1530_test.go b/internal/test/issues/issue-1530/issue1530_test.go new file mode 100644 index 0000000000..78ea737970 --- /dev/null +++ b/internal/test/issues/issue-1530/issue1530_test.go @@ -0,0 +1,51 @@ +package issue1530_test + +import ( + "testing" + + issue1530 "github.com/livesession/oapi-codegen/v2/internal/test/issues/issue-1530" + "github.com/stretchr/testify/require" +) + +func TestIssue1530(t *testing.T) { + httpConfigTypes := []string{ + "another_server", + "apache_server", + "web_server", + } + + for _, configType := range httpConfigTypes { + t.Run("http-"+configType, func(t *testing.T) { + saveReq := issue1530.ConfigSaveReq{} + err := saveReq.FromConfigHttp(issue1530.ConfigHttp{ + ConfigType: configType, + Host: "example.com", + }) + require.NoError(t, err) + + cfg, err := saveReq.AsConfigHttp() + require.NoError(t, err) + require.Equal(t, configType, cfg.ConfigType) + + cfgByDiscriminator, err := saveReq.ValueByDiscriminator() + require.NoError(t, err) + require.Equal(t, cfg, cfgByDiscriminator) + }) + } + + t.Run("ssh", func(t *testing.T) { + saveReq := issue1530.ConfigSaveReq{} + err := saveReq.FromConfigSsh(issue1530.ConfigSsh{ + ConfigType: "ssh_server", + }) + require.NoError(t, err) + + cfg, err := saveReq.AsConfigSsh() + require.NoError(t, err) + require.Equal(t, "ssh_server", cfg.ConfigType) + + cfgByDiscriminator, err := saveReq.ValueByDiscriminator() + require.NoError(t, err) + require.Equal(t, cfg, cfgByDiscriminator) + }) +} diff --git a/internal/test/issues/issue-200/config.yaml b/internal/test/issues/issue-200/config.yaml new file mode 100644 index 0000000000..d68804c987 --- /dev/null +++ b/internal/test/issues/issue-200/config.yaml @@ -0,0 +1,7 @@ +# yaml-language-server: $schema=../../../../configuration-schema.json +package: issue200 +generate: + models: true +output: issue200.gen.go +output-options: + resolve-type-name-collisions: true diff --git a/internal/test/issues/issue-200/doc.go b/internal/test/issues/issue-200/doc.go new file mode 100644 index 0000000000..2424e2beb2 --- /dev/null +++ b/internal/test/issues/issue-200/doc.go @@ -0,0 +1,3 @@ +package issue200 + +//go:generate go run github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml diff --git a/internal/test/issues/issue-200/issue200.gen.go b/internal/test/issues/issue-200/issue200.gen.go new file mode 100644 index 0000000000..4d428a28f1 --- /dev/null +++ b/internal/test/issues/issue-200/issue200.gen.go @@ -0,0 +1,295 @@ +// Package issue200 provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/livesession/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT. +package issue200 + +import ( + "encoding/json" + "fmt" +) + +// Bar defines model for Bar. +type Bar struct { + Value *string `json:"value,omitempty"` +} + +// Bar2 defines model for Bar2. +type Bar2 struct { + Value *float32 `json:"value,omitempty"` +} + +// BarParam defines model for BarParam. +type BarParam = []int + +// BarParam2 defines model for BarParam2. +type BarParam2 = []int + +// BarParameter defines model for Bar. +type BarParameter = string + +// BarResponse defines model for Bar. +type BarResponse struct { + Pagination *Bar_Pagination `json:"pagination,omitempty"` + Value1 *Bar `json:"value1,omitempty"` + Value2 *Bar2 `json:"value2,omitempty"` + Value3 *BarParam `json:"value3,omitempty"` + Value4 *BarParam2 `json:"value4,omitempty"` +} + +// Bar_Pagination defines model for Bar.Pagination. +type Bar_Pagination struct { + Page *int `json:"page,omitempty"` + TotalPages *int `json:"totalPages,omitempty"` + AdditionalProperties map[string]string `json:"-"` +} + +// BarRequestBody defines model for Bar. +type BarRequestBody struct { + Metadata *Bar_Metadata `json:"metadata,omitempty"` + Value *int `json:"value,omitempty"` +} + +// Bar_Metadata defines model for Bar.Metadata. +type Bar_Metadata struct { + Key *string `json:"key,omitempty"` + AdditionalProperties map[string]string `json:"-"` +} + +// PostFooJSONBody defines parameters for PostFoo. +type PostFooJSONBody struct { + Metadata *PostFooJSONBody_Metadata `json:"metadata,omitempty"` + Value *int `json:"value,omitempty"` +} + +// PostFooParams defines parameters for PostFoo. +type PostFooParams struct { + Bar *Bar `form:"Bar,omitempty" json:"Bar,omitempty"` +} + +// PostFooJSONBody_Metadata defines parameters for PostFoo. +type PostFooJSONBody_Metadata struct { + Key *string `json:"key,omitempty"` + AdditionalProperties map[string]string `json:"-"` +} + +// PostFooJSONRequestBody defines body for PostFoo for application/json ContentType. +type PostFooJSONRequestBody PostFooJSONBody + +// Getter for additional properties for PostFooJSONBody_Metadata. Returns the specified +// element and whether it was found +func (a PostFooJSONBody_Metadata) Get(fieldName string) (value string, found bool) { + if a.AdditionalProperties != nil { + value, found = a.AdditionalProperties[fieldName] + } + return +} + +// Setter for additional properties for PostFooJSONBody_Metadata +func (a *PostFooJSONBody_Metadata) Set(fieldName string, value string) { + if a.AdditionalProperties == nil { + a.AdditionalProperties = make(map[string]string) + } + a.AdditionalProperties[fieldName] = value +} + +// Override default JSON handling for PostFooJSONBody_Metadata to handle AdditionalProperties +func (a *PostFooJSONBody_Metadata) UnmarshalJSON(b []byte) error { + object := make(map[string]json.RawMessage) + err := json.Unmarshal(b, &object) + if err != nil { + return err + } + + if raw, found := object["key"]; found { + err = json.Unmarshal(raw, &a.Key) + if err != nil { + return fmt.Errorf("error reading 'key': %w", err) + } + delete(object, "key") + } + + 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 fmt.Errorf("error unmarshaling field %s: %w", fieldName, err) + } + a.AdditionalProperties[fieldName] = fieldVal + } + } + return nil +} + +// Override default JSON handling for PostFooJSONBody_Metadata to handle AdditionalProperties +func (a PostFooJSONBody_Metadata) MarshalJSON() ([]byte, error) { + var err error + object := make(map[string]json.RawMessage) + + if a.Key != nil { + object["key"], err = json.Marshal(a.Key) + if err != nil { + return nil, fmt.Errorf("error marshaling 'key': %w", err) + } + } + + for fieldName, field := range a.AdditionalProperties { + object[fieldName], err = json.Marshal(field) + if err != nil { + return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err) + } + } + return json.Marshal(object) +} + +// Getter for additional properties for Bar_Pagination. Returns the specified +// element and whether it was found +func (a Bar_Pagination) Get(fieldName string) (value string, found bool) { + if a.AdditionalProperties != nil { + value, found = a.AdditionalProperties[fieldName] + } + return +} + +// Setter for additional properties for Bar_Pagination +func (a *Bar_Pagination) Set(fieldName string, value string) { + if a.AdditionalProperties == nil { + a.AdditionalProperties = make(map[string]string) + } + a.AdditionalProperties[fieldName] = value +} + +// Override default JSON handling for Bar_Pagination to handle AdditionalProperties +func (a *Bar_Pagination) UnmarshalJSON(b []byte) error { + object := make(map[string]json.RawMessage) + err := json.Unmarshal(b, &object) + if err != nil { + return err + } + + if raw, found := object["page"]; found { + err = json.Unmarshal(raw, &a.Page) + if err != nil { + return fmt.Errorf("error reading 'page': %w", err) + } + delete(object, "page") + } + + if raw, found := object["totalPages"]; found { + err = json.Unmarshal(raw, &a.TotalPages) + if err != nil { + return fmt.Errorf("error reading 'totalPages': %w", err) + } + delete(object, "totalPages") + } + + 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 fmt.Errorf("error unmarshaling field %s: %w", fieldName, err) + } + a.AdditionalProperties[fieldName] = fieldVal + } + } + return nil +} + +// Override default JSON handling for Bar_Pagination to handle AdditionalProperties +func (a Bar_Pagination) MarshalJSON() ([]byte, error) { + var err error + object := make(map[string]json.RawMessage) + + if a.Page != nil { + object["page"], err = json.Marshal(a.Page) + if err != nil { + return nil, fmt.Errorf("error marshaling 'page': %w", err) + } + } + + if a.TotalPages != nil { + object["totalPages"], err = json.Marshal(a.TotalPages) + if err != nil { + return nil, fmt.Errorf("error marshaling 'totalPages': %w", err) + } + } + + for fieldName, field := range a.AdditionalProperties { + object[fieldName], err = json.Marshal(field) + if err != nil { + return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err) + } + } + return json.Marshal(object) +} + +// Getter for additional properties for Bar_Metadata. Returns the specified +// element and whether it was found +func (a Bar_Metadata) Get(fieldName string) (value string, found bool) { + if a.AdditionalProperties != nil { + value, found = a.AdditionalProperties[fieldName] + } + return +} + +// Setter for additional properties for Bar_Metadata +func (a *Bar_Metadata) Set(fieldName string, value string) { + if a.AdditionalProperties == nil { + a.AdditionalProperties = make(map[string]string) + } + a.AdditionalProperties[fieldName] = value +} + +// Override default JSON handling for Bar_Metadata to handle AdditionalProperties +func (a *Bar_Metadata) UnmarshalJSON(b []byte) error { + object := make(map[string]json.RawMessage) + err := json.Unmarshal(b, &object) + if err != nil { + return err + } + + if raw, found := object["key"]; found { + err = json.Unmarshal(raw, &a.Key) + if err != nil { + return fmt.Errorf("error reading 'key': %w", err) + } + delete(object, "key") + } + + 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 fmt.Errorf("error unmarshaling field %s: %w", fieldName, err) + } + a.AdditionalProperties[fieldName] = fieldVal + } + } + return nil +} + +// Override default JSON handling for Bar_Metadata to handle AdditionalProperties +func (a Bar_Metadata) MarshalJSON() ([]byte, error) { + var err error + object := make(map[string]json.RawMessage) + + if a.Key != nil { + object["key"], err = json.Marshal(a.Key) + if err != nil { + return nil, fmt.Errorf("error marshaling 'key': %w", err) + } + } + + for fieldName, field := range a.AdditionalProperties { + object[fieldName], err = json.Marshal(field) + if err != nil { + return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err) + } + } + return json.Marshal(object) +} diff --git a/internal/test/issues/issue-200/issue200_test.go b/internal/test/issues/issue-200/issue200_test.go new file mode 100644 index 0000000000..96fdb62e8b --- /dev/null +++ b/internal/test/issues/issue-200/issue200_test.go @@ -0,0 +1,63 @@ +package issue200 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +// TestDuplicateTypeNamesCompile verifies that when the same name "Bar" is used +// across components/schemas, components/parameters, components/responses, +// components/requestBodies, and components/headers, the codegen produces +// distinct, compilable types with component-based suffixes. +// +// If the auto-rename logic breaks, this test will fail to compile. +func TestDuplicateTypeNamesCompile(t *testing.T) { + // Schema type: Bar (no suffix, first definition wins) + _ = Bar{Value: ptr("hello")} + + // Schema types with unique names (no collision) + _ = Bar2{Value: ptr(float32(1.0))} + _ = BarParam([]int{1, 2, 3}) + _ = BarParam2([]int{4, 5, 6}) + + // Parameter type: BarParameter (was "Bar" in components/parameters) + _ = BarParameter("query-value") + + // Response type: BarResponse (was "Bar" in components/responses) + _ = BarResponse{ + Value1: &Bar{Value: ptr("v1")}, + Value2: &Bar2{Value: ptr(float32(2.0))}, + Value3: &BarParam{1}, + Value4: &BarParam2{2}, + } + + // RequestBody type: BarRequestBody (was "Bar" in components/requestBodies) + _ = BarRequestBody{Value: ptr(42)} + + // Inline nested object with additionalProperties inside a response + // must produce a named AdditionalType (not get silently dropped). + _ = Bar_Pagination{ + Page: ptr(1), + TotalPages: ptr(10), + AdditionalProperties: map[string]string{"cursor": "abc"}, + } + + // Inline nested object with additionalProperties inside a requestBody + // must produce a named AdditionalType (not get silently dropped). + _ = Bar_Metadata{ + Key: ptr("k"), + AdditionalProperties: map[string]string{"extra": "val"}, + } + + // Operation-derived types + _ = PostFooParams{Bar: &Bar{}} + _ = PostFooJSONBody{Value: ptr(99)} + _ = PostFooJSONRequestBody{Value: ptr(100)} + + assert.True(t, true, "all duplicate-named types resolved and compiled") +} + +func ptr[T any](v T) *T { + return &v +} diff --git a/internal/test/issues/issue-200/spec.yaml b/internal/test/issues/issue-200/spec.yaml new file mode 100644 index 0000000000..2a68f71694 --- /dev/null +++ b/internal/test/issues/issue-200/spec.yaml @@ -0,0 +1,96 @@ +openapi: 3.0.1 + +info: + title: "Duplicate type names test" + version: 0.0.0 + +paths: + /foo: + post: + operationId: postFoo + parameters: + - $ref: '#/components/parameters/Bar' + requestBody: + $ref: '#/components/requestBodies/Bar' + responses: + 200: + $ref: '#/components/responses/Bar' + +components: + schemas: + Bar: + type: object + properties: + value: + type: string + Bar2: + type: object + properties: + value: + type: number + BarParam: + type: array + items: + type: integer + BarParam2: + type: array + items: + type: integer + + headers: + Bar: + schema: + type: boolean + + parameters: + Bar: + name: Bar + in: query + schema: + type: string + + requestBodies: + Bar: + content: + application/json: + schema: + type: object + properties: + value: + type: integer + metadata: + type: object + properties: + key: + type: string + additionalProperties: + type: string + + responses: + Bar: + description: Bar response + headers: + X-Bar: + $ref: '#/components/headers/Bar' + content: + application/json: + schema: + type: object + properties: + value1: + $ref: '#/components/schemas/Bar' + value2: + $ref: '#/components/schemas/Bar2' + value3: + $ref: '#/components/schemas/BarParam' + value4: + $ref: '#/components/schemas/BarParam2' + pagination: + type: object + properties: + page: + type: integer + totalPages: + type: integer + additionalProperties: + type: string diff --git a/internal/test/issues/issue-2031/prefer/config.yaml b/internal/test/issues/issue-2031/prefer/config.yaml new file mode 100644 index 0000000000..4ec155a835 --- /dev/null +++ b/internal/test/issues/issue-2031/prefer/config.yaml @@ -0,0 +1,7 @@ +package: issue2031 +generate: + models: true + client: true +output-options: + prefer-skip-optional-pointer: true +output: issue2031.gen.go diff --git a/internal/test/issues/issue-2031/prefer/generate.go b/internal/test/issues/issue-2031/prefer/generate.go new file mode 100644 index 0000000000..753e6d21eb --- /dev/null +++ b/internal/test/issues/issue-2031/prefer/generate.go @@ -0,0 +1,3 @@ +package issue2031 + +//go:generate go run github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml openapi.yaml diff --git a/internal/test/issues/issue-2031/prefer/issue2031.gen.go b/internal/test/issues/issue-2031/prefer/issue2031.gen.go new file mode 100644 index 0000000000..bc276bcaa2 --- /dev/null +++ b/internal/test/issues/issue-2031/prefer/issue2031.gen.go @@ -0,0 +1,251 @@ +// Package issue2031 provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/livesession/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT. +package issue2031 + +import ( + "context" + "fmt" + "io" + "net/http" + "net/url" + "strings" + + "github.com/oapi-codegen/runtime" +) + +// GetTestParams defines parameters for GetTest. +type GetTestParams struct { + UserIds []int `form:"user_ids[],omitempty" json:"user_ids[],omitempty"` +} + +// RequestEditorFn is the function signature for the RequestEditor callback function +type RequestEditorFn func(ctx context.Context, req *http.Request) error + +// Doer performs HTTP requests. +// +// The standard http.Client implements this interface. +type HttpRequestDoer interface { + Do(req *http.Request) (*http.Response, error) +} + +// Client which conforms to the OpenAPI3 specification for this service. +type Client struct { + // The endpoint of the server conforming to this interface, with scheme, + // https://api.deepmap.com for example. This can contain a path relative + // to the server, such as https://api.deepmap.com/dev-test, and all the + // paths in the swagger spec will be appended to the server. + Server string + + // Doer for performing requests, typically a *http.Client with any + // customized settings, such as certificate chains. + Client HttpRequestDoer + + // A list of callbacks for modifying requests which are generated before sending over + // the network. + RequestEditors []RequestEditorFn +} + +// ClientOption allows setting custom parameters during construction +type ClientOption func(*Client) error + +// Creates a new Client, with reasonable defaults +func NewClient(server string, opts ...ClientOption) (*Client, error) { + // create a client with sane default values + client := Client{ + Server: server, + } + // mutate client and add all optional params + for _, o := range opts { + if err := o(&client); err != nil { + return nil, err + } + } + // ensure the server URL always has a trailing slash + if !strings.HasSuffix(client.Server, "/") { + client.Server += "/" + } + // create httpClient, if not already present + if client.Client == nil { + client.Client = &http.Client{} + } + 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.RequestEditors = append(c.RequestEditors, fn) + return nil + } +} + +// The interface specification for the client above. +type ClientInterface interface { + // GetTest request + GetTest(ctx context.Context, params *GetTestParams, reqEditors ...RequestEditorFn) (*http.Response, error) +} + +func (c *Client) GetTest(ctx context.Context, params *GetTestParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetTestRequest(c.Server, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +// NewGetTestRequest generates requests for GetTest +func NewGetTestRequest(server string, params *GetTestParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/test") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + if params != nil { + queryValues := queryURL.Query() + + if params.UserIds != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "user_ids[]", runtime.ParamLocationQuery, params.UserIds); 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 +} + +func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { + for _, r := range c.RequestEditors { + if err := r(ctx, req); err != nil { + return err + } + } + for _, r := range additionalEditors { + if err := r(ctx, req); err != nil { + return err + } + } + return 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 { + newBaseURL, err := url.Parse(baseURL) + if err != nil { + return err + } + c.Server = newBaseURL.String() + return nil + } +} + +// ClientWithResponsesInterface is the interface specification for the client with responses above. +type ClientWithResponsesInterface interface { + // GetTestWithResponse request + GetTestWithResponse(ctx context.Context, params *GetTestParams, reqEditors ...RequestEditorFn) (*GetTestResponse, error) +} + +type GetTestResponse struct { + Body []byte + HTTPResponse *http.Response +} + +// Status returns HTTPResponse.Status +func (r GetTestResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetTestResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +// GetTestWithResponse request returning *GetTestResponse +func (c *ClientWithResponses) GetTestWithResponse(ctx context.Context, params *GetTestParams, reqEditors ...RequestEditorFn) (*GetTestResponse, error) { + rsp, err := c.GetTest(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetTestResponse(rsp) +} + +// ParseGetTestResponse parses an HTTP response from a GetTestWithResponse call +func ParseGetTestResponse(rsp *http.Response) (*GetTestResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetTestResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + return response, nil +} diff --git a/internal/test/issues/issue-2031/prefer/issue2031_test.go b/internal/test/issues/issue-2031/prefer/issue2031_test.go new file mode 100644 index 0000000000..cd0c55c8dd --- /dev/null +++ b/internal/test/issues/issue-2031/prefer/issue2031_test.go @@ -0,0 +1,63 @@ +package issue2031 + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewGetTestRequest(t *testing.T) { + t.Run("does not add the user_ids[] parameter if zero value", func(t *testing.T) { + params := GetTestParams{} + + req, err := NewGetTestRequest("https://localhost", ¶ms) + require.NoError(t, err) + + assert.Equal(t, "https://localhost/test", req.URL.String()) + }) + + t.Run("does not add the user_ids[] parameter if nil", func(t *testing.T) { + params := GetTestParams{ + UserIds: nil, + } + + req, err := NewGetTestRequest("https://localhost", ¶ms) + require.NoError(t, err) + + assert.Equal(t, "https://localhost/test", req.URL.String()) + }) + + t.Run("adds the user_ids[] parameter if an explicitly initialised empty array", func(t *testing.T) { + params := GetTestParams{ + UserIds: []int{}, + } + + req, err := NewGetTestRequest("https://localhost", ¶ms) + require.NoError(t, err) + + assert.Equal(t, "https://localhost/test?user_ids%5B%5D=", req.URL.String()) + }) + + t.Run("adds the user_ids[] parameter if array contains a value", func(t *testing.T) { + params := GetTestParams{ + UserIds: []int{1}, + } + + req, err := NewGetTestRequest("https://localhost", ¶ms) + require.NoError(t, err) + + assert.Equal(t, "https://localhost/test?user_ids%5B%5D=1", req.URL.String()) + }) + + t.Run("handles multiple user_ids[] parameters", func(t *testing.T) { + params := GetTestParams{ + UserIds: []int{1, 100}, + } + + req, err := NewGetTestRequest("https://localhost", ¶ms) + require.NoError(t, err) + + assert.Equal(t, "https://localhost/test?user_ids%5B%5D=1&user_ids%5B%5D=100", req.URL.String()) + }) +} diff --git a/internal/test/issues/issue-2031/prefer/openapi.yaml b/internal/test/issues/issue-2031/prefer/openapi.yaml new file mode 100644 index 0000000000..d88d8df2fb --- /dev/null +++ b/internal/test/issues/issue-2031/prefer/openapi.yaml @@ -0,0 +1,17 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Issue 2031 +paths: + /test: + get: + parameters: + - name: "user_ids[]" + in: query + schema: + type: array + items: + type: integer + style: form + explode: true + required: false diff --git a/internal/test/issues/issue-2185/config.yaml b/internal/test/issues/issue-2185/config.yaml new file mode 100644 index 0000000000..71a7ba132e --- /dev/null +++ b/internal/test/issues/issue-2185/config.yaml @@ -0,0 +1,8 @@ +# yaml-language-server: $schema=../../../../configuration-schema.json +package: issue2185 +output: issue2185.gen.go +generate: + models: true +output-options: + skip-prune: true + nullable-type: true diff --git a/internal/test/issues/issue-2185/generate.go b/internal/test/issues/issue-2185/generate.go new file mode 100644 index 0000000000..f8ae327fd9 --- /dev/null +++ b/internal/test/issues/issue-2185/generate.go @@ -0,0 +1,3 @@ +package issue2185 + +//go:generate go run github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml diff --git a/internal/test/issues/issue-2185/issue2185.gen.go b/internal/test/issues/issue-2185/issue2185.gen.go new file mode 100644 index 0000000000..c8a1d1e7f3 --- /dev/null +++ b/internal/test/issues/issue-2185/issue2185.gen.go @@ -0,0 +1,13 @@ +// Package issue2185 provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/livesession/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT. +package issue2185 + +import ( + "github.com/oapi-codegen/nullable" +) + +// Container defines model for Container. +type Container struct { + MayBeNull []nullable.Nullable[string] `json:"may-be-null"` +} diff --git a/internal/test/issues/issue-2185/issue2185_test.go b/internal/test/issues/issue-2185/issue2185_test.go new file mode 100644 index 0000000000..cc98e2b4d3 --- /dev/null +++ b/internal/test/issues/issue-2185/issue2185_test.go @@ -0,0 +1,19 @@ +package issue2185 + +import ( + "testing" + + "github.com/oapi-codegen/nullable" + "github.com/stretchr/testify/require" +) + +func TestContainer_UsesNullableType(t *testing.T) { + c := Container{ + MayBeNull: []nullable.Nullable[string]{ + nullable.NewNullNullable[string](), + }, + } + + require.Len(t, c.MayBeNull, 1) + require.True(t, c.MayBeNull[0].IsNull()) +} diff --git a/internal/test/issues/issue-2185/spec.yaml b/internal/test/issues/issue-2185/spec.yaml new file mode 100644 index 0000000000..814048bc8f --- /dev/null +++ b/internal/test/issues/issue-2185/spec.yaml @@ -0,0 +1,15 @@ +openapi: "3.0.3" +info: + title: test + version: 1.0.0 +components: + schemas: + Container: + required: + - "may-be-null" + properties: + "may-be-null": + type: array + items: + type: string + nullable: true diff --git a/internal/test/issues/issue-2190/config.yaml b/internal/test/issues/issue-2190/config.yaml new file mode 100644 index 0000000000..da89951cdc --- /dev/null +++ b/internal/test/issues/issue-2190/config.yaml @@ -0,0 +1,9 @@ +package: issue2190 +output: issue2190.gen.go +generate: + std-http-server: true + strict-server: true + models: true + client: true +output-options: + nullable-type: true diff --git a/internal/test/issues/issue-2190/generate.go b/internal/test/issues/issue-2190/generate.go new file mode 100644 index 0000000000..6a4b4f4cd4 --- /dev/null +++ b/internal/test/issues/issue-2190/generate.go @@ -0,0 +1,3 @@ +package issue2190 + +//go:generate go run github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml diff --git a/internal/test/issues/issue-2190/issue2190.gen.go b/internal/test/issues/issue-2190/issue2190.gen.go new file mode 100644 index 0000000000..ee6e4b998f --- /dev/null +++ b/internal/test/issues/issue-2190/issue2190.gen.go @@ -0,0 +1,486 @@ +//go:build go1.22 + +// Package issue2190 provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/livesession/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT. +package issue2190 + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "strings" + + strictnethttp "github.com/oapi-codegen/runtime/strictmiddleware/nethttp" +) + +// Success defines model for Success. +type Success = string + +// RequestEditorFn is the function signature for the RequestEditor callback function +type RequestEditorFn func(ctx context.Context, req *http.Request) error + +// Doer performs HTTP requests. +// +// The standard http.Client implements this interface. +type HttpRequestDoer interface { + Do(req *http.Request) (*http.Response, error) +} + +// Client which conforms to the OpenAPI3 specification for this service. +type Client struct { + // The endpoint of the server conforming to this interface, with scheme, + // https://api.deepmap.com for example. This can contain a path relative + // to the server, such as https://api.deepmap.com/dev-test, and all the + // paths in the swagger spec will be appended to the server. + Server string + + // Doer for performing requests, typically a *http.Client with any + // customized settings, such as certificate chains. + Client HttpRequestDoer + + // A list of callbacks for modifying requests which are generated before sending over + // the network. + RequestEditors []RequestEditorFn +} + +// ClientOption allows setting custom parameters during construction +type ClientOption func(*Client) error + +// Creates a new Client, with reasonable defaults +func NewClient(server string, opts ...ClientOption) (*Client, error) { + // create a client with sane default values + client := Client{ + Server: server, + } + // mutate client and add all optional params + for _, o := range opts { + if err := o(&client); err != nil { + return nil, err + } + } + // ensure the server URL always has a trailing slash + if !strings.HasSuffix(client.Server, "/") { + client.Server += "/" + } + // create httpClient, if not already present + if client.Client == nil { + client.Client = &http.Client{} + } + 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.RequestEditors = append(c.RequestEditors, fn) + return nil + } +} + +// The interface specification for the client above. +type ClientInterface interface { + // GetTest request + GetTest(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) +} + +func (c *Client) GetTest(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetTestRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +// NewGetTestRequest generates requests for GetTest +func NewGetTestRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/v1/test") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { + for _, r := range c.RequestEditors { + if err := r(ctx, req); err != nil { + return err + } + } + for _, r := range additionalEditors { + if err := r(ctx, req); err != nil { + return err + } + } + return 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 { + newBaseURL, err := url.Parse(baseURL) + if err != nil { + return err + } + c.Server = newBaseURL.String() + return nil + } +} + +// ClientWithResponsesInterface is the interface specification for the client with responses above. +type ClientWithResponsesInterface interface { + // GetTestWithResponse request + GetTestWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetTestResponse, error) +} + +type GetTestResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Success +} + +// Status returns HTTPResponse.Status +func (r GetTestResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetTestResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +// GetTestWithResponse request returning *GetTestResponse +func (c *ClientWithResponses) GetTestWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetTestResponse, error) { + rsp, err := c.GetTest(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetTestResponse(rsp) +} + +// ParseGetTestResponse parses an HTTP response from a GetTestWithResponse call +func ParseGetTestResponse(rsp *http.Response) (*GetTestResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetTestResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest Success + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ServerInterface represents all server handlers. +type ServerInterface interface { + + // (GET /v1/test) + GetTest(w http.ResponseWriter, r *http.Request) +} + +// ServerInterfaceWrapper converts contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface + HandlerMiddlewares []MiddlewareFunc + ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) +} + +type MiddlewareFunc func(http.Handler) http.Handler + +// GetTest operation middleware +func (siw *ServerInterfaceWrapper) GetTest(w http.ResponseWriter, r *http.Request) { + + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.GetTest(w, r) + })) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r) +} + +type UnescapedCookieParamError struct { + ParamName string + Err error +} + +func (e *UnescapedCookieParamError) Error() string { + return fmt.Sprintf("error unescaping cookie parameter '%s'", e.ParamName) +} + +func (e *UnescapedCookieParamError) Unwrap() error { + return e.Err +} + +type UnmarshalingParamError struct { + ParamName string + Err error +} + +func (e *UnmarshalingParamError) Error() string { + return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +} + +func (e *UnmarshalingParamError) Unwrap() error { + return e.Err +} + +type RequiredParamError struct { + ParamName string +} + +func (e *RequiredParamError) Error() string { + return fmt.Sprintf("Query argument %s is required, but not found", e.ParamName) +} + +type RequiredHeaderError struct { + ParamName string + Err error +} + +func (e *RequiredHeaderError) Error() string { + return fmt.Sprintf("Header parameter %s is required, but not found", e.ParamName) +} + +func (e *RequiredHeaderError) Unwrap() error { + return e.Err +} + +type InvalidParamFormatError struct { + ParamName string + Err error +} + +func (e *InvalidParamFormatError) Error() string { + return fmt.Sprintf("Invalid format for parameter %s: %s", e.ParamName, e.Err.Error()) +} + +func (e *InvalidParamFormatError) Unwrap() error { + return e.Err +} + +type TooManyValuesForParamError struct { + ParamName string + Count int +} + +func (e *TooManyValuesForParamError) Error() string { + return fmt.Sprintf("Expected one value for %s, got %d", e.ParamName, e.Count) +} + +// Handler creates http.Handler with routing matching OpenAPI spec. +func Handler(si ServerInterface) http.Handler { + return HandlerWithOptions(si, StdHTTPServerOptions{}) +} + +// ServeMux is an abstraction of http.ServeMux. +type ServeMux interface { + HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) + ServeHTTP(w http.ResponseWriter, r *http.Request) +} + +type StdHTTPServerOptions struct { + BaseURL string + BaseRouter ServeMux + Middlewares []MiddlewareFunc + ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) +} + +// HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux. +func HandlerFromMux(si ServerInterface, m ServeMux) http.Handler { + return HandlerWithOptions(si, StdHTTPServerOptions{ + BaseRouter: m, + }) +} + +func HandlerFromMuxWithBaseURL(si ServerInterface, m ServeMux, baseURL string) http.Handler { + return HandlerWithOptions(si, StdHTTPServerOptions{ + BaseURL: baseURL, + BaseRouter: m, + }) +} + +// HandlerWithOptions creates http.Handler with additional options +func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.Handler { + m := options.BaseRouter + + if m == nil { + m = http.NewServeMux() + } + if options.ErrorHandlerFunc == nil { + options.ErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + + wrapper := ServerInterfaceWrapper{ + Handler: si, + HandlerMiddlewares: options.Middlewares, + ErrorHandlerFunc: options.ErrorHandlerFunc, + } + + m.HandleFunc("GET "+options.BaseURL+"/v1/test", wrapper.GetTest) + + return m +} + +type SuccessJSONResponse string + +type UnauthorizedTextResponse string + +type GetTestRequestObject struct { +} + +type GetTestResponseObject interface { + VisitGetTestResponse(w http.ResponseWriter) error +} + +type GetTest200JSONResponse struct{ SuccessJSONResponse } + +func (response GetTest200JSONResponse) VisitGetTestResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type GetTest401TextResponse UnauthorizedTextResponse + +func (response GetTest401TextResponse) VisitGetTestResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(401) + + _, err := w.Write([]byte(response)) + return err +} + +// StrictServerInterface represents all server handlers. +type StrictServerInterface interface { + + // (GET /v1/test) + GetTest(ctx context.Context, request GetTestRequestObject) (GetTestResponseObject, error) +} + +type StrictHandlerFunc = strictnethttp.StrictHTTPHandlerFunc +type StrictMiddlewareFunc = strictnethttp.StrictHTTPMiddlewareFunc + +type StrictHTTPServerOptions struct { + RequestErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) + ResponseErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) +} + +func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface { + return &strictHandler{ssi: ssi, middlewares: middlewares, options: StrictHTTPServerOptions{ + RequestErrorHandlerFunc: func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + }, + ResponseErrorHandlerFunc: func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + }, + }} +} + +func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} +} + +type strictHandler struct { + ssi StrictServerInterface + middlewares []StrictMiddlewareFunc + options StrictHTTPServerOptions +} + +// GetTest operation middleware +func (sh *strictHandler) GetTest(w http.ResponseWriter, r *http.Request) { + var request GetTestRequestObject + + handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { + return sh.ssi.GetTest(ctx, request.(GetTestRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "GetTest") + } + + response, err := handler(r.Context(), w, r, request) + + if err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } else if validResponse, ok := response.(GetTestResponseObject); ok { + if err := validResponse.VisitGetTestResponse(w); err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } + } else if response != nil { + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + } +} diff --git a/internal/test/issues/issue-2190/issue2190_test.go b/internal/test/issues/issue-2190/issue2190_test.go new file mode 100644 index 0000000000..8dc7a0b075 --- /dev/null +++ b/internal/test/issues/issue-2190/issue2190_test.go @@ -0,0 +1,37 @@ +package issue2190 + +import ( + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestGetTest401TextResponse verifies that the generated VisitGetTestResponse +// method on GetTest401TextResponse produces a valid text/plain 401 response. +// This is a regression test for https://github.com/oapi-codegen/oapi-codegen/issues/2190 +// where the generated code tried to do []byte(response) on a struct type, +// which does not compile. +func TestGetTest401TextResponse(t *testing.T) { + resp := GetTest401TextResponse("Unauthorized") + w := httptest.NewRecorder() + + err := resp.VisitGetTestResponse(w) + require.NoError(t, err) + assert.Equal(t, 401, w.Code) + assert.Equal(t, "text/plain", w.Header().Get("Content-Type")) + assert.Equal(t, "Unauthorized", w.Body.String()) +} + +// TestGetTest200JSONResponse verifies that the 200 JSON response path also works. +func TestGetTest200JSONResponse(t *testing.T) { + resp := GetTest200JSONResponse{SuccessJSONResponse("hello")} + w := httptest.NewRecorder() + + err := resp.VisitGetTestResponse(w) + require.NoError(t, err) + assert.Equal(t, 200, w.Code) + assert.Equal(t, "application/json", w.Header().Get("Content-Type")) + assert.Contains(t, w.Body.String(), "hello") +} diff --git a/internal/test/issues/issue-2190/spec.yaml b/internal/test/issues/issue-2190/spec.yaml new file mode 100644 index 0000000000..2844100e3d --- /dev/null +++ b/internal/test/issues/issue-2190/spec.yaml @@ -0,0 +1,30 @@ +openapi: 3.0.3 +info: + title: test + version: 1.0.0 +servers: + - url: https://te.st +paths: + /v1/test: + get: + operationId: GetTest + responses: + "200": + $ref: "#/components/responses/Success" + "401": + $ref: "#/components/responses/Unauthorized" +components: + responses: + Success: + description: Success + content: + application/json: + schema: + type: string + Unauthorized: + description: Unauthorized + content: + text/plain: + schema: + type: string + example: "Unauthorized" diff --git a/internal/test/issues/issue-2232/config.yaml b/internal/test/issues/issue-2232/config.yaml new file mode 100644 index 0000000000..6368de1d4d --- /dev/null +++ b/internal/test/issues/issue-2232/config.yaml @@ -0,0 +1,5 @@ +package: issue2232 +output: issue2232.gen.go +generate: + std-http-server: true + models: true diff --git a/internal/test/issues/issue-2232/generate.go b/internal/test/issues/issue-2232/generate.go new file mode 100644 index 0000000000..5a47c7865c --- /dev/null +++ b/internal/test/issues/issue-2232/generate.go @@ -0,0 +1,3 @@ +package issue2232 + +//go:generate go run github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml diff --git a/internal/test/issues/issue-2232/issue2232.gen.go b/internal/test/issues/issue-2232/issue2232.gen.go new file mode 100644 index 0000000000..113440a3d8 --- /dev/null +++ b/internal/test/issues/issue-2232/issue2232.gen.go @@ -0,0 +1,260 @@ +//go:build go1.22 + +// Package issue2232 provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/livesession/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT. +package issue2232 + +import ( + "fmt" + "net/http" + + "github.com/oapi-codegen/runtime" +) + +// Defines values for GetEndpointParamsEnvParamLevel. +const ( + GetEndpointParamsEnvParamLevelDev GetEndpointParamsEnvParamLevel = "dev" + GetEndpointParamsEnvParamLevelLive GetEndpointParamsEnvParamLevel = "live" +) + +// Valid indicates whether the value is a known member of the GetEndpointParamsEnvParamLevel enum. +func (e GetEndpointParamsEnvParamLevel) Valid() bool { + switch e { + case GetEndpointParamsEnvParamLevelDev: + return true + case GetEndpointParamsEnvParamLevelLive: + return true + default: + return false + } +} + +// Defines values for GetEndpointParamsEnvSchemaLevel. +const ( + GetEndpointParamsEnvSchemaLevelDev GetEndpointParamsEnvSchemaLevel = "dev" + GetEndpointParamsEnvSchemaLevelLive GetEndpointParamsEnvSchemaLevel = "live" +) + +// Valid indicates whether the value is a known member of the GetEndpointParamsEnvSchemaLevel enum. +func (e GetEndpointParamsEnvSchemaLevel) Valid() bool { + switch e { + case GetEndpointParamsEnvSchemaLevelDev: + return true + case GetEndpointParamsEnvSchemaLevelLive: + return true + default: + return false + } +} + +// GetEndpointParams defines parameters for GetEndpoint. +type GetEndpointParams struct { + EnvParamLevel GetEndpointParamsEnvParamLevel `form:"env_param_level" json:"env_param_level" validate:"required,oneof=dev live"` + EnvSchemaLevel GetEndpointParamsEnvSchemaLevel `form:"env_schema_level" json:"env_schema_level" validate:"required,oneof=dev live"` + Limit *int `form:"limit,omitempty" json:"limit,omitempty" validate:"min=0,max=100"` +} + +// GetEndpointParamsEnvParamLevel defines parameters for GetEndpoint. +type GetEndpointParamsEnvParamLevel string + +// GetEndpointParamsEnvSchemaLevel defines parameters for GetEndpoint. +type GetEndpointParamsEnvSchemaLevel string + +// ServerInterface represents all server handlers. +type ServerInterface interface { + + // (GET /v1/endpoint) + GetEndpoint(w http.ResponseWriter, r *http.Request, params GetEndpointParams) +} + +// ServerInterfaceWrapper converts contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface + HandlerMiddlewares []MiddlewareFunc + ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) +} + +type MiddlewareFunc func(http.Handler) http.Handler + +// GetEndpoint operation middleware +func (siw *ServerInterfaceWrapper) GetEndpoint(w http.ResponseWriter, r *http.Request) { + + var err error + + // Parameter object where we will unmarshal all parameters from the context + var params GetEndpointParams + + // ------------- Required query parameter "env_param_level" ------------- + + if paramValue := r.URL.Query().Get("env_param_level"); paramValue != "" { + + } else { + siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "env_param_level"}) + return + } + + err = runtime.BindQueryParameter("form", true, true, "env_param_level", r.URL.Query(), ¶ms.EnvParamLevel) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "env_param_level", Err: err}) + return + } + + // ------------- Required query parameter "env_schema_level" ------------- + + if paramValue := r.URL.Query().Get("env_schema_level"); paramValue != "" { + + } else { + siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "env_schema_level"}) + return + } + + err = runtime.BindQueryParameter("form", true, true, "env_schema_level", r.URL.Query(), ¶ms.EnvSchemaLevel) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "env_schema_level", Err: err}) + return + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameter("form", true, false, "limit", r.URL.Query(), ¶ms.Limit) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "limit", Err: err}) + return + } + + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.GetEndpoint(w, r, params) + })) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r) +} + +type UnescapedCookieParamError struct { + ParamName string + Err error +} + +func (e *UnescapedCookieParamError) Error() string { + return fmt.Sprintf("error unescaping cookie parameter '%s'", e.ParamName) +} + +func (e *UnescapedCookieParamError) Unwrap() error { + return e.Err +} + +type UnmarshalingParamError struct { + ParamName string + Err error +} + +func (e *UnmarshalingParamError) Error() string { + return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +} + +func (e *UnmarshalingParamError) Unwrap() error { + return e.Err +} + +type RequiredParamError struct { + ParamName string +} + +func (e *RequiredParamError) Error() string { + return fmt.Sprintf("Query argument %s is required, but not found", e.ParamName) +} + +type RequiredHeaderError struct { + ParamName string + Err error +} + +func (e *RequiredHeaderError) Error() string { + return fmt.Sprintf("Header parameter %s is required, but not found", e.ParamName) +} + +func (e *RequiredHeaderError) Unwrap() error { + return e.Err +} + +type InvalidParamFormatError struct { + ParamName string + Err error +} + +func (e *InvalidParamFormatError) Error() string { + return fmt.Sprintf("Invalid format for parameter %s: %s", e.ParamName, e.Err.Error()) +} + +func (e *InvalidParamFormatError) Unwrap() error { + return e.Err +} + +type TooManyValuesForParamError struct { + ParamName string + Count int +} + +func (e *TooManyValuesForParamError) Error() string { + return fmt.Sprintf("Expected one value for %s, got %d", e.ParamName, e.Count) +} + +// Handler creates http.Handler with routing matching OpenAPI spec. +func Handler(si ServerInterface) http.Handler { + return HandlerWithOptions(si, StdHTTPServerOptions{}) +} + +// ServeMux is an abstraction of http.ServeMux. +type ServeMux interface { + HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) + ServeHTTP(w http.ResponseWriter, r *http.Request) +} + +type StdHTTPServerOptions struct { + BaseURL string + BaseRouter ServeMux + Middlewares []MiddlewareFunc + ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) +} + +// HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux. +func HandlerFromMux(si ServerInterface, m ServeMux) http.Handler { + return HandlerWithOptions(si, StdHTTPServerOptions{ + BaseRouter: m, + }) +} + +func HandlerFromMuxWithBaseURL(si ServerInterface, m ServeMux, baseURL string) http.Handler { + return HandlerWithOptions(si, StdHTTPServerOptions{ + BaseURL: baseURL, + BaseRouter: m, + }) +} + +// HandlerWithOptions creates http.Handler with additional options +func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.Handler { + m := options.BaseRouter + + if m == nil { + m = http.NewServeMux() + } + if options.ErrorHandlerFunc == nil { + options.ErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + + wrapper := ServerInterfaceWrapper{ + Handler: si, + HandlerMiddlewares: options.Middlewares, + ErrorHandlerFunc: options.ErrorHandlerFunc, + } + + m.HandleFunc("GET "+options.BaseURL+"/v1/endpoint", wrapper.GetEndpoint) + + return m +} diff --git a/internal/test/issues/issue-2232/issue2232_test.go b/internal/test/issues/issue-2232/issue2232_test.go new file mode 100644 index 0000000000..a8ae51836e --- /dev/null +++ b/internal/test/issues/issue-2232/issue2232_test.go @@ -0,0 +1,41 @@ +package issue2232 + +import ( + "reflect" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestExtraTagsOnQueryParams verifies that x-oapi-codegen-extra-tags is applied +// to query parameter struct fields regardless of whether the extension is placed +// at the parameter level or at the schema level within the parameter. +// This is a regression test for https://github.com/oapi-codegen/oapi-codegen/issues/2232 +func TestExtraTagsOnQueryParams(t *testing.T) { + paramType := reflect.TypeOf(GetEndpointParams{}) + + t.Run("parameter-level extension", func(t *testing.T) { + field, ok := paramType.FieldByName("EnvParamLevel") + require.True(t, ok, "field EnvParamLevel should exist") + + assert.Equal(t, `required,oneof=dev live`, field.Tag.Get("validate"), + "x-oapi-codegen-extra-tags at parameter level should produce validate tag") + }) + + t.Run("schema-level extension", func(t *testing.T) { + field, ok := paramType.FieldByName("EnvSchemaLevel") + require.True(t, ok, "field EnvSchemaLevel should exist") + + assert.Equal(t, `required,oneof=dev live`, field.Tag.Get("validate"), + "x-oapi-codegen-extra-tags at schema level within a parameter should produce validate tag") + }) + + t.Run("schema-level extension on optional param", func(t *testing.T) { + field, ok := paramType.FieldByName("Limit") + require.True(t, ok, "field Limit should exist") + + assert.Equal(t, `min=0,max=100`, field.Tag.Get("validate"), + "x-oapi-codegen-extra-tags at schema level within an optional parameter should produce validate tag") + }) +} diff --git a/internal/test/issues/issue-2232/spec.yaml b/internal/test/issues/issue-2232/spec.yaml new file mode 100644 index 0000000000..0fea5cba83 --- /dev/null +++ b/internal/test/issues/issue-2232/spec.yaml @@ -0,0 +1,46 @@ +openapi: "3.0.3" +info: + title: test + version: 1.0.0 +paths: + /v1/endpoint: + get: + operationId: GetEndpoint + parameters: + - name: env_param_level + in: query + required: true + schema: + type: string + enum: + - dev + - live + x-oapi-codegen-extra-tags: + validate: "required,oneof=dev live" + - name: env_schema_level + in: query + required: true + schema: + type: string + enum: + - dev + - live + x-oapi-codegen-extra-tags: + validate: "required,oneof=dev live" + - name: limit + in: query + required: false + schema: + type: integer + x-oapi-codegen-extra-tags: + validate: "min=0,max=100" + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + properties: + message: + type: string diff --git a/internal/test/issues/issue-832/issue.gen.go b/internal/test/issues/issue-832/issue.gen.go index 9b4891289b..ee78d7a760 100644 --- a/internal/test/issues/issue-832/issue.gen.go +++ b/internal/test/issues/issue-832/issue.gen.go @@ -23,6 +23,22 @@ const ( Two Document_Status = "two" ) +// Valid indicates whether the value is a known member of the Document_Status enum. +func (e Document_Status) Valid() bool { + switch e { + case Four: + return true + case One: + return true + case Three: + return true + case Two: + return true + default: + return false + } +} + // Document defines model for Document. type Document struct { Name *string `json:"name,omitempty"` diff --git a/internal/test/issues/issue-illegal_enum_names/issue.gen.go b/internal/test/issues/issue-illegal_enum_names/issue.gen.go index 4179410c62..1ee690b86e 100644 --- a/internal/test/issues/issue-illegal_enum_names/issue.gen.go +++ b/internal/test/issues/issue-illegal_enum_names/issue.gen.go @@ -34,6 +34,34 @@ const ( BarUnderscoreFoo Bar = "_Foo_" ) +// Valid indicates whether the value is a known member of the Bar enum. +func (e Bar) Valid() bool { + switch e { + case BarBar: + return true + case BarEmpty: + return true + case BarFoo: + return true + case BarFoo1: + return true + case BarFoo2: + return true + case BarFooBar: + return true + case BarFooBar1: + return true + case BarN1: + return true + case BarN1Foo: + return true + case BarUnderscoreFoo: + return true + default: + return false + } +} + // Bar defines model for Bar. type Bar string diff --git a/internal/test/issues/issue1469/Makefile b/internal/test/issues/issue1469/Makefile new file mode 100644 index 0000000000..bb37d63394 --- /dev/null +++ b/internal/test/issues/issue1469/Makefile @@ -0,0 +1,36 @@ +SHELL:=/bin/bash + +YELLOW := \e[0;33m +RESET := \e[0;0m + +GOVER := $(shell go env GOVERSION) +GOMINOR := $(shell bash -c "cut -f1 -d' ' <<< \"$(GOVER)\" | cut -f2 -d.") + +define execute-if-go-124 +@{ \ +if [[ 24 -le $(GOMINOR) ]]; then \ + $1; \ +else \ + echo -e "$(YELLOW)Skipping task as you're running Go v1.$(GOMINOR).x which is < Go 1.24, which this module requires$(RESET)"; \ +fi \ +} +endef + +lint: + $(call execute-if-go-124,$(GOBIN)/golangci-lint run ./...) + +lint-ci: + + $(call execute-if-go-124,$(GOBIN)/golangci-lint run ./... --output.text.path=stdout --timeout=5m) + +generate: + $(call execute-if-go-124,go generate ./...) + +test: + $(call execute-if-go-124,go test -cover ./...) + +tidy: + $(call execute-if-go-124,go mod tidy) + +tidy-ci: + $(call execute-if-go-124,tidied -verbose) diff --git a/internal/test/issues/issue1469/go.mod b/internal/test/issues/issue1469/go.mod new file mode 100644 index 0000000000..88af6c7fe5 --- /dev/null +++ b/internal/test/issues/issue1469/go.mod @@ -0,0 +1,49 @@ +module github.com/livesession/oapi-codegen/v2/internal/test/issues/issue1469 + +go 1.24.0 + +replace github.com/livesession/oapi-codegen/v2 => ../../../../ + +tool github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen + +require ( + github.com/gofiber/fiber/v2 v2.52.11 + github.com/stretchr/testify v1.11.1 +) + +require ( + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect + github.com/getkin/kin-openapi v0.133.0 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/livesession/oapi-codegen/v2 v2.0.0-00010101000000-000000000000 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect + github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect + github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/speakeasy-api/jsonpath v0.6.0 // indirect + github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.51.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect + github.com/woodsbury/decimal128 v1.3.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/tools v0.30.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/internal/test/issues/issue1469/go.sum b/internal/test/issues/issue1469/go.sum new file mode 100644 index 0000000000..e2954b1efc --- /dev/null +++ b/internal/test/issues/issue1469/go.sum @@ -0,0 +1,198 @@ +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +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/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= +github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= +github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ= +github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= +github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/gofiber/fiber/v2 v2.52.11 h1:5f4yzKLcBcF8ha1GQTWB+mpblWz3Vz6nSAbTL31HkWs= +github.com/gofiber/fiber/v2 v2.52.11/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= +github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/speakeasy-api/jsonpath v0.6.0 h1:IhtFOV9EbXplhyRqsVhHoBmmYjblIRh5D1/g8DHMXJ8= +github.com/speakeasy-api/jsonpath v0.6.0/go.mod h1:ymb2iSkyOycmzKwbEAYPJV/yi2rSmvBCLZJcyD+VVWw= +github.com/speakeasy-api/openapi-overlay v0.10.2 h1:VOdQ03eGKeiHnpb1boZCGm7x8Haj6gST0P3SGTX95GU= +github.com/speakeasy-api/openapi-overlay v0.10.2/go.mod h1:n0iOU7AqKpNFfEt6tq7qYITC4f0yzVVdFw0S7hukemg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= +github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= +github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= +github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0= +github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/test/parameters/parameters.gen.go b/internal/test/parameters/parameters.gen.go index 4f295deeba..b4a1ec0b9a 100644 --- a/internal/test/parameters/parameters.gen.go +++ b/internal/test/parameters/parameters.gen.go @@ -27,6 +27,18 @@ const ( N200 EnumParamsParamsEnumPathParam = 200 ) +// Valid indicates whether the value is a known member of the EnumParamsParamsEnumPathParam enum. +func (e EnumParamsParamsEnumPathParam) Valid() bool { + switch e { + case N100: + return true + case N200: + return true + default: + return false + } +} + // ComplexObject defines model for ComplexObject. type ComplexObject struct { Id int `json:"Id"` diff --git a/internal/test/schemas/schemas.gen.go b/internal/test/schemas/schemas.gen.go index b7da4e527c..11ecbd0a82 100644 --- a/internal/test/schemas/schemas.gen.go +++ b/internal/test/schemas/schemas.gen.go @@ -34,6 +34,18 @@ const ( Second EnumInObjInArrayVal = "second" ) +// Valid indicates whether the value is a known member of the EnumInObjInArrayVal enum. +func (e EnumInObjInArrayVal) Valid() bool { + switch e { + case First: + return true + case Second: + return true + default: + return false + } +} + // N5StartsWithNumber This schema name starts with a number type N5StartsWithNumber = map[string]interface{} @@ -80,7 +92,7 @@ type GenericObject = map[string]interface{} // NullableProperties defines model for NullableProperties. type NullableProperties struct { Optional *string `json:"optional,omitempty"` - OptionalAndNullable *string `json:"optionalAndNullable"` + OptionalAndNullable *string `json:"optionalAndNullable,omitempty"` Required string `json:"required"` RequiredAndNullable *string `json:"requiredAndNullable"` } diff --git a/internal/test/server/server.gen.go b/internal/test/server/server.gen.go index 13c5d9a46a..28fddb099e 100644 --- a/internal/test/server/server.gen.go +++ b/internal/test/server/server.gen.go @@ -19,6 +19,18 @@ const ( Text GetWithContentTypeParamsContentType = "text" ) +// Valid indicates whether the value is a known member of the GetWithContentTypeParamsContentType enum. +func (e GetWithContentTypeParamsContentType) Valid() bool { + switch e { + case Json: + return true + case Text: + return true + default: + return false + } +} + // EveryTypeOptional defines model for EveryTypeOptional. type EveryTypeOptional struct { ArrayInlineField *[]int `json:"array_inline_field,omitempty"` diff --git a/internal/test/strict-server/chi/server.gen.go b/internal/test/strict-server/chi/server.gen.go index 8652545f6f..f0197b41ef 100644 --- a/internal/test/strict-server/chi/server.gen.go +++ b/internal/test/strict-server/chi/server.gen.go @@ -9,6 +9,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "mime" @@ -39,6 +40,12 @@ type ServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(w http.ResponseWriter, r *http.Request) + // (POST /required-json-body) + RequiredJSONBody(w http.ResponseWriter, r *http.Request) + + // (POST /required-text-body) + RequiredTextBody(w http.ResponseWriter, r *http.Request) + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request, pType string) @@ -88,6 +95,16 @@ func (_ Unimplemented) MultipleRequestAndResponseTypes(w http.ResponseWriter, r w.WriteHeader(http.StatusNotImplemented) } +// (POST /required-json-body) +func (_ Unimplemented) RequiredJSONBody(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + +// (POST /required-text-body) +func (_ Unimplemented) RequiredTextBody(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + // (GET /reserved-go-keyword-parameters/{type}) func (_ Unimplemented) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request, pType string) { w.WriteHeader(http.StatusNotImplemented) @@ -193,6 +210,34 @@ func (siw *ServerInterfaceWrapper) MultipleRequestAndResponseTypes(w http.Respon handler.ServeHTTP(w, r) } +// RequiredJSONBody operation middleware +func (siw *ServerInterfaceWrapper) RequiredJSONBody(w http.ResponseWriter, r *http.Request) { + + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.RequiredJSONBody(w, r) + })) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r) +} + +// RequiredTextBody operation middleware +func (siw *ServerInterfaceWrapper) RequiredTextBody(w http.ResponseWriter, r *http.Request) { + + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.RequiredTextBody(w, r) + })) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r) +} + // ReservedGoKeywordParameters operation middleware func (siw *ServerInterfaceWrapper) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request) { @@ -490,6 +535,12 @@ func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handl r.Group(func(r chi.Router) { r.Post(options.BaseURL+"/multiple", wrapper.MultipleRequestAndResponseTypes) }) + r.Group(func(r chi.Router) { + r.Post(options.BaseURL+"/required-json-body", wrapper.RequiredJSONBody) + }) + r.Group(func(r chi.Router) { + r.Post(options.BaseURL+"/required-text-body", wrapper.RequiredTextBody) + }) r.Group(func(r chi.Router) { r.Get(options.BaseURL+"/reserved-go-keyword-parameters/{type}", wrapper.ReservedGoKeywordParameters) }) @@ -716,6 +767,73 @@ func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestA return nil } +type RequiredJSONBodyRequestObject struct { + Body *RequiredJSONBodyJSONRequestBody +} + +type RequiredJSONBodyResponseObject interface { + VisitRequiredJSONBodyResponse(w http.ResponseWriter) error +} + +type RequiredJSONBody200JSONResponse Example + +func (response RequiredJSONBody200JSONResponse) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type RequiredJSONBody400Response = BadrequestResponse + +func (response RequiredJSONBody400Response) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(400) + return nil +} + +type RequiredJSONBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredJSONBodydefaultResponse) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(response.StatusCode) + return nil +} + +type RequiredTextBodyRequestObject struct { + Body *RequiredTextBodyTextRequestBody +} + +type RequiredTextBodyResponseObject interface { + VisitRequiredTextBodyResponse(w http.ResponseWriter) error +} + +type RequiredTextBody200TextResponse string + +func (response RequiredTextBody200TextResponse) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(200) + + _, err := w.Write([]byte(response)) + return err +} + +type RequiredTextBody400Response = BadrequestResponse + +func (response RequiredTextBody400Response) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(400) + return nil +} + +type RequiredTextBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredTextBodydefaultResponse) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(response.StatusCode) + return nil +} + type ReservedGoKeywordParametersRequestObject struct { Type string `json:"type"` } @@ -1063,6 +1181,12 @@ type StrictServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error) + // (POST /required-json-body) + RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) + + // (POST /required-text-body) + RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) @@ -1123,10 +1247,13 @@ func (sh *strictHandler) JSONExample(w http.ResponseWriter, r *http.Request) { var body JSONExampleJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.JSONExample(ctx, request.(JSONExampleRequestObject)) @@ -1221,10 +1348,13 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter, var body MultipleRequestAndResponseTypesJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.JSONBody = &body } - request.JSONBody = &body } if strings.HasPrefix(r.Header.Get("Content-Type"), "application/x-www-form-urlencoded") { if err := r.ParseForm(); err != nil { @@ -1255,8 +1385,10 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter, sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err)) return } - body := MultipleRequestAndResponseTypesTextRequestBody(data) - request.TextBody = &body + if len(data) > 0 { + body := MultipleRequestAndResponseTypesTextRequestBody(data) + request.TextBody = &body + } } handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { @@ -1279,6 +1411,69 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter, } } +// RequiredJSONBody operation middleware +func (sh *strictHandler) RequiredJSONBody(w http.ResponseWriter, r *http.Request) { + var request RequiredJSONBodyRequestObject + + var body RequiredJSONBodyJSONRequestBody + if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + request.Body = &body + + handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { + return sh.ssi.RequiredJSONBody(ctx, request.(RequiredJSONBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredJSONBody") + } + + response, err := handler(r.Context(), w, r, request) + + if err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } else if validResponse, ok := response.(RequiredJSONBodyResponseObject); ok { + if err := validResponse.VisitRequiredJSONBodyResponse(w); err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } + } else if response != nil { + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + } +} + +// RequiredTextBody operation middleware +func (sh *strictHandler) RequiredTextBody(w http.ResponseWriter, r *http.Request) { + var request RequiredTextBodyRequestObject + + data, err := io.ReadAll(r.Body) + if err != nil { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err)) + return + } + body := RequiredTextBodyTextRequestBody(data) + request.Body = &body + + handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { + return sh.ssi.RequiredTextBody(ctx, request.(RequiredTextBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredTextBody") + } + + response, err := handler(r.Context(), w, r, request) + + if err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } else if validResponse, ok := response.(RequiredTextBodyResponseObject); ok { + if err := validResponse.VisitRequiredTextBodyResponse(w); err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } + } else if response != nil { + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + } +} + // ReservedGoKeywordParameters operation middleware func (sh *strictHandler) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request, pType string) { var request ReservedGoKeywordParametersRequestObject @@ -1311,10 +1506,13 @@ func (sh *strictHandler) ReusableResponses(w http.ResponseWriter, r *http.Reques var body ReusableResponsesJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.ReusableResponses(ctx, request.(ReusableResponsesRequestObject)) @@ -1345,8 +1543,10 @@ func (sh *strictHandler) TextExample(w http.ResponseWriter, r *http.Request) { sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err)) return } - body := TextExampleTextRequestBody(data) - request.Body = &body + if len(data) > 0 { + body := TextExampleTextRequestBody(data) + request.Body = &body + } handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.TextExample(ctx, request.(TextExampleRequestObject)) @@ -1465,10 +1665,13 @@ func (sh *strictHandler) HeadersExample(w http.ResponseWriter, r *http.Request, var body HeadersExampleJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.HeadersExample(ctx, request.(HeadersExampleRequestObject)) @@ -1496,10 +1699,13 @@ func (sh *strictHandler) UnionExample(w http.ResponseWriter, r *http.Request) { var body UnionExampleJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.UnionExample(ctx, request.(UnionExampleRequestObject)) @@ -1524,24 +1730,25 @@ func (sh *strictHandler) UnionExample(w http.ResponseWriter, r *http.Request) { // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+xYS3PbNhD+Kxi0p5QUZccn3hpPJm3T1h3ZPnV8gIilhIQE0MVStEaj/94BQb0sWpUS", - "PTqZ3PhY7C6+b3ex2BnPTGmNBk2OpzOO4KzRDpqXoZAI/1TgyL9JcBkqS8ponvJ3Qg7af/OII1RODAtY", - "LPfymdEEulkqrC1UJvzS5JPz62fcZWMohX/6ESHnKf8hWbmShL8ugWdR2gL4fD6PXnhw95FHfAxCAjbe", - "hserTd00tcBT7giVHnGvJIhdd4opTTAC9Na8aOuEF1j4kc64RWMBSQWMJqKooNtS+8UMP0FGYQdK52Yb", - "y1ujSSjtmFR5DgiaWAse8zocc5W1BgkkG06Zt5ARc4ATQB5xUuQd4/fr31nrsOMRnwC6YOiq1+/1PV/G", - "ghZW8ZS/bT5F3AoaNxtaEmRNF++/3d/9yZRjoiJTClKZKIopKwW6sShAMqXJeBerjFyPN5awIf5X2a5+", - "30Lpo6YJoHdGTk8RME1croXzdb9/pricR/wmGOvSsXQqWUuwRk0uqqID80f9WZtaM0A02O4sKauClBVI", - "61xtov3HQmQfyJf6ktxgGUtB4kSoH8vSpYGPEQpBIPcgYBAkD+NhTf1JWfgaOxfloK3HnXXqfmxqx8am", - "ZmSYBFGwWtGYLRa+KLBKM8Gc0qMC2MKpqJPMAtpj72ctB+1eHryOk9ezaEPLc1zXddwkUIUF6MzIL6Mw", - "4qoUI0isHm0u97oF8ZQPp+RDdvuAO1IiR5zgmRJbCKV3n95nKunfkT5aYod0RWi6EhmPTPwZprVBGVuB", - "ogQCdMnMW597xSPoSOW/lpIsE5oNgWlRgmQiJ0D2wbBWpdtK2UFr94P5GERWqpqWZ/mS/j3jHpKmDeIR", - "9wZ4GlAJea3Qk05YQbQDtqf/jM+vImCBZmi24w1T3WVwUaKW0CHkzpfELuY68AuWBmsSl2nadkfc1vXj", - "HGeQZ/L1o/8Bnvdqu45Y+s6d24cCVoWPr2PWrtoHti+spHugOFESTFLamwM1XwxUZyFTuQIZt7uIg2+v", - "lYRbozME2myB/JVOG2JLZf6mSWNgAYGIOcNqYGXliFnhHFPUVJFChduqhK3i8bjy7DZYeliV012svjkR", - "p28uxehN/+rwJW9PHDcbrcwr+Tj4/X2QOfTOfrSe6cCO73h2L5TO/pISrw21ulP4lyCwOtMzUBPfEWnJ", - "EKhCDZJNlFgMYrZys1WworWrFwpurLqhxYDtkIYo2qnrmke7hnBP3/CI6JSjy3PFaaXVrlHho//N2h76", - "5dmgjP6fDgJFQYBakJrAT8e5QW5rMRru8ibTXrAc7Wnh6duLqnnEw+w6lKAKC18niGyaJGHm3XO1GI0A", - "e8okwiqPwr8BAAD//4h9qqfAGAAA", + "H4sIAAAAAAAC/+xZTXPbNhP+Kzt431NKmrbjE2+NJ5O2aeuObJ86PkDESkJCAiiwFK3R6L93QEBfFq1K", + "qT4ynt5Ecr/wPLuLBTRlha6MVqjIsXzKLDqjlcP2oc+Fxb9qdOSfBLrCSkNSK5azD1z04rdZwizWjvdL", + "nKt7+UIrQtWqcmNKWXCvmn1xXn/KXDHCivtf/7c4YDn7X7YMJQtfXYbPvDIlstlslryI4O4zS9gIuUDb", + "Rht+Xq3bpolBljNHVqoh80aC2HWnmFSEQ7TemxeNQXiBeRz5lBmrDVqSAaMxL2vs9hTf6P4XLCisQKqB", + "3sTyViviUjkQcjBAi4ogggfehgNXG6MtoYD+BLyHgsChHaNlCSNJPjB2v/oeYsCOJWyM1gVHVxeXF5ee", + "L21QcSNZzt63rxJmOI3aBS0IMrqL91/u734H6YDXpCtOsuBlOYGKWzfiJQqQirQPsS7IXbDWk22J/1lE", + "7Y8RSp81bQJ90GJyjIRp83Ilna8vL0+Ul7OE3QRnXTYWQWUrBdaaGfC67MD8UX1VulGA1mobV5ZVdUnS", + "cEurXK2j/dtcZBfIF/aygbZVKjjxI6F+KE/nBj61WHJCsQMBvSC5Hw8r5o/Kwr/xc1YOYj/u7FP3I904", + "GOkGSINAXkIjaQRzxRcNVirg4KQalgjzoJJOMkuM296PSvTiWh68jaP3s2TNynPaNE3aFlBtS1SFFt9G", + "YcJkxYeYGTVcV/e2ObGc9SfkU3ZzgztQISeM8JkyU3Kptu/eJ2rp/yF9sMIO5eofpUWRekbSfqyP7sKN", + "5QVeyg8ac90EnIZKOl+l4aMb6boUwMuGT1zoD5sTRy+q+8mjLcyjjx3BgffJcrI1vu0xZEGtz6zzUPuA", + "z/SP1O6R+PvSd+qa2p+i9kwg0qFOv+Kk0VakhlteIaF12dTHOfO2hthh8o+FJBRcQR9B8QoF8AGhhU8a", + "oknXwU/w+0l/DiJLU+2BY/GQ/zllHrz2EMIS5h2wPOD3ko5kC8BPx6VqjmY46qZrrl5L+Cgyh87iwPmB", + "pIvjDvyCp96KxHmOTNtzc+Pwf4qk9ky+Pnj7lrDLsH3AweN77wJ1ePk6ZlFrF9i+cY7ZAcWxFKizytzs", + "aflsoDqDhRxIFGlcRRpie60l3GpVWKT1A4jfDJUmWBiD/gRohBAQaPfHBqGqHYHhzoGktouUMtwVCdxo", + "Ho/LyG6Dp4dlO93G6rsjcfruXIzeXF7tr/L+yHmzdpB4pR57v34MMvvemB3sxLLneetwfs9Uzo2kUbpy", + "pdxdwj8FgeWeXqAc+4lICbBItVUoYCz5/Bp0ozajgSWtXbNQCGM5Dc2vt/cZiJKttq5Zsu0K/OkNX9Ae", + "84+DU+VpreS2i/pH/xniDP1yb5BafafX8LwktIqTHOMPh7m/2bSiFd4N2kp7wXKyo4ent5dVs4SFf45C", + "C6pt6fsEkcmzLPzjdOEaPhyivZA640Z6FP4OAAD//0nTejA+HAAA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/test/strict-server/chi/server.go b/internal/test/strict-server/chi/server.go index 989df4b09c..fc6d4b5a17 100644 --- a/internal/test/strict-server/chi/server.go +++ b/internal/test/strict-server/chi/server.go @@ -126,6 +126,14 @@ func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableRes return ReusableResponses200JSONResponse{ReusableresponseJSONResponse: ReusableresponseJSONResponse{Body: *request.Body}}, nil } +func (s StrictServer) RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) { + return RequiredJSONBody200JSONResponse(*request.Body), nil +} + +func (s StrictServer) RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) { + return RequiredTextBody200TextResponse(*request.Body), nil +} + func (s StrictServer) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) { return ReservedGoKeywordParameters200TextResponse(""), nil } diff --git a/internal/test/strict-server/chi/types.gen.go b/internal/test/strict-server/chi/types.gen.go index e0781f12f9..9b74c20754 100644 --- a/internal/test/strict-server/chi/types.gen.go +++ b/internal/test/strict-server/chi/types.gen.go @@ -14,6 +14,9 @@ type Reusableresponse = Example // MultipleRequestAndResponseTypesTextBody defines parameters for MultipleRequestAndResponseTypes. type MultipleRequestAndResponseTypesTextBody = string +// RequiredTextBodyTextBody defines parameters for RequiredTextBody. +type RequiredTextBodyTextBody = string + // TextExampleTextBody defines parameters for TextExample. type TextExampleTextBody = string @@ -44,6 +47,12 @@ type MultipleRequestAndResponseTypesMultipartRequestBody = Example // MultipleRequestAndResponseTypesTextRequestBody defines body for MultipleRequestAndResponseTypes for text/plain ContentType. type MultipleRequestAndResponseTypesTextRequestBody = MultipleRequestAndResponseTypesTextBody +// RequiredJSONBodyJSONRequestBody defines body for RequiredJSONBody for application/json ContentType. +type RequiredJSONBodyJSONRequestBody = Example + +// RequiredTextBodyTextRequestBody defines body for RequiredTextBody for text/plain ContentType. +type RequiredTextBodyTextRequestBody = RequiredTextBodyTextBody + // ReusableResponsesJSONRequestBody defines body for ReusableResponses for application/json ContentType. type ReusableResponsesJSONRequestBody = Example diff --git a/internal/test/strict-server/client/client.gen.go b/internal/test/strict-server/client/client.gen.go index 8ec5f8d122..ae963e5686 100644 --- a/internal/test/strict-server/client/client.gen.go +++ b/internal/test/strict-server/client/client.gen.go @@ -27,6 +27,9 @@ type Reusableresponse = Example // MultipleRequestAndResponseTypesTextBody defines parameters for MultipleRequestAndResponseTypes. type MultipleRequestAndResponseTypesTextBody = string +// RequiredTextBodyTextBody defines parameters for RequiredTextBody. +type RequiredTextBodyTextBody = string + // TextExampleTextBody defines parameters for TextExample. type TextExampleTextBody = string @@ -57,6 +60,12 @@ type MultipleRequestAndResponseTypesMultipartRequestBody = Example // MultipleRequestAndResponseTypesTextRequestBody defines body for MultipleRequestAndResponseTypes for text/plain ContentType. type MultipleRequestAndResponseTypesTextRequestBody = MultipleRequestAndResponseTypesTextBody +// RequiredJSONBodyJSONRequestBody defines body for RequiredJSONBody for application/json ContentType. +type RequiredJSONBodyJSONRequestBody = Example + +// RequiredTextBodyTextRequestBody defines body for RequiredTextBody for text/plain ContentType. +type RequiredTextBodyTextRequestBody = RequiredTextBodyTextBody + // ReusableResponsesJSONRequestBody defines body for ReusableResponses for application/json ContentType. type ReusableResponsesJSONRequestBody = Example @@ -165,6 +174,16 @@ type ClientInterface interface { MultipleRequestAndResponseTypesWithTextBody(ctx context.Context, body MultipleRequestAndResponseTypesTextRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // RequiredJSONBodyWithBody request with any body + RequiredJSONBodyWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + RequiredJSONBody(ctx context.Context, body RequiredJSONBodyJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // RequiredTextBodyWithBody request with any body + RequiredTextBodyWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + RequiredTextBodyWithTextBody(ctx context.Context, body RequiredTextBodyTextRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // ReservedGoKeywordParameters request ReservedGoKeywordParameters(ctx context.Context, pType string, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -296,6 +315,54 @@ func (c *Client) MultipleRequestAndResponseTypesWithTextBody(ctx context.Context return c.Client.Do(req) } +func (c *Client) RequiredJSONBodyWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRequiredJSONBodyRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) RequiredJSONBody(ctx context.Context, body RequiredJSONBodyJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRequiredJSONBodyRequest(c.Server, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) RequiredTextBodyWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRequiredTextBodyRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) RequiredTextBodyWithTextBody(ctx context.Context, body RequiredTextBodyTextRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRequiredTextBodyRequestWithTextBody(c.Server, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) ReservedGoKeywordParameters(ctx context.Context, pType string, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewReservedGoKeywordParametersRequest(c.Server, pType) if err != nil { @@ -608,6 +675,82 @@ func NewMultipleRequestAndResponseTypesRequestWithBody(server string, contentTyp return req, nil } +// NewRequiredJSONBodyRequest calls the generic RequiredJSONBody builder with application/json body +func NewRequiredJSONBodyRequest(server string, body RequiredJSONBodyJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewRequiredJSONBodyRequestWithBody(server, "application/json", bodyReader) +} + +// NewRequiredJSONBodyRequestWithBody generates requests for RequiredJSONBody with any type of body +func NewRequiredJSONBodyRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/required-json-body") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + 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 +} + +// NewRequiredTextBodyRequestWithTextBody calls the generic RequiredTextBody builder with text/plain body +func NewRequiredTextBodyRequestWithTextBody(server string, body RequiredTextBodyTextRequestBody) (*http.Request, error) { + var bodyReader io.Reader + bodyReader = strings.NewReader(string(body)) + return NewRequiredTextBodyRequestWithBody(server, "text/plain", bodyReader) +} + +// NewRequiredTextBodyRequestWithBody generates requests for RequiredTextBody with any type of body +func NewRequiredTextBodyRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/required-text-body") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + 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 +} + // NewReservedGoKeywordParametersRequest generates requests for ReservedGoKeywordParameters func NewReservedGoKeywordParametersRequest(server string, pType string) (*http.Request, error) { var err error @@ -983,6 +1126,16 @@ type ClientWithResponsesInterface interface { MultipleRequestAndResponseTypesWithTextBodyWithResponse(ctx context.Context, body MultipleRequestAndResponseTypesTextRequestBody, reqEditors ...RequestEditorFn) (*MultipleRequestAndResponseTypesResponse, error) + // RequiredJSONBodyWithBodyWithResponse request with any body + RequiredJSONBodyWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RequiredJSONBodyResponse, error) + + RequiredJSONBodyWithResponse(ctx context.Context, body RequiredJSONBodyJSONRequestBody, reqEditors ...RequestEditorFn) (*RequiredJSONBodyResponse, error) + + // RequiredTextBodyWithBodyWithResponse request with any body + RequiredTextBodyWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RequiredTextBodyResponse, error) + + RequiredTextBodyWithTextBodyWithResponse(ctx context.Context, body RequiredTextBodyTextRequestBody, reqEditors ...RequestEditorFn) (*RequiredTextBodyResponse, error) + // ReservedGoKeywordParametersWithResponse request ReservedGoKeywordParametersWithResponse(ctx context.Context, pType string, reqEditors ...RequestEditorFn) (*ReservedGoKeywordParametersResponse, error) @@ -1104,6 +1257,49 @@ func (r MultipleRequestAndResponseTypesResponse) StatusCode() int { return 0 } +type RequiredJSONBodyResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Example +} + +// Status returns HTTPResponse.Status +func (r RequiredJSONBodyResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r RequiredJSONBodyResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type RequiredTextBodyResponse struct { + Body []byte + HTTPResponse *http.Response +} + +// Status returns HTTPResponse.Status +func (r RequiredTextBodyResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r RequiredTextBodyResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type ReservedGoKeywordParametersResponse struct { Body []byte HTTPResponse *http.Response @@ -1347,6 +1543,40 @@ func (c *ClientWithResponses) MultipleRequestAndResponseTypesWithTextBodyWithRes return ParseMultipleRequestAndResponseTypesResponse(rsp) } +// RequiredJSONBodyWithBodyWithResponse request with arbitrary body returning *RequiredJSONBodyResponse +func (c *ClientWithResponses) RequiredJSONBodyWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RequiredJSONBodyResponse, error) { + rsp, err := c.RequiredJSONBodyWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseRequiredJSONBodyResponse(rsp) +} + +func (c *ClientWithResponses) RequiredJSONBodyWithResponse(ctx context.Context, body RequiredJSONBodyJSONRequestBody, reqEditors ...RequestEditorFn) (*RequiredJSONBodyResponse, error) { + rsp, err := c.RequiredJSONBody(ctx, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseRequiredJSONBodyResponse(rsp) +} + +// RequiredTextBodyWithBodyWithResponse request with arbitrary body returning *RequiredTextBodyResponse +func (c *ClientWithResponses) RequiredTextBodyWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RequiredTextBodyResponse, error) { + rsp, err := c.RequiredTextBodyWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseRequiredTextBodyResponse(rsp) +} + +func (c *ClientWithResponses) RequiredTextBodyWithTextBodyWithResponse(ctx context.Context, body RequiredTextBodyTextRequestBody, reqEditors ...RequestEditorFn) (*RequiredTextBodyResponse, error) { + rsp, err := c.RequiredTextBodyWithTextBody(ctx, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseRequiredTextBodyResponse(rsp) +} + // ReservedGoKeywordParametersWithResponse request returning *ReservedGoKeywordParametersResponse func (c *ClientWithResponses) ReservedGoKeywordParametersWithResponse(ctx context.Context, pType string, reqEditors ...RequestEditorFn) (*ReservedGoKeywordParametersResponse, error) { rsp, err := c.ReservedGoKeywordParameters(ctx, pType, reqEditors...) @@ -1546,6 +1776,48 @@ func ParseMultipleRequestAndResponseTypesResponse(rsp *http.Response) (*Multiple return response, nil } +// ParseRequiredJSONBodyResponse parses an HTTP response from a RequiredJSONBodyWithResponse call +func ParseRequiredJSONBodyResponse(rsp *http.Response) (*RequiredJSONBodyResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RequiredJSONBodyResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest Example + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseRequiredTextBodyResponse parses an HTTP response from a RequiredTextBodyWithResponse call +func ParseRequiredTextBodyResponse(rsp *http.Response) (*RequiredTextBodyResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RequiredTextBodyResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + return response, nil +} + // ParseReservedGoKeywordParametersResponse parses an HTTP response from a ReservedGoKeywordParametersWithResponse call func ParseReservedGoKeywordParametersResponse(rsp *http.Response) (*ReservedGoKeywordParametersResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/internal/test/strict-server/echo/server.gen.go b/internal/test/strict-server/echo/server.gen.go index 15131bb2fd..abde7e78f5 100644 --- a/internal/test/strict-server/echo/server.gen.go +++ b/internal/test/strict-server/echo/server.gen.go @@ -9,6 +9,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "mime" @@ -39,6 +40,12 @@ type ServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(ctx echo.Context) error + // (POST /required-json-body) + RequiredJSONBody(ctx echo.Context) error + + // (POST /required-text-body) + RequiredTextBody(ctx echo.Context) error + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(ctx echo.Context, pType string) error @@ -105,6 +112,24 @@ func (w *ServerInterfaceWrapper) MultipleRequestAndResponseTypes(ctx echo.Contex return err } +// RequiredJSONBody converts echo context to params. +func (w *ServerInterfaceWrapper) RequiredJSONBody(ctx echo.Context) error { + var err error + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.RequiredJSONBody(ctx) + return err +} + +// RequiredTextBody converts echo context to params. +func (w *ServerInterfaceWrapper) RequiredTextBody(ctx echo.Context) error { + var err error + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.RequiredTextBody(ctx) + return err +} + // ReservedGoKeywordParameters converts echo context to params. func (w *ServerInterfaceWrapper) ReservedGoKeywordParameters(ctx echo.Context) error { var err error @@ -253,6 +278,8 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.POST(baseURL+"/multipart", wrapper.MultipartExample) router.POST(baseURL+"/multipart-related", wrapper.MultipartRelatedExample) router.POST(baseURL+"/multiple", wrapper.MultipleRequestAndResponseTypes) + router.POST(baseURL+"/required-json-body", wrapper.RequiredJSONBody) + router.POST(baseURL+"/required-text-body", wrapper.RequiredTextBody) router.GET(baseURL+"/reserved-go-keyword-parameters/:type", wrapper.ReservedGoKeywordParameters) router.POST(baseURL+"/reusable-responses", wrapper.ReusableResponses) router.POST(baseURL+"/text", wrapper.TextExample) @@ -462,6 +489,73 @@ func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestA return nil } +type RequiredJSONBodyRequestObject struct { + Body *RequiredJSONBodyJSONRequestBody +} + +type RequiredJSONBodyResponseObject interface { + VisitRequiredJSONBodyResponse(w http.ResponseWriter) error +} + +type RequiredJSONBody200JSONResponse Example + +func (response RequiredJSONBody200JSONResponse) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type RequiredJSONBody400Response = BadrequestResponse + +func (response RequiredJSONBody400Response) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(400) + return nil +} + +type RequiredJSONBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredJSONBodydefaultResponse) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(response.StatusCode) + return nil +} + +type RequiredTextBodyRequestObject struct { + Body *RequiredTextBodyTextRequestBody +} + +type RequiredTextBodyResponseObject interface { + VisitRequiredTextBodyResponse(w http.ResponseWriter) error +} + +type RequiredTextBody200TextResponse string + +func (response RequiredTextBody200TextResponse) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(200) + + _, err := w.Write([]byte(response)) + return err +} + +type RequiredTextBody400Response = BadrequestResponse + +func (response RequiredTextBody400Response) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(400) + return nil +} + +type RequiredTextBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredTextBodydefaultResponse) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(response.StatusCode) + return nil +} + type ReservedGoKeywordParametersRequestObject struct { Type string `json:"type"` } @@ -809,6 +903,12 @@ type StrictServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error) + // (POST /required-json-body) + RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) + + // (POST /required-text-body) + RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) @@ -852,9 +952,12 @@ func (sh *strictHandler) JSONExample(ctx echo.Context) error { var body JSONExampleJSONRequestBody if err := ctx.Bind(&body); err != nil { - return err + if !errors.Is(err, io.EOF) { + return err + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.JSONExample(ctx.Request().Context(), request.(JSONExampleRequestObject)) @@ -942,9 +1045,12 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx echo.Context) error if strings.HasPrefix(ctx.Request().Header.Get("Content-Type"), "application/json") { var body MultipleRequestAndResponseTypesJSONRequestBody if err := ctx.Bind(&body); err != nil { - return err + if !errors.Is(err, io.EOF) { + return err + } + } else { + request.JSONBody = &body } - request.JSONBody = &body } if strings.HasPrefix(ctx.Request().Header.Get("Content-Type"), "application/x-www-form-urlencoded") { if form, err := ctx.FormParams(); err == nil { @@ -972,8 +1078,10 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx echo.Context) error if err != nil { return err } - body := MultipleRequestAndResponseTypesTextRequestBody(data) - request.TextBody = &body + if len(data) > 0 { + body := MultipleRequestAndResponseTypesTextRequestBody(data) + request.TextBody = &body + } } handler := func(ctx echo.Context, request interface{}) (interface{}, error) { @@ -995,6 +1103,65 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx echo.Context) error return nil } +// RequiredJSONBody operation middleware +func (sh *strictHandler) RequiredJSONBody(ctx echo.Context) error { + var request RequiredJSONBodyRequestObject + + var body RequiredJSONBodyJSONRequestBody + if err := ctx.Bind(&body); err != nil { + return err + } + request.Body = &body + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.RequiredJSONBody(ctx.Request().Context(), request.(RequiredJSONBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredJSONBody") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(RequiredJSONBodyResponseObject); ok { + return validResponse.VisitRequiredJSONBodyResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("unexpected response type: %T", response) + } + return nil +} + +// RequiredTextBody operation middleware +func (sh *strictHandler) RequiredTextBody(ctx echo.Context) error { + var request RequiredTextBodyRequestObject + + data, err := io.ReadAll(ctx.Request().Body) + if err != nil { + return err + } + body := RequiredTextBodyTextRequestBody(data) + request.Body = &body + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.RequiredTextBody(ctx.Request().Context(), request.(RequiredTextBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredTextBody") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(RequiredTextBodyResponseObject); ok { + return validResponse.VisitRequiredTextBodyResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("unexpected response type: %T", response) + } + return nil +} + // ReservedGoKeywordParameters operation middleware func (sh *strictHandler) ReservedGoKeywordParameters(ctx echo.Context, pType string) error { var request ReservedGoKeywordParametersRequestObject @@ -1026,9 +1193,12 @@ func (sh *strictHandler) ReusableResponses(ctx echo.Context) error { var body ReusableResponsesJSONRequestBody if err := ctx.Bind(&body); err != nil { - return err + if !errors.Is(err, io.EOF) { + return err + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.ReusableResponses(ctx.Request().Context(), request.(ReusableResponsesRequestObject)) @@ -1057,8 +1227,10 @@ func (sh *strictHandler) TextExample(ctx echo.Context) error { if err != nil { return err } - body := TextExampleTextRequestBody(data) - request.Body = &body + if len(data) > 0 { + body := TextExampleTextRequestBody(data) + request.Body = &body + } handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.TextExample(ctx.Request().Context(), request.(TextExampleRequestObject)) @@ -1172,9 +1344,12 @@ func (sh *strictHandler) HeadersExample(ctx echo.Context, params HeadersExampleP var body HeadersExampleJSONRequestBody if err := ctx.Bind(&body); err != nil { - return err + if !errors.Is(err, io.EOF) { + return err + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.HeadersExample(ctx.Request().Context(), request.(HeadersExampleRequestObject)) @@ -1201,9 +1376,12 @@ func (sh *strictHandler) UnionExample(ctx echo.Context) error { var body UnionExampleJSONRequestBody if err := ctx.Bind(&body); err != nil { - return err + if !errors.Is(err, io.EOF) { + return err + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.UnionExample(ctx.Request().Context(), request.(UnionExampleRequestObject)) @@ -1227,24 +1405,25 @@ func (sh *strictHandler) UnionExample(ctx echo.Context) error { // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+xYS3PbNhD+Kxi0p5QUZccn3hpPJm3T1h3ZPnV8gIilhIQE0MVStEaj/94BQb0sWpUS", - "PTqZ3PhY7C6+b3ex2BnPTGmNBk2OpzOO4KzRDpqXoZAI/1TgyL9JcBkqS8ponvJ3Qg7af/OII1RODAtY", - "LPfymdEEulkqrC1UJvzS5JPz62fcZWMohX/6ESHnKf8hWbmShL8ugWdR2gL4fD6PXnhw95FHfAxCAjbe", - "hserTd00tcBT7giVHnGvJIhdd4opTTAC9Na8aOuEF1j4kc64RWMBSQWMJqKooNtS+8UMP0FGYQdK52Yb", - "y1ujSSjtmFR5DgiaWAse8zocc5W1BgkkG06Zt5ARc4ATQB5xUuQd4/fr31nrsOMRnwC6YOiq1+/1PV/G", - "ghZW8ZS/bT5F3AoaNxtaEmRNF++/3d/9yZRjoiJTClKZKIopKwW6sShAMqXJeBerjFyPN5awIf5X2a5+", - "30Lpo6YJoHdGTk8RME1croXzdb9/pricR/wmGOvSsXQqWUuwRk0uqqID80f9WZtaM0A02O4sKauClBVI", - "61xtov3HQmQfyJf6ktxgGUtB4kSoH8vSpYGPEQpBIPcgYBAkD+NhTf1JWfgaOxfloK3HnXXqfmxqx8am", - "ZmSYBFGwWtGYLRa+KLBKM8Gc0qMC2MKpqJPMAtpj72ctB+1eHryOk9ezaEPLc1zXddwkUIUF6MzIL6Mw", - "4qoUI0isHm0u97oF8ZQPp+RDdvuAO1IiR5zgmRJbCKV3n95nKunfkT5aYod0RWi6EhmPTPwZprVBGVuB", - "ogQCdMnMW597xSPoSOW/lpIsE5oNgWlRgmQiJ0D2wbBWpdtK2UFr94P5GERWqpqWZ/mS/j3jHpKmDeIR", - "9wZ4GlAJea3Qk05YQbQDtqf/jM+vImCBZmi24w1T3WVwUaKW0CHkzpfELuY68AuWBmsSl2nadkfc1vXj", - "HGeQZ/L1o/8Bnvdqu45Y+s6d24cCVoWPr2PWrtoHti+spHugOFESTFLamwM1XwxUZyFTuQIZt7uIg2+v", - "lYRbozME2myB/JVOG2JLZf6mSWNgAYGIOcNqYGXliFnhHFPUVJFChduqhK3i8bjy7DZYeliV012svjkR", - "p28uxehN/+rwJW9PHDcbrcwr+Tj4/X2QOfTOfrSe6cCO73h2L5TO/pISrw21ulP4lyCwOtMzUBPfEWnJ", - "EKhCDZJNlFgMYrZys1WworWrFwpurLqhxYDtkIYo2qnrmke7hnBP3/CI6JSjy3PFaaXVrlHho//N2h76", - "5dmgjP6fDgJFQYBakJrAT8e5QW5rMRru8ibTXrAc7Wnh6duLqnnEw+w6lKAKC18niGyaJGHm3XO1GI0A", - "e8okwiqPwr8BAAD//4h9qqfAGAAA", + "H4sIAAAAAAAC/+xZTXPbNhP+Kzt431NKmrbjE2+NJ5O2aeuObJ86PkDESkJCAiiwFK3R6L93QEBfFq1K", + "qT4ynt5Ecr/wPLuLBTRlha6MVqjIsXzKLDqjlcP2oc+Fxb9qdOSfBLrCSkNSK5azD1z04rdZwizWjvdL", + "nKt7+UIrQtWqcmNKWXCvmn1xXn/KXDHCivtf/7c4YDn7X7YMJQtfXYbPvDIlstlslryI4O4zS9gIuUDb", + "Rht+Xq3bpolBljNHVqoh80aC2HWnmFSEQ7TemxeNQXiBeRz5lBmrDVqSAaMxL2vs9hTf6P4XLCisQKqB", + "3sTyViviUjkQcjBAi4ogggfehgNXG6MtoYD+BLyHgsChHaNlCSNJPjB2v/oeYsCOJWyM1gVHVxeXF5ee", + "L21QcSNZzt63rxJmOI3aBS0IMrqL91/u734H6YDXpCtOsuBlOYGKWzfiJQqQirQPsS7IXbDWk22J/1lE", + "7Y8RSp81bQJ90GJyjIRp83Ilna8vL0+Ul7OE3QRnXTYWQWUrBdaaGfC67MD8UX1VulGA1mobV5ZVdUnS", + "cEurXK2j/dtcZBfIF/aygbZVKjjxI6F+KE/nBj61WHJCsQMBvSC5Hw8r5o/Kwr/xc1YOYj/u7FP3I904", + "GOkGSINAXkIjaQRzxRcNVirg4KQalgjzoJJOMkuM296PSvTiWh68jaP3s2TNynPaNE3aFlBtS1SFFt9G", + "YcJkxYeYGTVcV/e2ObGc9SfkU3ZzgztQISeM8JkyU3Kptu/eJ2rp/yF9sMIO5eofpUWRekbSfqyP7sKN", + "5QVeyg8ac90EnIZKOl+l4aMb6boUwMuGT1zoD5sTRy+q+8mjLcyjjx3BgffJcrI1vu0xZEGtz6zzUPuA", + "z/SP1O6R+PvSd+qa2p+i9kwg0qFOv+Kk0VakhlteIaF12dTHOfO2hthh8o+FJBRcQR9B8QoF8AGhhU8a", + "oknXwU/w+0l/DiJLU+2BY/GQ/zllHrz2EMIS5h2wPOD3ko5kC8BPx6VqjmY46qZrrl5L+Cgyh87iwPmB", + "pIvjDvyCp96KxHmOTNtzc+Pwf4qk9ky+Pnj7lrDLsH3AweN77wJ1ePk6ZlFrF9i+cY7ZAcWxFKizytzs", + "aflsoDqDhRxIFGlcRRpie60l3GpVWKT1A4jfDJUmWBiD/gRohBAQaPfHBqGqHYHhzoGktouUMtwVCdxo", + "Ho/LyG6Dp4dlO93G6rsjcfruXIzeXF7tr/L+yHmzdpB4pR57v34MMvvemB3sxLLneetwfs9Uzo2kUbpy", + "pdxdwj8FgeWeXqAc+4lICbBItVUoYCz5/Bp0ozajgSWtXbNQCGM5Dc2vt/cZiJKttq5Zsu0K/OkNX9Ae", + "84+DU+VpreS2i/pH/xniDP1yb5BafafX8LwktIqTHOMPh7m/2bSiFd4N2kp7wXKyo4ent5dVs4SFf45C", + "C6pt6fsEkcmzLPzjdOEaPhyivZA640Z6FP4OAAD//0nTejA+HAAA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/test/strict-server/echo/server.go b/internal/test/strict-server/echo/server.go index 989df4b09c..fc6d4b5a17 100644 --- a/internal/test/strict-server/echo/server.go +++ b/internal/test/strict-server/echo/server.go @@ -126,6 +126,14 @@ func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableRes return ReusableResponses200JSONResponse{ReusableresponseJSONResponse: ReusableresponseJSONResponse{Body: *request.Body}}, nil } +func (s StrictServer) RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) { + return RequiredJSONBody200JSONResponse(*request.Body), nil +} + +func (s StrictServer) RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) { + return RequiredTextBody200TextResponse(*request.Body), nil +} + func (s StrictServer) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) { return ReservedGoKeywordParameters200TextResponse(""), nil } diff --git a/internal/test/strict-server/echo/types.gen.go b/internal/test/strict-server/echo/types.gen.go index e0781f12f9..9b74c20754 100644 --- a/internal/test/strict-server/echo/types.gen.go +++ b/internal/test/strict-server/echo/types.gen.go @@ -14,6 +14,9 @@ type Reusableresponse = Example // MultipleRequestAndResponseTypesTextBody defines parameters for MultipleRequestAndResponseTypes. type MultipleRequestAndResponseTypesTextBody = string +// RequiredTextBodyTextBody defines parameters for RequiredTextBody. +type RequiredTextBodyTextBody = string + // TextExampleTextBody defines parameters for TextExample. type TextExampleTextBody = string @@ -44,6 +47,12 @@ type MultipleRequestAndResponseTypesMultipartRequestBody = Example // MultipleRequestAndResponseTypesTextRequestBody defines body for MultipleRequestAndResponseTypes for text/plain ContentType. type MultipleRequestAndResponseTypesTextRequestBody = MultipleRequestAndResponseTypesTextBody +// RequiredJSONBodyJSONRequestBody defines body for RequiredJSONBody for application/json ContentType. +type RequiredJSONBodyJSONRequestBody = Example + +// RequiredTextBodyTextRequestBody defines body for RequiredTextBody for text/plain ContentType. +type RequiredTextBodyTextRequestBody = RequiredTextBodyTextBody + // ReusableResponsesJSONRequestBody defines body for ReusableResponses for application/json ContentType. type ReusableResponsesJSONRequestBody = Example diff --git a/internal/test/strict-server/fiber/Makefile b/internal/test/strict-server/fiber/Makefile new file mode 100644 index 0000000000..bb37d63394 --- /dev/null +++ b/internal/test/strict-server/fiber/Makefile @@ -0,0 +1,36 @@ +SHELL:=/bin/bash + +YELLOW := \e[0;33m +RESET := \e[0;0m + +GOVER := $(shell go env GOVERSION) +GOMINOR := $(shell bash -c "cut -f1 -d' ' <<< \"$(GOVER)\" | cut -f2 -d.") + +define execute-if-go-124 +@{ \ +if [[ 24 -le $(GOMINOR) ]]; then \ + $1; \ +else \ + echo -e "$(YELLOW)Skipping task as you're running Go v1.$(GOMINOR).x which is < Go 1.24, which this module requires$(RESET)"; \ +fi \ +} +endef + +lint: + $(call execute-if-go-124,$(GOBIN)/golangci-lint run ./...) + +lint-ci: + + $(call execute-if-go-124,$(GOBIN)/golangci-lint run ./... --output.text.path=stdout --timeout=5m) + +generate: + $(call execute-if-go-124,go generate ./...) + +test: + $(call execute-if-go-124,go test -cover ./...) + +tidy: + $(call execute-if-go-124,go mod tidy) + +tidy-ci: + $(call execute-if-go-124,tidied -verbose) diff --git a/internal/test/strict-server/fiber/fiber_strict_test.go b/internal/test/strict-server/fiber/fiber_strict_test.go new file mode 100644 index 0000000000..989860fc66 --- /dev/null +++ b/internal/test/strict-server/fiber/fiber_strict_test.go @@ -0,0 +1,229 @@ +package api + +import ( + "bytes" + "encoding/json" + "io" + "mime" + "mime/multipart" + "net/http" + "net/url" + "strings" + "testing" + + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/adaptor" + "github.com/stretchr/testify/assert" + + clientAPI "github.com/livesession/oapi-codegen/v2/internal/test/strict-server/client" + "github.com/oapi-codegen/runtime" + "github.com/oapi-codegen/testutil" +) + +func TestFiberServer(t *testing.T) { + server := StrictServer{} + strictHandler := NewStrictHandler(server, nil) + r := fiber.New() + RegisterHandlers(r, strictHandler) + testImpl(t, adaptor.FiberApp(r)) +} + +func testImpl(t *testing.T, handler http.Handler) { + t.Run("JSONExample", func(t *testing.T) { + value := "123" + requestBody := clientAPI.Example{Value: &value} + rr := testutil.NewRequest().Post("/json").WithJsonBody(requestBody).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + assert.True(t, strings.HasPrefix(rr.Header().Get("Content-Type"), "application/json")) + var responseBody clientAPI.Example + err := json.NewDecoder(rr.Body).Decode(&responseBody) + assert.NoError(t, err) + assert.Equal(t, requestBody, responseBody) + }) + t.Run("URLEncodedExample", func(t *testing.T) { + value := "456" + requestBody := clientAPI.Example{Value: &value} + requestBodyEncoded, err := runtime.MarshalForm(&requestBody, nil) + assert.NoError(t, err) + rr := testutil.NewRequest().Post("/urlencoded").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(requestBodyEncoded.Encode())).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + assert.Equal(t, "application/x-www-form-urlencoded", rr.Header().Get("Content-Type")) + values, err := url.ParseQuery(rr.Body.String()) + assert.NoError(t, err) + var responseBody clientAPI.Example + err = runtime.BindForm(&responseBody, values, nil, nil) + assert.NoError(t, err) + assert.Equal(t, requestBody, responseBody) + }) + t.Run("MultipartExample", func(t *testing.T) { + value := "789" + fieldName := "value" + var writer bytes.Buffer + mw := multipart.NewWriter(&writer) + field, err := mw.CreateFormField(fieldName) + assert.NoError(t, err) + _, _ = field.Write([]byte(value)) + assert.NoError(t, mw.Close()) + rr := testutil.NewRequest().Post("/multipart").WithContentType(mw.FormDataContentType()).WithBody(writer.Bytes()).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + contentType, params, err := mime.ParseMediaType(rr.Header().Get("Content-Type")) + assert.NoError(t, err) + assert.Equal(t, "multipart/form-data", contentType) + reader := multipart.NewReader(rr.Body, params["boundary"]) + part, err := reader.NextPart() + assert.NoError(t, err) + assert.Equal(t, part.FormName(), fieldName) + readValue, err := io.ReadAll(part) + assert.NoError(t, err) + assert.Equal(t, value, string(readValue)) + _, err = reader.NextPart() + assert.Equal(t, io.EOF, err) + }) + t.Run("MultipartRelatedExample", func(t *testing.T) { + value := "789" + fieldName := "value" + var writer bytes.Buffer + mw := multipart.NewWriter(&writer) + field, err := mw.CreateFormField(fieldName) + assert.NoError(t, err) + _, _ = field.Write([]byte(value)) + assert.NoError(t, mw.Close()) + rr := testutil.NewRequest().Post("/multipart-related").WithContentType(mime.FormatMediaType("multipart/related", map[string]string{"boundary": mw.Boundary()})).WithBody(writer.Bytes()).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + contentType, params, err := mime.ParseMediaType(rr.Header().Get("Content-Type")) + assert.NoError(t, err) + assert.Equal(t, "multipart/related", contentType) + reader := multipart.NewReader(rr.Body, params["boundary"]) + part, err := reader.NextPart() + assert.NoError(t, err) + assert.Equal(t, part.FormName(), fieldName) + readValue, err := io.ReadAll(part) + assert.NoError(t, err) + assert.Equal(t, value, string(readValue)) + _, err = reader.NextPart() + assert.Equal(t, io.EOF, err) + }) + t.Run("TextExample", func(t *testing.T) { + value := "text" + rr := testutil.NewRequest().Post("/text").WithContentType("text/plain").WithBody([]byte(value)).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + assert.Equal(t, "text/plain", rr.Header().Get("Content-Type")) + assert.Equal(t, value, rr.Body.String()) + }) + t.Run("UnknownExample", func(t *testing.T) { + data := []byte("unknown data") + rr := testutil.NewRequest().Post("/unknown").WithContentType("image/png").WithBody(data).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + assert.Equal(t, "video/mp4", rr.Header().Get("Content-Type")) + assert.Equal(t, data, rr.Body.Bytes()) + }) + t.Run("MultipleRequestAndResponseTypesJSON", func(t *testing.T) { + value := "123" + requestBody := clientAPI.Example{Value: &value} + rr := testutil.NewRequest().Post("/multiple").WithJsonBody(requestBody).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + assert.True(t, strings.HasPrefix(rr.Header().Get("Content-Type"), "application/json")) + var responseBody clientAPI.Example + err := json.NewDecoder(rr.Body).Decode(&responseBody) + assert.NoError(t, err) + assert.Equal(t, requestBody, responseBody) + }) + t.Run("MultipleRequestAndResponseTypesFormdata", func(t *testing.T) { + value := "456" + requestBody := clientAPI.Example{Value: &value} + requestBodyEncoded, err := runtime.MarshalForm(&requestBody, nil) + assert.NoError(t, err) + rr := testutil.NewRequest().Post("/multiple").WithContentType("application/x-www-form-urlencoded").WithBody([]byte(requestBodyEncoded.Encode())).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + assert.Equal(t, "application/x-www-form-urlencoded", rr.Header().Get("Content-Type")) + values, err := url.ParseQuery(rr.Body.String()) + assert.NoError(t, err) + var responseBody clientAPI.Example + err = runtime.BindForm(&responseBody, values, nil, nil) + assert.NoError(t, err) + assert.Equal(t, requestBody, responseBody) + }) + t.Run("MultipleRequestAndResponseTypesMultipart", func(t *testing.T) { + value := "789" + fieldName := "value" + var writer bytes.Buffer + mw := multipart.NewWriter(&writer) + field, err := mw.CreateFormField(fieldName) + assert.NoError(t, err) + _, _ = field.Write([]byte(value)) + assert.NoError(t, mw.Close()) + rr := testutil.NewRequest().Post("/multiple").WithContentType(mw.FormDataContentType()).WithBody(writer.Bytes()).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + contentType, params, err := mime.ParseMediaType(rr.Header().Get("Content-Type")) + assert.NoError(t, err) + assert.Equal(t, "multipart/form-data", contentType) + reader := multipart.NewReader(rr.Body, params["boundary"]) + part, err := reader.NextPart() + assert.NoError(t, err) + assert.Equal(t, part.FormName(), fieldName) + readValue, err := io.ReadAll(part) + assert.NoError(t, err) + assert.Equal(t, value, string(readValue)) + _, err = reader.NextPart() + assert.Equal(t, io.EOF, err) + }) + t.Run("MultipleRequestAndResponseTypesText", func(t *testing.T) { + value := "text" + rr := testutil.NewRequest().Post("/multiple").WithContentType("text/plain").WithBody([]byte(value)).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + assert.Equal(t, "text/plain", rr.Header().Get("Content-Type")) + assert.Equal(t, value, rr.Body.String()) + }) + t.Run("MultipleRequestAndResponseTypesImage", func(t *testing.T) { + data := []byte("unknown data") + rr := testutil.NewRequest().Post("/multiple").WithContentType("image/png").WithBody(data).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + assert.Equal(t, "image/png", rr.Header().Get("Content-Type")) + assert.Equal(t, data, rr.Body.Bytes()) + }) + t.Run("HeadersExample", func(t *testing.T) { + header1 := "value1" + header2 := "890" + value := "asdf" + requestBody := clientAPI.Example{Value: &value} + rr := testutil.NewRequest().Post("/with-headers").WithHeader("header1", header1).WithHeader("header2", header2).WithJsonBody(requestBody).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + assert.True(t, strings.HasPrefix(rr.Header().Get("Content-Type"), "application/json")) + var responseBody clientAPI.Example + err := json.NewDecoder(rr.Body).Decode(&responseBody) + assert.NoError(t, err) + assert.Equal(t, requestBody, responseBody) + assert.Equal(t, header1, rr.Header().Get("header1")) + assert.Equal(t, header2, rr.Header().Get("header2")) + }) + t.Run("UnspecifiedContentType", func(t *testing.T) { + data := []byte("image data") + contentType := "image/jpeg" + rr := testutil.NewRequest().Post("/unspecified-content-type").WithContentType(contentType).WithBody(data).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + assert.Equal(t, contentType, rr.Header().Get("Content-Type")) + assert.Equal(t, data, rr.Body.Bytes()) + }) + t.Run("ReusableResponses", func(t *testing.T) { + value := "jkl;" + requestBody := clientAPI.Example{Value: &value} + rr := testutil.NewRequest().Post("/reusable-responses").WithJsonBody(requestBody).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + assert.True(t, strings.HasPrefix(rr.Header().Get("Content-Type"), "application/json")) + var responseBody clientAPI.Example + err := json.NewDecoder(rr.Body).Decode(&responseBody) + assert.NoError(t, err) + assert.Equal(t, requestBody, responseBody) + }) + t.Run("UnionResponses", func(t *testing.T) { + value := "union" + requestBody := clientAPI.Example{Value: &value} + rr := testutil.NewRequest().Post("/with-union").WithJsonBody(requestBody).GoWithHTTPHandler(t, handler).Recorder + assert.Equal(t, http.StatusOK, rr.Code) + assert.True(t, strings.HasPrefix(rr.Header().Get("Content-Type"), "application/json")) + var responseBody clientAPI.Example + err := json.NewDecoder(rr.Body).Decode(&responseBody) + assert.NoError(t, err) + assert.Equal(t, requestBody, responseBody) + }) +} diff --git a/internal/test/strict-server/fiber/go.mod b/internal/test/strict-server/fiber/go.mod new file mode 100644 index 0000000000..71331c7725 --- /dev/null +++ b/internal/test/strict-server/fiber/go.mod @@ -0,0 +1,55 @@ +module github.com/livesession/oapi-codegen/v2/internal/test/strict-server/fiber + +go 1.24.0 + +replace github.com/livesession/oapi-codegen/v2 => ../../../../ + +replace github.com/livesession/oapi-codegen/v2/internal/test => ../.. + +tool github.com/livesession/oapi-codegen/v2/cmd/oapi-codegen + +require ( + github.com/getkin/kin-openapi v0.133.0 + github.com/gofiber/fiber/v2 v2.52.11 + github.com/livesession/oapi-codegen/v2/internal/test v0.0.0-00010101000000-000000000000 + github.com/oapi-codegen/runtime v1.1.0 + github.com/oapi-codegen/testutil v1.0.0 + github.com/stretchr/testify v1.11.1 +) + +require ( + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/livesession/oapi-codegen/v2 v2.0.0-00010101000000-000000000000 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect + github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect + github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rivo/uniseg v0.4.4 // indirect + github.com/speakeasy-api/jsonpath v0.6.0 // indirect + github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.51.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect + github.com/woodsbury/decimal128 v1.3.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect + golang.org/x/tools v0.30.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/internal/test/strict-server/fiber/go.sum b/internal/test/strict-server/fiber/go.sum new file mode 100644 index 0000000000..f585043c1b --- /dev/null +++ b/internal/test/strict-server/fiber/go.sum @@ -0,0 +1,210 @@ +github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= +github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= +github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +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/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= +github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= +github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ= +github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= +github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/gofiber/fiber/v2 v2.52.11 h1:5f4yzKLcBcF8ha1GQTWB+mpblWz3Vz6nSAbTL31HkWs= +github.com/gofiber/fiber/v2 v2.52.11/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oapi-codegen/runtime v1.1.0 h1:rJpoNUawn5XTvekgfkvSZr0RqEnoYpFkyvrzfWeFKWM= +github.com/oapi-codegen/runtime v1.1.0/go.mod h1:BeSfBkWWWnAnGdyS+S/GnlbmHKzf8/hwkvelJZDeKA8= +github.com/oapi-codegen/testutil v1.0.0 h1:1GI2IiMMLh2vDHr1OkNacaYU/VaApKdcmfgl4aeXAa8= +github.com/oapi-codegen/testutil v1.0.0/go.mod h1:ttCaYbHvJtHuiyeBF0tPIX+4uhEPTeizXKx28okijLw= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= +github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/speakeasy-api/jsonpath v0.6.0 h1:IhtFOV9EbXplhyRqsVhHoBmmYjblIRh5D1/g8DHMXJ8= +github.com/speakeasy-api/jsonpath v0.6.0/go.mod h1:ymb2iSkyOycmzKwbEAYPJV/yi2rSmvBCLZJcyD+VVWw= +github.com/speakeasy-api/openapi-overlay v0.10.2 h1:VOdQ03eGKeiHnpb1boZCGm7x8Haj6gST0P3SGTX95GU= +github.com/speakeasy-api/openapi-overlay v0.10.2/go.mod h1:n0iOU7AqKpNFfEt6tq7qYITC4f0yzVVdFw0S7hukemg= +github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= +github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= +github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= +github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0= +github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/test/strict-server/fiber/server.gen.go b/internal/test/strict-server/fiber/server.gen.go index 559bfd9f42..0a5f8c3ccc 100644 --- a/internal/test/strict-server/fiber/server.gen.go +++ b/internal/test/strict-server/fiber/server.gen.go @@ -9,6 +9,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "mime" @@ -38,6 +39,12 @@ type ServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(c *fiber.Ctx) error + // (POST /required-json-body) + RequiredJSONBody(c *fiber.Ctx) error + + // (POST /required-text-body) + RequiredTextBody(c *fiber.Ctx) error + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(c *fiber.Ctx, pType string) error @@ -94,6 +101,18 @@ func (siw *ServerInterfaceWrapper) MultipleRequestAndResponseTypes(c *fiber.Ctx) return siw.Handler.MultipleRequestAndResponseTypes(c) } +// RequiredJSONBody operation middleware +func (siw *ServerInterfaceWrapper) RequiredJSONBody(c *fiber.Ctx) error { + + return siw.Handler.RequiredJSONBody(c) +} + +// RequiredTextBody operation middleware +func (siw *ServerInterfaceWrapper) RequiredTextBody(c *fiber.Ctx) error { + + return siw.Handler.RequiredTextBody(c) +} + // ReservedGoKeywordParameters operation middleware func (siw *ServerInterfaceWrapper) ReservedGoKeywordParameters(c *fiber.Ctx) error { @@ -151,10 +170,14 @@ func (siw *ServerInterfaceWrapper) HeadersExample(c *fiber.Ctx) error { headers := c.GetReqHeaders() // ------------- Required header parameter "header1" ------------- - if value, found := headers[http.CanonicalHeaderKey("header1")]; found { + if valueList, found := headers[http.CanonicalHeaderKey("header1")]; found { var Header1 string + n := len(valueList) + if n != 1 { + return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Too many values for ParamName header1, 1 is required, but %d found", n)) + } - err = runtime.BindStyledParameterWithOptions("simple", "header1", value, &Header1, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "header1", valueList[0], &Header1, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: false, Required: true}) if err != nil { return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for parameter header1: %w", err).Error()) } @@ -167,10 +190,14 @@ func (siw *ServerInterfaceWrapper) HeadersExample(c *fiber.Ctx) error { } // ------------- Optional header parameter "header2" ------------- - if value, found := headers[http.CanonicalHeaderKey("header2")]; found { + if valueList, found := headers[http.CanonicalHeaderKey("header2")]; found { var Header2 int + n := len(valueList) + if n != 1 { + return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Too many values for ParamName header2, 1 is required, but %d found", n)) + } - err = runtime.BindStyledParameterWithOptions("simple", "header2", value, &Header2, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: false, Required: false}) + err = runtime.BindStyledParameterWithOptions("simple", "header2", valueList[0], &Header2, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: false, Required: false}) if err != nil { return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for parameter header2: %w", err).Error()) } @@ -217,6 +244,10 @@ func RegisterHandlersWithOptions(router fiber.Router, si ServerInterface, option router.Post(options.BaseURL+"/multiple", wrapper.MultipleRequestAndResponseTypes) + router.Post(options.BaseURL+"/required-json-body", wrapper.RequiredJSONBody) + + router.Post(options.BaseURL+"/required-text-body", wrapper.RequiredTextBody) + router.Get(options.BaseURL+"/reserved-go-keyword-parameters/:type", wrapper.ReservedGoKeywordParameters) router.Post(options.BaseURL+"/reusable-responses", wrapper.ReusableResponses) @@ -433,6 +464,73 @@ func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestA return nil } +type RequiredJSONBodyRequestObject struct { + Body *RequiredJSONBodyJSONRequestBody +} + +type RequiredJSONBodyResponseObject interface { + VisitRequiredJSONBodyResponse(ctx *fiber.Ctx) error +} + +type RequiredJSONBody200JSONResponse Example + +func (response RequiredJSONBody200JSONResponse) VisitRequiredJSONBodyResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/json") + ctx.Status(200) + + return ctx.JSON(&response) +} + +type RequiredJSONBody400Response = BadrequestResponse + +func (response RequiredJSONBody400Response) VisitRequiredJSONBodyResponse(ctx *fiber.Ctx) error { + ctx.Status(400) + return nil +} + +type RequiredJSONBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredJSONBodydefaultResponse) VisitRequiredJSONBodyResponse(ctx *fiber.Ctx) error { + ctx.Status(response.StatusCode) + return nil +} + +type RequiredTextBodyRequestObject struct { + Body *RequiredTextBodyTextRequestBody +} + +type RequiredTextBodyResponseObject interface { + VisitRequiredTextBodyResponse(ctx *fiber.Ctx) error +} + +type RequiredTextBody200TextResponse string + +func (response RequiredTextBody200TextResponse) VisitRequiredTextBodyResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "text/plain") + ctx.Status(200) + + _, err := ctx.WriteString(string(response)) + return err +} + +type RequiredTextBody400Response = BadrequestResponse + +func (response RequiredTextBody400Response) VisitRequiredTextBodyResponse(ctx *fiber.Ctx) error { + ctx.Status(400) + return nil +} + +type RequiredTextBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredTextBodydefaultResponse) VisitRequiredTextBodyResponse(ctx *fiber.Ctx) error { + ctx.Status(response.StatusCode) + return nil +} + type ReservedGoKeywordParametersRequestObject struct { Type string `json:"type"` } @@ -780,6 +878,12 @@ type StrictServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error) + // (POST /required-json-body) + RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) + + // (POST /required-text-body) + RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) @@ -824,9 +928,12 @@ func (sh *strictHandler) JSONExample(ctx *fiber.Ctx) error { var body JSONExampleJSONRequestBody if err := ctx.BodyParser(&body); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + if !errors.Is(err, io.EOF) { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) { return sh.ssi.JSONExample(ctx.UserContext(), request.(JSONExampleRequestObject)) @@ -917,9 +1024,12 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx *fiber.Ctx) error { var body MultipleRequestAndResponseTypesJSONRequestBody if err := ctx.BodyParser(&body); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + if !errors.Is(err, io.EOF) { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + } else { + request.JSONBody = &body } - request.JSONBody = &body } if strings.HasPrefix(string(ctx.Request().Header.ContentType()), "application/x-www-form-urlencoded") { var body MultipleRequestAndResponseTypesFormdataRequestBody @@ -936,8 +1046,10 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx *fiber.Ctx) error { } if strings.HasPrefix(string(ctx.Request().Header.ContentType()), "text/plain") { data := ctx.Request().Body() - body := MultipleRequestAndResponseTypesTextRequestBody(data) - request.TextBody = &body + if len(data) > 0 { + body := MultipleRequestAndResponseTypesTextRequestBody(data) + request.TextBody = &body + } } handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) { @@ -961,6 +1073,66 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx *fiber.Ctx) error { return nil } +// RequiredJSONBody operation middleware +func (sh *strictHandler) RequiredJSONBody(ctx *fiber.Ctx) error { + var request RequiredJSONBodyRequestObject + + var body RequiredJSONBodyJSONRequestBody + if err := ctx.BodyParser(&body); err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + request.Body = &body + + handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) { + return sh.ssi.RequiredJSONBody(ctx.UserContext(), request.(RequiredJSONBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredJSONBody") + } + + response, err := handler(ctx, request) + + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } else if validResponse, ok := response.(RequiredJSONBodyResponseObject); ok { + if err := validResponse.VisitRequiredJSONBodyResponse(ctx); err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + } else if response != nil { + return fmt.Errorf("unexpected response type: %T", response) + } + return nil +} + +// RequiredTextBody operation middleware +func (sh *strictHandler) RequiredTextBody(ctx *fiber.Ctx) error { + var request RequiredTextBodyRequestObject + + data := ctx.Request().Body() + body := RequiredTextBodyTextRequestBody(data) + request.Body = &body + + handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) { + return sh.ssi.RequiredTextBody(ctx.UserContext(), request.(RequiredTextBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredTextBody") + } + + response, err := handler(ctx, request) + + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } else if validResponse, ok := response.(RequiredTextBodyResponseObject); ok { + if err := validResponse.VisitRequiredTextBodyResponse(ctx); err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + } else if response != nil { + return fmt.Errorf("unexpected response type: %T", response) + } + return nil +} + // ReservedGoKeywordParameters operation middleware func (sh *strictHandler) ReservedGoKeywordParameters(ctx *fiber.Ctx, pType string) error { var request ReservedGoKeywordParametersRequestObject @@ -994,9 +1166,12 @@ func (sh *strictHandler) ReusableResponses(ctx *fiber.Ctx) error { var body ReusableResponsesJSONRequestBody if err := ctx.BodyParser(&body); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + if !errors.Is(err, io.EOF) { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) { return sh.ssi.ReusableResponses(ctx.UserContext(), request.(ReusableResponsesRequestObject)) @@ -1024,8 +1199,10 @@ func (sh *strictHandler) TextExample(ctx *fiber.Ctx) error { var request TextExampleRequestObject data := ctx.Request().Body() - body := TextExampleTextRequestBody(data) - request.Body = &body + if len(data) > 0 { + body := TextExampleTextRequestBody(data) + request.Body = &body + } handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) { return sh.ssi.TextExample(ctx.UserContext(), request.(TextExampleRequestObject)) @@ -1143,9 +1320,12 @@ func (sh *strictHandler) HeadersExample(ctx *fiber.Ctx, params HeadersExamplePar var body HeadersExampleJSONRequestBody if err := ctx.BodyParser(&body); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + if !errors.Is(err, io.EOF) { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) { return sh.ssi.HeadersExample(ctx.UserContext(), request.(HeadersExampleRequestObject)) @@ -1174,9 +1354,12 @@ func (sh *strictHandler) UnionExample(ctx *fiber.Ctx) error { var body UnionExampleJSONRequestBody if err := ctx.BodyParser(&body); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + if !errors.Is(err, io.EOF) { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) { return sh.ssi.UnionExample(ctx.UserContext(), request.(UnionExampleRequestObject)) @@ -1202,24 +1385,25 @@ func (sh *strictHandler) UnionExample(ctx *fiber.Ctx) error { // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+xYS3PbNhD+Kxi0p5QUZccn3hpPJm3T1h3ZPnV8gIilhIQE0MVStEaj/94BQb0sWpUS", - "PTqZ3PhY7C6+b3ex2BnPTGmNBk2OpzOO4KzRDpqXoZAI/1TgyL9JcBkqS8ponvJ3Qg7af/OII1RODAtY", - "LPfymdEEulkqrC1UJvzS5JPz62fcZWMohX/6ESHnKf8hWbmShL8ugWdR2gL4fD6PXnhw95FHfAxCAjbe", - "hserTd00tcBT7giVHnGvJIhdd4opTTAC9Na8aOuEF1j4kc64RWMBSQWMJqKooNtS+8UMP0FGYQdK52Yb", - "y1ujSSjtmFR5DgiaWAse8zocc5W1BgkkG06Zt5ARc4ATQB5xUuQd4/fr31nrsOMRnwC6YOiq1+/1PV/G", - "ghZW8ZS/bT5F3AoaNxtaEmRNF++/3d/9yZRjoiJTClKZKIopKwW6sShAMqXJeBerjFyPN5awIf5X2a5+", - "30Lpo6YJoHdGTk8RME1croXzdb9/pricR/wmGOvSsXQqWUuwRk0uqqID80f9WZtaM0A02O4sKauClBVI", - "61xtov3HQmQfyJf6ktxgGUtB4kSoH8vSpYGPEQpBIPcgYBAkD+NhTf1JWfgaOxfloK3HnXXqfmxqx8am", - "ZmSYBFGwWtGYLRa+KLBKM8Gc0qMC2MKpqJPMAtpj72ctB+1eHryOk9ezaEPLc1zXddwkUIUF6MzIL6Mw", - "4qoUI0isHm0u97oF8ZQPp+RDdvuAO1IiR5zgmRJbCKV3n95nKunfkT5aYod0RWi6EhmPTPwZprVBGVuB", - "ogQCdMnMW597xSPoSOW/lpIsE5oNgWlRgmQiJ0D2wbBWpdtK2UFr94P5GERWqpqWZ/mS/j3jHpKmDeIR", - "9wZ4GlAJea3Qk05YQbQDtqf/jM+vImCBZmi24w1T3WVwUaKW0CHkzpfELuY68AuWBmsSl2nadkfc1vXj", - "HGeQZ/L1o/8Bnvdqu45Y+s6d24cCVoWPr2PWrtoHti+spHugOFESTFLamwM1XwxUZyFTuQIZt7uIg2+v", - "lYRbozME2myB/JVOG2JLZf6mSWNgAYGIOcNqYGXliFnhHFPUVJFChduqhK3i8bjy7DZYeliV012svjkR", - "p28uxehN/+rwJW9PHDcbrcwr+Tj4/X2QOfTOfrSe6cCO73h2L5TO/pISrw21ulP4lyCwOtMzUBPfEWnJ", - "EKhCDZJNlFgMYrZys1WworWrFwpurLqhxYDtkIYo2qnrmke7hnBP3/CI6JSjy3PFaaXVrlHho//N2h76", - "5dmgjP6fDgJFQYBakJrAT8e5QW5rMRru8ibTXrAc7Wnh6duLqnnEw+w6lKAKC18niGyaJGHm3XO1GI0A", - "e8okwiqPwr8BAAD//4h9qqfAGAAA", + "H4sIAAAAAAAC/+xZTXPbNhP+Kzt431NKmrbjE2+NJ5O2aeuObJ86PkDESkJCAiiwFK3R6L93QEBfFq1K", + "qT4ynt5Ecr/wPLuLBTRlha6MVqjIsXzKLDqjlcP2oc+Fxb9qdOSfBLrCSkNSK5azD1z04rdZwizWjvdL", + "nKt7+UIrQtWqcmNKWXCvmn1xXn/KXDHCivtf/7c4YDn7X7YMJQtfXYbPvDIlstlslryI4O4zS9gIuUDb", + "Rht+Xq3bpolBljNHVqoh80aC2HWnmFSEQ7TemxeNQXiBeRz5lBmrDVqSAaMxL2vs9hTf6P4XLCisQKqB", + "3sTyViviUjkQcjBAi4ogggfehgNXG6MtoYD+BLyHgsChHaNlCSNJPjB2v/oeYsCOJWyM1gVHVxeXF5ee", + "L21QcSNZzt63rxJmOI3aBS0IMrqL91/u734H6YDXpCtOsuBlOYGKWzfiJQqQirQPsS7IXbDWk22J/1lE", + "7Y8RSp81bQJ90GJyjIRp83Ilna8vL0+Ul7OE3QRnXTYWQWUrBdaaGfC67MD8UX1VulGA1mobV5ZVdUnS", + "cEurXK2j/dtcZBfIF/aygbZVKjjxI6F+KE/nBj61WHJCsQMBvSC5Hw8r5o/Kwr/xc1YOYj/u7FP3I904", + "GOkGSINAXkIjaQRzxRcNVirg4KQalgjzoJJOMkuM296PSvTiWh68jaP3s2TNynPaNE3aFlBtS1SFFt9G", + "YcJkxYeYGTVcV/e2ObGc9SfkU3ZzgztQISeM8JkyU3Kptu/eJ2rp/yF9sMIO5eofpUWRekbSfqyP7sKN", + "5QVeyg8ac90EnIZKOl+l4aMb6boUwMuGT1zoD5sTRy+q+8mjLcyjjx3BgffJcrI1vu0xZEGtz6zzUPuA", + "z/SP1O6R+PvSd+qa2p+i9kwg0qFOv+Kk0VakhlteIaF12dTHOfO2hthh8o+FJBRcQR9B8QoF8AGhhU8a", + "oknXwU/w+0l/DiJLU+2BY/GQ/zllHrz2EMIS5h2wPOD3ko5kC8BPx6VqjmY46qZrrl5L+Cgyh87iwPmB", + "pIvjDvyCp96KxHmOTNtzc+Pwf4qk9ky+Pnj7lrDLsH3AweN77wJ1ePk6ZlFrF9i+cY7ZAcWxFKizytzs", + "aflsoDqDhRxIFGlcRRpie60l3GpVWKT1A4jfDJUmWBiD/gRohBAQaPfHBqGqHYHhzoGktouUMtwVCdxo", + "Ho/LyG6Dp4dlO93G6rsjcfruXIzeXF7tr/L+yHmzdpB4pR57v34MMvvemB3sxLLneetwfs9Uzo2kUbpy", + "pdxdwj8FgeWeXqAc+4lICbBItVUoYCz5/Bp0ozajgSWtXbNQCGM5Dc2vt/cZiJKttq5Zsu0K/OkNX9Ae", + "84+DU+VpreS2i/pH/xniDP1yb5BafafX8LwktIqTHOMPh7m/2bSiFd4N2kp7wXKyo4ent5dVs4SFf45C", + "C6pt6fsEkcmzLPzjdOEaPhyivZA640Z6FP4OAAD//0nTejA+HAAA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/test/strict-server/fiber/server.go b/internal/test/strict-server/fiber/server.go index 989df4b09c..fc6d4b5a17 100644 --- a/internal/test/strict-server/fiber/server.go +++ b/internal/test/strict-server/fiber/server.go @@ -126,6 +126,14 @@ func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableRes return ReusableResponses200JSONResponse{ReusableresponseJSONResponse: ReusableresponseJSONResponse{Body: *request.Body}}, nil } +func (s StrictServer) RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) { + return RequiredJSONBody200JSONResponse(*request.Body), nil +} + +func (s StrictServer) RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) { + return RequiredTextBody200TextResponse(*request.Body), nil +} + func (s StrictServer) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) { return ReservedGoKeywordParameters200TextResponse(""), nil } diff --git a/internal/test/strict-server/fiber/types.gen.go b/internal/test/strict-server/fiber/types.gen.go index e0781f12f9..9b74c20754 100644 --- a/internal/test/strict-server/fiber/types.gen.go +++ b/internal/test/strict-server/fiber/types.gen.go @@ -14,6 +14,9 @@ type Reusableresponse = Example // MultipleRequestAndResponseTypesTextBody defines parameters for MultipleRequestAndResponseTypes. type MultipleRequestAndResponseTypesTextBody = string +// RequiredTextBodyTextBody defines parameters for RequiredTextBody. +type RequiredTextBodyTextBody = string + // TextExampleTextBody defines parameters for TextExample. type TextExampleTextBody = string @@ -44,6 +47,12 @@ type MultipleRequestAndResponseTypesMultipartRequestBody = Example // MultipleRequestAndResponseTypesTextRequestBody defines body for MultipleRequestAndResponseTypes for text/plain ContentType. type MultipleRequestAndResponseTypesTextRequestBody = MultipleRequestAndResponseTypesTextBody +// RequiredJSONBodyJSONRequestBody defines body for RequiredJSONBody for application/json ContentType. +type RequiredJSONBodyJSONRequestBody = Example + +// RequiredTextBodyTextRequestBody defines body for RequiredTextBody for text/plain ContentType. +type RequiredTextBodyTextRequestBody = RequiredTextBodyTextBody + // ReusableResponsesJSONRequestBody defines body for ReusableResponses for application/json ContentType. type ReusableResponsesJSONRequestBody = Example diff --git a/internal/test/strict-server/gin/server.gen.go b/internal/test/strict-server/gin/server.gen.go index c5937565f6..742978fb28 100644 --- a/internal/test/strict-server/gin/server.gen.go +++ b/internal/test/strict-server/gin/server.gen.go @@ -9,6 +9,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "mime" @@ -39,6 +40,12 @@ type ServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(c *gin.Context) + // (POST /required-json-body) + RequiredJSONBody(c *gin.Context) + + // (POST /required-text-body) + RequiredTextBody(c *gin.Context) + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(c *gin.Context, pType string) @@ -125,6 +132,32 @@ func (siw *ServerInterfaceWrapper) MultipleRequestAndResponseTypes(c *gin.Contex siw.Handler.MultipleRequestAndResponseTypes(c) } +// RequiredJSONBody operation middleware +func (siw *ServerInterfaceWrapper) RequiredJSONBody(c *gin.Context) { + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.RequiredJSONBody(c) +} + +// RequiredTextBody operation middleware +func (siw *ServerInterfaceWrapper) RequiredTextBody(c *gin.Context) { + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.RequiredTextBody(c) +} + // ReservedGoKeywordParameters operation middleware func (siw *ServerInterfaceWrapper) ReservedGoKeywordParameters(c *gin.Context) { @@ -319,6 +352,8 @@ func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options router.POST(options.BaseURL+"/multipart", wrapper.MultipartExample) router.POST(options.BaseURL+"/multipart-related", wrapper.MultipartRelatedExample) router.POST(options.BaseURL+"/multiple", wrapper.MultipleRequestAndResponseTypes) + router.POST(options.BaseURL+"/required-json-body", wrapper.RequiredJSONBody) + router.POST(options.BaseURL+"/required-text-body", wrapper.RequiredTextBody) router.GET(options.BaseURL+"/reserved-go-keyword-parameters/:type", wrapper.ReservedGoKeywordParameters) router.POST(options.BaseURL+"/reusable-responses", wrapper.ReusableResponses) router.POST(options.BaseURL+"/text", wrapper.TextExample) @@ -527,6 +562,73 @@ func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestA return nil } +type RequiredJSONBodyRequestObject struct { + Body *RequiredJSONBodyJSONRequestBody +} + +type RequiredJSONBodyResponseObject interface { + VisitRequiredJSONBodyResponse(w http.ResponseWriter) error +} + +type RequiredJSONBody200JSONResponse Example + +func (response RequiredJSONBody200JSONResponse) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type RequiredJSONBody400Response = BadrequestResponse + +func (response RequiredJSONBody400Response) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(400) + return nil +} + +type RequiredJSONBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredJSONBodydefaultResponse) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(response.StatusCode) + return nil +} + +type RequiredTextBodyRequestObject struct { + Body *RequiredTextBodyTextRequestBody +} + +type RequiredTextBodyResponseObject interface { + VisitRequiredTextBodyResponse(w http.ResponseWriter) error +} + +type RequiredTextBody200TextResponse string + +func (response RequiredTextBody200TextResponse) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(200) + + _, err := w.Write([]byte(response)) + return err +} + +type RequiredTextBody400Response = BadrequestResponse + +func (response RequiredTextBody400Response) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(400) + return nil +} + +type RequiredTextBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredTextBodydefaultResponse) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(response.StatusCode) + return nil +} + type ReservedGoKeywordParametersRequestObject struct { Type string `json:"type"` } @@ -874,6 +976,12 @@ type StrictServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error) + // (POST /required-json-body) + RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) + + // (POST /required-text-body) + RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) @@ -917,11 +1025,14 @@ func (sh *strictHandler) JSONExample(ctx *gin.Context) { var body JSONExampleJSONRequestBody if err := ctx.ShouldBindJSON(&body); err != nil { - ctx.Status(http.StatusBadRequest) - ctx.Error(err) - return + if !errors.Is(err, io.EOF) { + ctx.Status(http.StatusBadRequest) + ctx.Error(err) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { return sh.ssi.JSONExample(ctx, request.(JSONExampleRequestObject)) @@ -1019,11 +1130,14 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx *gin.Context) { var body MultipleRequestAndResponseTypesJSONRequestBody if err := ctx.ShouldBindJSON(&body); err != nil { - ctx.Status(http.StatusBadRequest) - ctx.Error(err) - return + if !errors.Is(err, io.EOF) { + ctx.Status(http.StatusBadRequest) + ctx.Error(err) + return + } + } else { + request.JSONBody = &body } - request.JSONBody = &body } if strings.HasPrefix(ctx.GetHeader("Content-Type"), "application/x-www-form-urlencoded") { if err := ctx.Request.ParseForm(); err != nil { @@ -1054,8 +1168,10 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx *gin.Context) { ctx.Error(err) return } - body := MultipleRequestAndResponseTypesTextRequestBody(data) - request.TextBody = &body + if len(data) > 0 { + body := MultipleRequestAndResponseTypesTextRequestBody(data) + request.TextBody = &body + } } handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { @@ -1079,6 +1195,72 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx *gin.Context) { } } +// RequiredJSONBody operation middleware +func (sh *strictHandler) RequiredJSONBody(ctx *gin.Context) { + var request RequiredJSONBodyRequestObject + + var body RequiredJSONBodyJSONRequestBody + if err := ctx.ShouldBindJSON(&body); err != nil { + ctx.Status(http.StatusBadRequest) + ctx.Error(err) + return + } + request.Body = &body + + handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { + return sh.ssi.RequiredJSONBody(ctx, request.(RequiredJSONBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredJSONBody") + } + + response, err := handler(ctx, request) + + if err != nil { + ctx.Error(err) + ctx.Status(http.StatusInternalServerError) + } else if validResponse, ok := response.(RequiredJSONBodyResponseObject); ok { + if err := validResponse.VisitRequiredJSONBodyResponse(ctx.Writer); err != nil { + ctx.Error(err) + } + } else if response != nil { + ctx.Error(fmt.Errorf("unexpected response type: %T", response)) + } +} + +// RequiredTextBody operation middleware +func (sh *strictHandler) RequiredTextBody(ctx *gin.Context) { + var request RequiredTextBodyRequestObject + + data, err := io.ReadAll(ctx.Request.Body) + if err != nil { + ctx.Error(err) + return + } + body := RequiredTextBodyTextRequestBody(data) + request.Body = &body + + handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { + return sh.ssi.RequiredTextBody(ctx, request.(RequiredTextBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredTextBody") + } + + response, err := handler(ctx, request) + + if err != nil { + ctx.Error(err) + ctx.Status(http.StatusInternalServerError) + } else if validResponse, ok := response.(RequiredTextBodyResponseObject); ok { + if err := validResponse.VisitRequiredTextBodyResponse(ctx.Writer); err != nil { + ctx.Error(err) + } + } else if response != nil { + ctx.Error(fmt.Errorf("unexpected response type: %T", response)) + } +} + // ReservedGoKeywordParameters operation middleware func (sh *strictHandler) ReservedGoKeywordParameters(ctx *gin.Context, pType string) { var request ReservedGoKeywordParametersRequestObject @@ -1112,11 +1294,14 @@ func (sh *strictHandler) ReusableResponses(ctx *gin.Context) { var body ReusableResponsesJSONRequestBody if err := ctx.ShouldBindJSON(&body); err != nil { - ctx.Status(http.StatusBadRequest) - ctx.Error(err) - return + if !errors.Is(err, io.EOF) { + ctx.Status(http.StatusBadRequest) + ctx.Error(err) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { return sh.ssi.ReusableResponses(ctx, request.(ReusableResponsesRequestObject)) @@ -1148,8 +1333,10 @@ func (sh *strictHandler) TextExample(ctx *gin.Context) { ctx.Error(err) return } - body := TextExampleTextRequestBody(data) - request.Body = &body + if len(data) > 0 { + body := TextExampleTextRequestBody(data) + request.Body = &body + } handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { return sh.ssi.TextExample(ctx, request.(TextExampleRequestObject)) @@ -1272,11 +1459,14 @@ func (sh *strictHandler) HeadersExample(ctx *gin.Context, params HeadersExampleP var body HeadersExampleJSONRequestBody if err := ctx.ShouldBindJSON(&body); err != nil { - ctx.Status(http.StatusBadRequest) - ctx.Error(err) - return + if !errors.Is(err, io.EOF) { + ctx.Status(http.StatusBadRequest) + ctx.Error(err) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { return sh.ssi.HeadersExample(ctx, request.(HeadersExampleRequestObject)) @@ -1305,11 +1495,14 @@ func (sh *strictHandler) UnionExample(ctx *gin.Context) { var body UnionExampleJSONRequestBody if err := ctx.ShouldBindJSON(&body); err != nil { - ctx.Status(http.StatusBadRequest) - ctx.Error(err) - return + if !errors.Is(err, io.EOF) { + ctx.Status(http.StatusBadRequest) + ctx.Error(err) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { return sh.ssi.UnionExample(ctx, request.(UnionExampleRequestObject)) @@ -1335,24 +1528,25 @@ func (sh *strictHandler) UnionExample(ctx *gin.Context) { // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+xYS3PbNhD+Kxi0p5QUZccn3hpPJm3T1h3ZPnV8gIilhIQE0MVStEaj/94BQb0sWpUS", - "PTqZ3PhY7C6+b3ex2BnPTGmNBk2OpzOO4KzRDpqXoZAI/1TgyL9JcBkqS8ponvJ3Qg7af/OII1RODAtY", - "LPfymdEEulkqrC1UJvzS5JPz62fcZWMohX/6ESHnKf8hWbmShL8ugWdR2gL4fD6PXnhw95FHfAxCAjbe", - "hserTd00tcBT7giVHnGvJIhdd4opTTAC9Na8aOuEF1j4kc64RWMBSQWMJqKooNtS+8UMP0FGYQdK52Yb", - "y1ujSSjtmFR5DgiaWAse8zocc5W1BgkkG06Zt5ARc4ATQB5xUuQd4/fr31nrsOMRnwC6YOiq1+/1PV/G", - "ghZW8ZS/bT5F3AoaNxtaEmRNF++/3d/9yZRjoiJTClKZKIopKwW6sShAMqXJeBerjFyPN5awIf5X2a5+", - "30Lpo6YJoHdGTk8RME1croXzdb9/pricR/wmGOvSsXQqWUuwRk0uqqID80f9WZtaM0A02O4sKauClBVI", - "61xtov3HQmQfyJf6ktxgGUtB4kSoH8vSpYGPEQpBIPcgYBAkD+NhTf1JWfgaOxfloK3HnXXqfmxqx8am", - "ZmSYBFGwWtGYLRa+KLBKM8Gc0qMC2MKpqJPMAtpj72ctB+1eHryOk9ezaEPLc1zXddwkUIUF6MzIL6Mw", - "4qoUI0isHm0u97oF8ZQPp+RDdvuAO1IiR5zgmRJbCKV3n95nKunfkT5aYod0RWi6EhmPTPwZprVBGVuB", - "ogQCdMnMW597xSPoSOW/lpIsE5oNgWlRgmQiJ0D2wbBWpdtK2UFr94P5GERWqpqWZ/mS/j3jHpKmDeIR", - "9wZ4GlAJea3Qk05YQbQDtqf/jM+vImCBZmi24w1T3WVwUaKW0CHkzpfELuY68AuWBmsSl2nadkfc1vXj", - "HGeQZ/L1o/8Bnvdqu45Y+s6d24cCVoWPr2PWrtoHti+spHugOFESTFLamwM1XwxUZyFTuQIZt7uIg2+v", - "lYRbozME2myB/JVOG2JLZf6mSWNgAYGIOcNqYGXliFnhHFPUVJFChduqhK3i8bjy7DZYeliV012svjkR", - "p28uxehN/+rwJW9PHDcbrcwr+Tj4/X2QOfTOfrSe6cCO73h2L5TO/pISrw21ulP4lyCwOtMzUBPfEWnJ", - "EKhCDZJNlFgMYrZys1WworWrFwpurLqhxYDtkIYo2qnrmke7hnBP3/CI6JSjy3PFaaXVrlHho//N2h76", - "5dmgjP6fDgJFQYBakJrAT8e5QW5rMRru8ibTXrAc7Wnh6duLqnnEw+w6lKAKC18niGyaJGHm3XO1GI0A", - "e8okwiqPwr8BAAD//4h9qqfAGAAA", + "H4sIAAAAAAAC/+xZTXPbNhP+Kzt431NKmrbjE2+NJ5O2aeuObJ86PkDESkJCAiiwFK3R6L93QEBfFq1K", + "qT4ynt5Ecr/wPLuLBTRlha6MVqjIsXzKLDqjlcP2oc+Fxb9qdOSfBLrCSkNSK5azD1z04rdZwizWjvdL", + "nKt7+UIrQtWqcmNKWXCvmn1xXn/KXDHCivtf/7c4YDn7X7YMJQtfXYbPvDIlstlslryI4O4zS9gIuUDb", + "Rht+Xq3bpolBljNHVqoh80aC2HWnmFSEQ7TemxeNQXiBeRz5lBmrDVqSAaMxL2vs9hTf6P4XLCisQKqB", + "3sTyViviUjkQcjBAi4ogggfehgNXG6MtoYD+BLyHgsChHaNlCSNJPjB2v/oeYsCOJWyM1gVHVxeXF5ee", + "L21QcSNZzt63rxJmOI3aBS0IMrqL91/u734H6YDXpCtOsuBlOYGKWzfiJQqQirQPsS7IXbDWk22J/1lE", + "7Y8RSp81bQJ90GJyjIRp83Ilna8vL0+Ul7OE3QRnXTYWQWUrBdaaGfC67MD8UX1VulGA1mobV5ZVdUnS", + "cEurXK2j/dtcZBfIF/aygbZVKjjxI6F+KE/nBj61WHJCsQMBvSC5Hw8r5o/Kwr/xc1YOYj/u7FP3I904", + "GOkGSINAXkIjaQRzxRcNVirg4KQalgjzoJJOMkuM296PSvTiWh68jaP3s2TNynPaNE3aFlBtS1SFFt9G", + "YcJkxYeYGTVcV/e2ObGc9SfkU3ZzgztQISeM8JkyU3Kptu/eJ2rp/yF9sMIO5eofpUWRekbSfqyP7sKN", + "5QVeyg8ac90EnIZKOl+l4aMb6boUwMuGT1zoD5sTRy+q+8mjLcyjjx3BgffJcrI1vu0xZEGtz6zzUPuA", + "z/SP1O6R+PvSd+qa2p+i9kwg0qFOv+Kk0VakhlteIaF12dTHOfO2hthh8o+FJBRcQR9B8QoF8AGhhU8a", + "oknXwU/w+0l/DiJLU+2BY/GQ/zllHrz2EMIS5h2wPOD3ko5kC8BPx6VqjmY46qZrrl5L+Cgyh87iwPmB", + "pIvjDvyCp96KxHmOTNtzc+Pwf4qk9ky+Pnj7lrDLsH3AweN77wJ1ePk6ZlFrF9i+cY7ZAcWxFKizytzs", + "aflsoDqDhRxIFGlcRRpie60l3GpVWKT1A4jfDJUmWBiD/gRohBAQaPfHBqGqHYHhzoGktouUMtwVCdxo", + "Ho/LyG6Dp4dlO93G6rsjcfruXIzeXF7tr/L+yHmzdpB4pR57v34MMvvemB3sxLLneetwfs9Uzo2kUbpy", + "pdxdwj8FgeWeXqAc+4lICbBItVUoYCz5/Bp0ozajgSWtXbNQCGM5Dc2vt/cZiJKttq5Zsu0K/OkNX9Ae", + "84+DU+VpreS2i/pH/xniDP1yb5BafafX8LwktIqTHOMPh7m/2bSiFd4N2kp7wXKyo4ent5dVs4SFf45C", + "C6pt6fsEkcmzLPzjdOEaPhyivZA640Z6FP4OAAD//0nTejA+HAAA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/test/strict-server/gin/server.go b/internal/test/strict-server/gin/server.go index 989df4b09c..fc6d4b5a17 100644 --- a/internal/test/strict-server/gin/server.go +++ b/internal/test/strict-server/gin/server.go @@ -126,6 +126,14 @@ func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableRes return ReusableResponses200JSONResponse{ReusableresponseJSONResponse: ReusableresponseJSONResponse{Body: *request.Body}}, nil } +func (s StrictServer) RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) { + return RequiredJSONBody200JSONResponse(*request.Body), nil +} + +func (s StrictServer) RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) { + return RequiredTextBody200TextResponse(*request.Body), nil +} + func (s StrictServer) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) { return ReservedGoKeywordParameters200TextResponse(""), nil } diff --git a/internal/test/strict-server/gin/types.gen.go b/internal/test/strict-server/gin/types.gen.go index e0781f12f9..9b74c20754 100644 --- a/internal/test/strict-server/gin/types.gen.go +++ b/internal/test/strict-server/gin/types.gen.go @@ -14,6 +14,9 @@ type Reusableresponse = Example // MultipleRequestAndResponseTypesTextBody defines parameters for MultipleRequestAndResponseTypes. type MultipleRequestAndResponseTypesTextBody = string +// RequiredTextBodyTextBody defines parameters for RequiredTextBody. +type RequiredTextBodyTextBody = string + // TextExampleTextBody defines parameters for TextExample. type TextExampleTextBody = string @@ -44,6 +47,12 @@ type MultipleRequestAndResponseTypesMultipartRequestBody = Example // MultipleRequestAndResponseTypesTextRequestBody defines body for MultipleRequestAndResponseTypes for text/plain ContentType. type MultipleRequestAndResponseTypesTextRequestBody = MultipleRequestAndResponseTypesTextBody +// RequiredJSONBodyJSONRequestBody defines body for RequiredJSONBody for application/json ContentType. +type RequiredJSONBodyJSONRequestBody = Example + +// RequiredTextBodyTextRequestBody defines body for RequiredTextBody for text/plain ContentType. +type RequiredTextBodyTextRequestBody = RequiredTextBodyTextBody + // ReusableResponsesJSONRequestBody defines body for ReusableResponses for application/json ContentType. type ReusableResponsesJSONRequestBody = Example diff --git a/internal/test/strict-server/gorilla/server.gen.go b/internal/test/strict-server/gorilla/server.gen.go index 7206ff836c..650a5a1ef0 100644 --- a/internal/test/strict-server/gorilla/server.gen.go +++ b/internal/test/strict-server/gorilla/server.gen.go @@ -9,6 +9,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "mime" @@ -39,6 +40,12 @@ type ServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(w http.ResponseWriter, r *http.Request) + // (POST /required-json-body) + RequiredJSONBody(w http.ResponseWriter, r *http.Request) + + // (POST /required-text-body) + RequiredTextBody(w http.ResponseWriter, r *http.Request) + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request, pType string) @@ -129,6 +136,34 @@ func (siw *ServerInterfaceWrapper) MultipleRequestAndResponseTypes(w http.Respon handler.ServeHTTP(w, r) } +// RequiredJSONBody operation middleware +func (siw *ServerInterfaceWrapper) RequiredJSONBody(w http.ResponseWriter, r *http.Request) { + + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.RequiredJSONBody(w, r) + })) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r) +} + +// RequiredTextBody operation middleware +func (siw *ServerInterfaceWrapper) RequiredTextBody(w http.ResponseWriter, r *http.Request) { + + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.RequiredTextBody(w, r) + })) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r) +} + // ReservedGoKeywordParameters operation middleware func (siw *ServerInterfaceWrapper) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request) { @@ -422,6 +457,10 @@ func HandlerWithOptions(si ServerInterface, options GorillaServerOptions) http.H r.HandleFunc(options.BaseURL+"/multiple", wrapper.MultipleRequestAndResponseTypes).Methods("POST") + r.HandleFunc(options.BaseURL+"/required-json-body", wrapper.RequiredJSONBody).Methods("POST") + + r.HandleFunc(options.BaseURL+"/required-text-body", wrapper.RequiredTextBody).Methods("POST") + r.HandleFunc(options.BaseURL+"/reserved-go-keyword-parameters/{type}", wrapper.ReservedGoKeywordParameters).Methods("GET") r.HandleFunc(options.BaseURL+"/reusable-responses", wrapper.ReusableResponses).Methods("POST") @@ -639,6 +678,73 @@ func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestA return nil } +type RequiredJSONBodyRequestObject struct { + Body *RequiredJSONBodyJSONRequestBody +} + +type RequiredJSONBodyResponseObject interface { + VisitRequiredJSONBodyResponse(w http.ResponseWriter) error +} + +type RequiredJSONBody200JSONResponse Example + +func (response RequiredJSONBody200JSONResponse) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type RequiredJSONBody400Response = BadrequestResponse + +func (response RequiredJSONBody400Response) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(400) + return nil +} + +type RequiredJSONBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredJSONBodydefaultResponse) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(response.StatusCode) + return nil +} + +type RequiredTextBodyRequestObject struct { + Body *RequiredTextBodyTextRequestBody +} + +type RequiredTextBodyResponseObject interface { + VisitRequiredTextBodyResponse(w http.ResponseWriter) error +} + +type RequiredTextBody200TextResponse string + +func (response RequiredTextBody200TextResponse) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(200) + + _, err := w.Write([]byte(response)) + return err +} + +type RequiredTextBody400Response = BadrequestResponse + +func (response RequiredTextBody400Response) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(400) + return nil +} + +type RequiredTextBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredTextBodydefaultResponse) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(response.StatusCode) + return nil +} + type ReservedGoKeywordParametersRequestObject struct { Type string `json:"type"` } @@ -986,6 +1092,12 @@ type StrictServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error) + // (POST /required-json-body) + RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) + + // (POST /required-text-body) + RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) @@ -1046,10 +1158,13 @@ func (sh *strictHandler) JSONExample(w http.ResponseWriter, r *http.Request) { var body JSONExampleJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.JSONExample(ctx, request.(JSONExampleRequestObject)) @@ -1144,10 +1259,13 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter, var body MultipleRequestAndResponseTypesJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.JSONBody = &body } - request.JSONBody = &body } if strings.HasPrefix(r.Header.Get("Content-Type"), "application/x-www-form-urlencoded") { if err := r.ParseForm(); err != nil { @@ -1178,8 +1296,10 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter, sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err)) return } - body := MultipleRequestAndResponseTypesTextRequestBody(data) - request.TextBody = &body + if len(data) > 0 { + body := MultipleRequestAndResponseTypesTextRequestBody(data) + request.TextBody = &body + } } handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { @@ -1202,6 +1322,69 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter, } } +// RequiredJSONBody operation middleware +func (sh *strictHandler) RequiredJSONBody(w http.ResponseWriter, r *http.Request) { + var request RequiredJSONBodyRequestObject + + var body RequiredJSONBodyJSONRequestBody + if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + request.Body = &body + + handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { + return sh.ssi.RequiredJSONBody(ctx, request.(RequiredJSONBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredJSONBody") + } + + response, err := handler(r.Context(), w, r, request) + + if err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } else if validResponse, ok := response.(RequiredJSONBodyResponseObject); ok { + if err := validResponse.VisitRequiredJSONBodyResponse(w); err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } + } else if response != nil { + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + } +} + +// RequiredTextBody operation middleware +func (sh *strictHandler) RequiredTextBody(w http.ResponseWriter, r *http.Request) { + var request RequiredTextBodyRequestObject + + data, err := io.ReadAll(r.Body) + if err != nil { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err)) + return + } + body := RequiredTextBodyTextRequestBody(data) + request.Body = &body + + handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { + return sh.ssi.RequiredTextBody(ctx, request.(RequiredTextBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredTextBody") + } + + response, err := handler(r.Context(), w, r, request) + + if err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } else if validResponse, ok := response.(RequiredTextBodyResponseObject); ok { + if err := validResponse.VisitRequiredTextBodyResponse(w); err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } + } else if response != nil { + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + } +} + // ReservedGoKeywordParameters operation middleware func (sh *strictHandler) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request, pType string) { var request ReservedGoKeywordParametersRequestObject @@ -1234,10 +1417,13 @@ func (sh *strictHandler) ReusableResponses(w http.ResponseWriter, r *http.Reques var body ReusableResponsesJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.ReusableResponses(ctx, request.(ReusableResponsesRequestObject)) @@ -1268,8 +1454,10 @@ func (sh *strictHandler) TextExample(w http.ResponseWriter, r *http.Request) { sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err)) return } - body := TextExampleTextRequestBody(data) - request.Body = &body + if len(data) > 0 { + body := TextExampleTextRequestBody(data) + request.Body = &body + } handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.TextExample(ctx, request.(TextExampleRequestObject)) @@ -1388,10 +1576,13 @@ func (sh *strictHandler) HeadersExample(w http.ResponseWriter, r *http.Request, var body HeadersExampleJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.HeadersExample(ctx, request.(HeadersExampleRequestObject)) @@ -1419,10 +1610,13 @@ func (sh *strictHandler) UnionExample(w http.ResponseWriter, r *http.Request) { var body UnionExampleJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.UnionExample(ctx, request.(UnionExampleRequestObject)) @@ -1447,24 +1641,25 @@ func (sh *strictHandler) UnionExample(w http.ResponseWriter, r *http.Request) { // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+xYS3PbNhD+Kxi0p5QUZccn3hpPJm3T1h3ZPnV8gIilhIQE0MVStEaj/94BQb0sWpUS", - "PTqZ3PhY7C6+b3ex2BnPTGmNBk2OpzOO4KzRDpqXoZAI/1TgyL9JcBkqS8ponvJ3Qg7af/OII1RODAtY", - "LPfymdEEulkqrC1UJvzS5JPz62fcZWMohX/6ESHnKf8hWbmShL8ugWdR2gL4fD6PXnhw95FHfAxCAjbe", - "hserTd00tcBT7giVHnGvJIhdd4opTTAC9Na8aOuEF1j4kc64RWMBSQWMJqKooNtS+8UMP0FGYQdK52Yb", - "y1ujSSjtmFR5DgiaWAse8zocc5W1BgkkG06Zt5ARc4ATQB5xUuQd4/fr31nrsOMRnwC6YOiq1+/1PV/G", - "ghZW8ZS/bT5F3AoaNxtaEmRNF++/3d/9yZRjoiJTClKZKIopKwW6sShAMqXJeBerjFyPN5awIf5X2a5+", - "30Lpo6YJoHdGTk8RME1croXzdb9/pricR/wmGOvSsXQqWUuwRk0uqqID80f9WZtaM0A02O4sKauClBVI", - "61xtov3HQmQfyJf6ktxgGUtB4kSoH8vSpYGPEQpBIPcgYBAkD+NhTf1JWfgaOxfloK3HnXXqfmxqx8am", - "ZmSYBFGwWtGYLRa+KLBKM8Gc0qMC2MKpqJPMAtpj72ctB+1eHryOk9ezaEPLc1zXddwkUIUF6MzIL6Mw", - "4qoUI0isHm0u97oF8ZQPp+RDdvuAO1IiR5zgmRJbCKV3n95nKunfkT5aYod0RWi6EhmPTPwZprVBGVuB", - "ogQCdMnMW597xSPoSOW/lpIsE5oNgWlRgmQiJ0D2wbBWpdtK2UFr94P5GERWqpqWZ/mS/j3jHpKmDeIR", - "9wZ4GlAJea3Qk05YQbQDtqf/jM+vImCBZmi24w1T3WVwUaKW0CHkzpfELuY68AuWBmsSl2nadkfc1vXj", - "HGeQZ/L1o/8Bnvdqu45Y+s6d24cCVoWPr2PWrtoHti+spHugOFESTFLamwM1XwxUZyFTuQIZt7uIg2+v", - "lYRbozME2myB/JVOG2JLZf6mSWNgAYGIOcNqYGXliFnhHFPUVJFChduqhK3i8bjy7DZYeliV012svjkR", - "p28uxehN/+rwJW9PHDcbrcwr+Tj4/X2QOfTOfrSe6cCO73h2L5TO/pISrw21ulP4lyCwOtMzUBPfEWnJ", - "EKhCDZJNlFgMYrZys1WworWrFwpurLqhxYDtkIYo2qnrmke7hnBP3/CI6JSjy3PFaaXVrlHho//N2h76", - "5dmgjP6fDgJFQYBakJrAT8e5QW5rMRru8ibTXrAc7Wnh6duLqnnEw+w6lKAKC18niGyaJGHm3XO1GI0A", - "e8okwiqPwr8BAAD//4h9qqfAGAAA", + "H4sIAAAAAAAC/+xZTXPbNhP+Kzt431NKmrbjE2+NJ5O2aeuObJ86PkDESkJCAiiwFK3R6L93QEBfFq1K", + "qT4ynt5Ecr/wPLuLBTRlha6MVqjIsXzKLDqjlcP2oc+Fxb9qdOSfBLrCSkNSK5azD1z04rdZwizWjvdL", + "nKt7+UIrQtWqcmNKWXCvmn1xXn/KXDHCivtf/7c4YDn7X7YMJQtfXYbPvDIlstlslryI4O4zS9gIuUDb", + "Rht+Xq3bpolBljNHVqoh80aC2HWnmFSEQ7TemxeNQXiBeRz5lBmrDVqSAaMxL2vs9hTf6P4XLCisQKqB", + "3sTyViviUjkQcjBAi4ogggfehgNXG6MtoYD+BLyHgsChHaNlCSNJPjB2v/oeYsCOJWyM1gVHVxeXF5ee", + "L21QcSNZzt63rxJmOI3aBS0IMrqL91/u734H6YDXpCtOsuBlOYGKWzfiJQqQirQPsS7IXbDWk22J/1lE", + "7Y8RSp81bQJ90GJyjIRp83Ilna8vL0+Ul7OE3QRnXTYWQWUrBdaaGfC67MD8UX1VulGA1mobV5ZVdUnS", + "cEurXK2j/dtcZBfIF/aygbZVKjjxI6F+KE/nBj61WHJCsQMBvSC5Hw8r5o/Kwr/xc1YOYj/u7FP3I904", + "GOkGSINAXkIjaQRzxRcNVirg4KQalgjzoJJOMkuM296PSvTiWh68jaP3s2TNynPaNE3aFlBtS1SFFt9G", + "YcJkxYeYGTVcV/e2ObGc9SfkU3ZzgztQISeM8JkyU3Kptu/eJ2rp/yF9sMIO5eofpUWRekbSfqyP7sKN", + "5QVeyg8ac90EnIZKOl+l4aMb6boUwMuGT1zoD5sTRy+q+8mjLcyjjx3BgffJcrI1vu0xZEGtz6zzUPuA", + "z/SP1O6R+PvSd+qa2p+i9kwg0qFOv+Kk0VakhlteIaF12dTHOfO2hthh8o+FJBRcQR9B8QoF8AGhhU8a", + "oknXwU/w+0l/DiJLU+2BY/GQ/zllHrz2EMIS5h2wPOD3ko5kC8BPx6VqjmY46qZrrl5L+Cgyh87iwPmB", + "pIvjDvyCp96KxHmOTNtzc+Pwf4qk9ky+Pnj7lrDLsH3AweN77wJ1ePk6ZlFrF9i+cY7ZAcWxFKizytzs", + "aflsoDqDhRxIFGlcRRpie60l3GpVWKT1A4jfDJUmWBiD/gRohBAQaPfHBqGqHYHhzoGktouUMtwVCdxo", + "Ho/LyG6Dp4dlO93G6rsjcfruXIzeXF7tr/L+yHmzdpB4pR57v34MMvvemB3sxLLneetwfs9Uzo2kUbpy", + "pdxdwj8FgeWeXqAc+4lICbBItVUoYCz5/Bp0ozajgSWtXbNQCGM5Dc2vt/cZiJKttq5Zsu0K/OkNX9Ae", + "84+DU+VpreS2i/pH/xniDP1yb5BafafX8LwktIqTHOMPh7m/2bSiFd4N2kp7wXKyo4ent5dVs4SFf45C", + "C6pt6fsEkcmzLPzjdOEaPhyivZA640Z6FP4OAAD//0nTejA+HAAA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/test/strict-server/gorilla/server.go b/internal/test/strict-server/gorilla/server.go index c65e1170e2..17cc5cb946 100644 --- a/internal/test/strict-server/gorilla/server.go +++ b/internal/test/strict-server/gorilla/server.go @@ -102,6 +102,14 @@ func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableRes return ReusableResponses200JSONResponse{ReusableresponseJSONResponse: ReusableresponseJSONResponse{Body: *request.Body}}, nil } +func (s StrictServer) RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) { + return RequiredJSONBody200JSONResponse(*request.Body), nil +} + +func (s StrictServer) RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) { + return RequiredTextBody200TextResponse(*request.Body), nil +} + func (s StrictServer) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) { return ReservedGoKeywordParameters200TextResponse(""), nil } diff --git a/internal/test/strict-server/gorilla/types.gen.go b/internal/test/strict-server/gorilla/types.gen.go index e0781f12f9..9b74c20754 100644 --- a/internal/test/strict-server/gorilla/types.gen.go +++ b/internal/test/strict-server/gorilla/types.gen.go @@ -14,6 +14,9 @@ type Reusableresponse = Example // MultipleRequestAndResponseTypesTextBody defines parameters for MultipleRequestAndResponseTypes. type MultipleRequestAndResponseTypesTextBody = string +// RequiredTextBodyTextBody defines parameters for RequiredTextBody. +type RequiredTextBodyTextBody = string + // TextExampleTextBody defines parameters for TextExample. type TextExampleTextBody = string @@ -44,6 +47,12 @@ type MultipleRequestAndResponseTypesMultipartRequestBody = Example // MultipleRequestAndResponseTypesTextRequestBody defines body for MultipleRequestAndResponseTypes for text/plain ContentType. type MultipleRequestAndResponseTypesTextRequestBody = MultipleRequestAndResponseTypesTextBody +// RequiredJSONBodyJSONRequestBody defines body for RequiredJSONBody for application/json ContentType. +type RequiredJSONBodyJSONRequestBody = Example + +// RequiredTextBodyTextRequestBody defines body for RequiredTextBody for text/plain ContentType. +type RequiredTextBodyTextRequestBody = RequiredTextBodyTextBody + // ReusableResponsesJSONRequestBody defines body for ReusableResponses for application/json ContentType. type ReusableResponsesJSONRequestBody = Example diff --git a/internal/test/strict-server/iris/server.gen.go b/internal/test/strict-server/iris/server.gen.go index bd0f7a4c05..0d6caf38b9 100644 --- a/internal/test/strict-server/iris/server.gen.go +++ b/internal/test/strict-server/iris/server.gen.go @@ -9,6 +9,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "mime" @@ -39,6 +40,12 @@ type ServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(ctx iris.Context) + // (POST /required-json-body) + RequiredJSONBody(ctx iris.Context) + + // (POST /required-text-body) + RequiredTextBody(ctx iris.Context) + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(ctx iris.Context, pType string) @@ -99,6 +106,20 @@ func (w *ServerInterfaceWrapper) MultipleRequestAndResponseTypes(ctx iris.Contex w.Handler.MultipleRequestAndResponseTypes(ctx) } +// RequiredJSONBody converts iris context to params. +func (w *ServerInterfaceWrapper) RequiredJSONBody(ctx iris.Context) { + + // Invoke the callback with all the unmarshaled arguments + w.Handler.RequiredJSONBody(ctx) +} + +// RequiredTextBody converts iris context to params. +func (w *ServerInterfaceWrapper) RequiredTextBody(ctx iris.Context) { + + // Invoke the callback with all the unmarshaled arguments + w.Handler.RequiredTextBody(ctx) +} + // ReservedGoKeywordParameters converts iris context to params. func (w *ServerInterfaceWrapper) ReservedGoKeywordParameters(ctx iris.Context) { @@ -238,6 +259,8 @@ func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, o router.Post(options.BaseURL+"/multipart", wrapper.MultipartExample) router.Post(options.BaseURL+"/multipart-related", wrapper.MultipartRelatedExample) router.Post(options.BaseURL+"/multiple", wrapper.MultipleRequestAndResponseTypes) + router.Post(options.BaseURL+"/required-json-body", wrapper.RequiredJSONBody) + router.Post(options.BaseURL+"/required-text-body", wrapper.RequiredTextBody) router.Get(options.BaseURL+"/reserved-go-keyword-parameters/:type", wrapper.ReservedGoKeywordParameters) router.Post(options.BaseURL+"/reusable-responses", wrapper.ReusableResponses) router.Post(options.BaseURL+"/text", wrapper.TextExample) @@ -448,6 +471,73 @@ func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestA return nil } +type RequiredJSONBodyRequestObject struct { + Body *RequiredJSONBodyJSONRequestBody +} + +type RequiredJSONBodyResponseObject interface { + VisitRequiredJSONBodyResponse(ctx iris.Context) error +} + +type RequiredJSONBody200JSONResponse Example + +func (response RequiredJSONBody200JSONResponse) VisitRequiredJSONBodyResponse(ctx iris.Context) error { + ctx.ResponseWriter().Header().Set("Content-Type", "application/json") + ctx.StatusCode(200) + + return ctx.JSON(&response) +} + +type RequiredJSONBody400Response = BadrequestResponse + +func (response RequiredJSONBody400Response) VisitRequiredJSONBodyResponse(ctx iris.Context) error { + ctx.StatusCode(400) + return nil +} + +type RequiredJSONBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredJSONBodydefaultResponse) VisitRequiredJSONBodyResponse(ctx iris.Context) error { + ctx.StatusCode(response.StatusCode) + return nil +} + +type RequiredTextBodyRequestObject struct { + Body *RequiredTextBodyTextRequestBody +} + +type RequiredTextBodyResponseObject interface { + VisitRequiredTextBodyResponse(ctx iris.Context) error +} + +type RequiredTextBody200TextResponse string + +func (response RequiredTextBody200TextResponse) VisitRequiredTextBodyResponse(ctx iris.Context) error { + ctx.ResponseWriter().Header().Set("Content-Type", "text/plain") + ctx.StatusCode(200) + + _, err := ctx.WriteString(string(response)) + return err +} + +type RequiredTextBody400Response = BadrequestResponse + +func (response RequiredTextBody400Response) VisitRequiredTextBodyResponse(ctx iris.Context) error { + ctx.StatusCode(400) + return nil +} + +type RequiredTextBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredTextBodydefaultResponse) VisitRequiredTextBodyResponse(ctx iris.Context) error { + ctx.StatusCode(response.StatusCode) + return nil +} + type ReservedGoKeywordParametersRequestObject struct { Type string `json:"type"` } @@ -795,6 +885,12 @@ type StrictServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error) + // (POST /required-json-body) + RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) + + // (POST /required-text-body) + RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) @@ -838,10 +934,13 @@ func (sh *strictHandler) JSONExample(ctx iris.Context) { var body JSONExampleJSONRequestBody if err := ctx.ReadJSON(&body); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) - return + if !errors.Is(err, io.EOF) { + ctx.StopWithError(http.StatusBadRequest, err) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx iris.Context, request interface{}) (interface{}, error) { return sh.ssi.JSONExample(ctx, request.(JSONExampleRequestObject)) @@ -945,10 +1044,13 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx iris.Context) { var body MultipleRequestAndResponseTypesJSONRequestBody if err := ctx.ReadJSON(&body); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) - return + if !errors.Is(err, io.EOF) { + ctx.StopWithError(http.StatusBadRequest, err) + return + } + } else { + request.JSONBody = &body } - request.JSONBody = &body } if strings.HasPrefix(ctx.GetHeader("Content-Type"), "application/x-www-form-urlencoded") { if err := ctx.Request().ParseForm(); err != nil { @@ -979,8 +1081,10 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx iris.Context) { ctx.StopWithError(http.StatusBadRequest, err) return } - body := MultipleRequestAndResponseTypesTextRequestBody(data) - request.TextBody = &body + if len(data) > 0 { + body := MultipleRequestAndResponseTypesTextRequestBody(data) + request.TextBody = &body + } } handler := func(ctx iris.Context, request interface{}) (interface{}, error) { @@ -1006,6 +1110,75 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx iris.Context) { } } +// RequiredJSONBody operation middleware +func (sh *strictHandler) RequiredJSONBody(ctx iris.Context) { + var request RequiredJSONBodyRequestObject + + var body RequiredJSONBodyJSONRequestBody + if err := ctx.ReadJSON(&body); err != nil { + ctx.StopWithError(http.StatusBadRequest, err) + return + } + request.Body = &body + + handler := func(ctx iris.Context, request interface{}) (interface{}, error) { + return sh.ssi.RequiredJSONBody(ctx, request.(RequiredJSONBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredJSONBody") + } + + response, err := handler(ctx, request) + + if err != nil { + ctx.StopWithError(http.StatusBadRequest, err) + return + } else if validResponse, ok := response.(RequiredJSONBodyResponseObject); ok { + if err := validResponse.VisitRequiredJSONBodyResponse(ctx); err != nil { + ctx.StopWithError(http.StatusBadRequest, err) + return + } + } else if response != nil { + ctx.Writef("Unexpected response type: %T", response) + return + } +} + +// RequiredTextBody operation middleware +func (sh *strictHandler) RequiredTextBody(ctx iris.Context) { + var request RequiredTextBodyRequestObject + + data, err := io.ReadAll(ctx.Request().Body) + if err != nil { + ctx.StopWithError(http.StatusBadRequest, err) + return + } + body := RequiredTextBodyTextRequestBody(data) + request.Body = &body + + handler := func(ctx iris.Context, request interface{}) (interface{}, error) { + return sh.ssi.RequiredTextBody(ctx, request.(RequiredTextBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredTextBody") + } + + response, err := handler(ctx, request) + + if err != nil { + ctx.StopWithError(http.StatusBadRequest, err) + return + } else if validResponse, ok := response.(RequiredTextBodyResponseObject); ok { + if err := validResponse.VisitRequiredTextBodyResponse(ctx); err != nil { + ctx.StopWithError(http.StatusBadRequest, err) + return + } + } else if response != nil { + ctx.Writef("Unexpected response type: %T", response) + return + } +} + // ReservedGoKeywordParameters operation middleware func (sh *strictHandler) ReservedGoKeywordParameters(ctx iris.Context, pType string) { var request ReservedGoKeywordParametersRequestObject @@ -1041,10 +1214,13 @@ func (sh *strictHandler) ReusableResponses(ctx iris.Context) { var body ReusableResponsesJSONRequestBody if err := ctx.ReadJSON(&body); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) - return + if !errors.Is(err, io.EOF) { + ctx.StopWithError(http.StatusBadRequest, err) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx iris.Context, request interface{}) (interface{}, error) { return sh.ssi.ReusableResponses(ctx, request.(ReusableResponsesRequestObject)) @@ -1078,8 +1254,10 @@ func (sh *strictHandler) TextExample(ctx iris.Context) { ctx.StopWithError(http.StatusBadRequest, err) return } - body := TextExampleTextRequestBody(data) - request.Body = &body + if len(data) > 0 { + body := TextExampleTextRequestBody(data) + request.Body = &body + } handler := func(ctx iris.Context, request interface{}) (interface{}, error) { return sh.ssi.TextExample(ctx, request.(TextExampleRequestObject)) @@ -1210,10 +1388,13 @@ func (sh *strictHandler) HeadersExample(ctx iris.Context, params HeadersExampleP var body HeadersExampleJSONRequestBody if err := ctx.ReadJSON(&body); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) - return + if !errors.Is(err, io.EOF) { + ctx.StopWithError(http.StatusBadRequest, err) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx iris.Context, request interface{}) (interface{}, error) { return sh.ssi.HeadersExample(ctx, request.(HeadersExampleRequestObject)) @@ -1244,10 +1425,13 @@ func (sh *strictHandler) UnionExample(ctx iris.Context) { var body UnionExampleJSONRequestBody if err := ctx.ReadJSON(&body); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) - return + if !errors.Is(err, io.EOF) { + ctx.StopWithError(http.StatusBadRequest, err) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx iris.Context, request interface{}) (interface{}, error) { return sh.ssi.UnionExample(ctx, request.(UnionExampleRequestObject)) @@ -1275,24 +1459,25 @@ func (sh *strictHandler) UnionExample(ctx iris.Context) { // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+xYS3PbNhD+Kxi0p5QUZccn3hpPJm3T1h3ZPnV8gIilhIQE0MVStEaj/94BQb0sWpUS", - "PTqZ3PhY7C6+b3ex2BnPTGmNBk2OpzOO4KzRDpqXoZAI/1TgyL9JcBkqS8ponvJ3Qg7af/OII1RODAtY", - "LPfymdEEulkqrC1UJvzS5JPz62fcZWMohX/6ESHnKf8hWbmShL8ugWdR2gL4fD6PXnhw95FHfAxCAjbe", - "hserTd00tcBT7giVHnGvJIhdd4opTTAC9Na8aOuEF1j4kc64RWMBSQWMJqKooNtS+8UMP0FGYQdK52Yb", - "y1ujSSjtmFR5DgiaWAse8zocc5W1BgkkG06Zt5ARc4ATQB5xUuQd4/fr31nrsOMRnwC6YOiq1+/1PV/G", - "ghZW8ZS/bT5F3AoaNxtaEmRNF++/3d/9yZRjoiJTClKZKIopKwW6sShAMqXJeBerjFyPN5awIf5X2a5+", - "30Lpo6YJoHdGTk8RME1croXzdb9/pricR/wmGOvSsXQqWUuwRk0uqqID80f9WZtaM0A02O4sKauClBVI", - "61xtov3HQmQfyJf6ktxgGUtB4kSoH8vSpYGPEQpBIPcgYBAkD+NhTf1JWfgaOxfloK3HnXXqfmxqx8am", - "ZmSYBFGwWtGYLRa+KLBKM8Gc0qMC2MKpqJPMAtpj72ctB+1eHryOk9ezaEPLc1zXddwkUIUF6MzIL6Mw", - "4qoUI0isHm0u97oF8ZQPp+RDdvuAO1IiR5zgmRJbCKV3n95nKunfkT5aYod0RWi6EhmPTPwZprVBGVuB", - "ogQCdMnMW597xSPoSOW/lpIsE5oNgWlRgmQiJ0D2wbBWpdtK2UFr94P5GERWqpqWZ/mS/j3jHpKmDeIR", - "9wZ4GlAJea3Qk05YQbQDtqf/jM+vImCBZmi24w1T3WVwUaKW0CHkzpfELuY68AuWBmsSl2nadkfc1vXj", - "HGeQZ/L1o/8Bnvdqu45Y+s6d24cCVoWPr2PWrtoHti+spHugOFESTFLamwM1XwxUZyFTuQIZt7uIg2+v", - "lYRbozME2myB/JVOG2JLZf6mSWNgAYGIOcNqYGXliFnhHFPUVJFChduqhK3i8bjy7DZYeliV012svjkR", - "p28uxehN/+rwJW9PHDcbrcwr+Tj4/X2QOfTOfrSe6cCO73h2L5TO/pISrw21ulP4lyCwOtMzUBPfEWnJ", - "EKhCDZJNlFgMYrZys1WworWrFwpurLqhxYDtkIYo2qnrmke7hnBP3/CI6JSjy3PFaaXVrlHho//N2h76", - "5dmgjP6fDgJFQYBakJrAT8e5QW5rMRru8ibTXrAc7Wnh6duLqnnEw+w6lKAKC18niGyaJGHm3XO1GI0A", - "e8okwiqPwr8BAAD//4h9qqfAGAAA", + "H4sIAAAAAAAC/+xZTXPbNhP+Kzt431NKmrbjE2+NJ5O2aeuObJ86PkDESkJCAiiwFK3R6L93QEBfFq1K", + "qT4ynt5Ecr/wPLuLBTRlha6MVqjIsXzKLDqjlcP2oc+Fxb9qdOSfBLrCSkNSK5azD1z04rdZwizWjvdL", + "nKt7+UIrQtWqcmNKWXCvmn1xXn/KXDHCivtf/7c4YDn7X7YMJQtfXYbPvDIlstlslryI4O4zS9gIuUDb", + "Rht+Xq3bpolBljNHVqoh80aC2HWnmFSEQ7TemxeNQXiBeRz5lBmrDVqSAaMxL2vs9hTf6P4XLCisQKqB", + "3sTyViviUjkQcjBAi4ogggfehgNXG6MtoYD+BLyHgsChHaNlCSNJPjB2v/oeYsCOJWyM1gVHVxeXF5ee", + "L21QcSNZzt63rxJmOI3aBS0IMrqL91/u734H6YDXpCtOsuBlOYGKWzfiJQqQirQPsS7IXbDWk22J/1lE", + "7Y8RSp81bQJ90GJyjIRp83Ilna8vL0+Ul7OE3QRnXTYWQWUrBdaaGfC67MD8UX1VulGA1mobV5ZVdUnS", + "cEurXK2j/dtcZBfIF/aygbZVKjjxI6F+KE/nBj61WHJCsQMBvSC5Hw8r5o/Kwr/xc1YOYj/u7FP3I904", + "GOkGSINAXkIjaQRzxRcNVirg4KQalgjzoJJOMkuM296PSvTiWh68jaP3s2TNynPaNE3aFlBtS1SFFt9G", + "YcJkxYeYGTVcV/e2ObGc9SfkU3ZzgztQISeM8JkyU3Kptu/eJ2rp/yF9sMIO5eofpUWRekbSfqyP7sKN", + "5QVeyg8ac90EnIZKOl+l4aMb6boUwMuGT1zoD5sTRy+q+8mjLcyjjx3BgffJcrI1vu0xZEGtz6zzUPuA", + "z/SP1O6R+PvSd+qa2p+i9kwg0qFOv+Kk0VakhlteIaF12dTHOfO2hthh8o+FJBRcQR9B8QoF8AGhhU8a", + "oknXwU/w+0l/DiJLU+2BY/GQ/zllHrz2EMIS5h2wPOD3ko5kC8BPx6VqjmY46qZrrl5L+Cgyh87iwPmB", + "pIvjDvyCp96KxHmOTNtzc+Pwf4qk9ky+Pnj7lrDLsH3AweN77wJ1ePk6ZlFrF9i+cY7ZAcWxFKizytzs", + "aflsoDqDhRxIFGlcRRpie60l3GpVWKT1A4jfDJUmWBiD/gRohBAQaPfHBqGqHYHhzoGktouUMtwVCdxo", + "Ho/LyG6Dp4dlO93G6rsjcfruXIzeXF7tr/L+yHmzdpB4pR57v34MMvvemB3sxLLneetwfs9Uzo2kUbpy", + "pdxdwj8FgeWeXqAc+4lICbBItVUoYCz5/Bp0ozajgSWtXbNQCGM5Dc2vt/cZiJKttq5Zsu0K/OkNX9Ae", + "84+DU+VpreS2i/pH/xniDP1yb5BafafX8LwktIqTHOMPh7m/2bSiFd4N2kp7wXKyo4ent5dVs4SFf45C", + "C6pt6fsEkcmzLPzjdOEaPhyivZA640Z6FP4OAAD//0nTejA+HAAA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/test/strict-server/iris/server.go b/internal/test/strict-server/iris/server.go index e93a1de5eb..9d1f652ecf 100644 --- a/internal/test/strict-server/iris/server.go +++ b/internal/test/strict-server/iris/server.go @@ -125,6 +125,14 @@ func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableRes return ReusableResponses200JSONResponse{ReusableresponseJSONResponse: ReusableresponseJSONResponse{Body: *request.Body}}, nil } +func (s StrictServer) RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) { + return RequiredJSONBody200JSONResponse(*request.Body), nil +} + +func (s StrictServer) RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) { + return RequiredTextBody200TextResponse(*request.Body), nil +} + func (s StrictServer) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) { return ReservedGoKeywordParameters200TextResponse(""), nil } diff --git a/internal/test/strict-server/iris/types.gen.go b/internal/test/strict-server/iris/types.gen.go index e0781f12f9..9b74c20754 100644 --- a/internal/test/strict-server/iris/types.gen.go +++ b/internal/test/strict-server/iris/types.gen.go @@ -14,6 +14,9 @@ type Reusableresponse = Example // MultipleRequestAndResponseTypesTextBody defines parameters for MultipleRequestAndResponseTypes. type MultipleRequestAndResponseTypesTextBody = string +// RequiredTextBodyTextBody defines parameters for RequiredTextBody. +type RequiredTextBodyTextBody = string + // TextExampleTextBody defines parameters for TextExample. type TextExampleTextBody = string @@ -44,6 +47,12 @@ type MultipleRequestAndResponseTypesMultipartRequestBody = Example // MultipleRequestAndResponseTypesTextRequestBody defines body for MultipleRequestAndResponseTypes for text/plain ContentType. type MultipleRequestAndResponseTypesTextRequestBody = MultipleRequestAndResponseTypesTextBody +// RequiredJSONBodyJSONRequestBody defines body for RequiredJSONBody for application/json ContentType. +type RequiredJSONBodyJSONRequestBody = Example + +// RequiredTextBodyTextRequestBody defines body for RequiredTextBody for text/plain ContentType. +type RequiredTextBodyTextRequestBody = RequiredTextBodyTextBody + // ReusableResponsesJSONRequestBody defines body for ReusableResponses for application/json ContentType. type ReusableResponsesJSONRequestBody = Example diff --git a/internal/test/strict-server/stdhttp/go.mod b/internal/test/strict-server/stdhttp/go.mod index 3cbb72265c..f918a51ee6 100644 --- a/internal/test/strict-server/stdhttp/go.mod +++ b/internal/test/strict-server/stdhttp/go.mod @@ -33,10 +33,10 @@ require ( github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/woodsbury/decimal128 v1.3.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/sync v0.9.0 // indirect - golang.org/x/text v0.20.0 // indirect - golang.org/x/tools v0.25.1 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/text v0.22.0 // indirect + golang.org/x/tools v0.30.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/internal/test/strict-server/stdhttp/go.sum b/internal/test/strict-server/stdhttp/go.sum index 7fe4b88d07..880c5ff529 100644 --- a/internal/test/strict-server/stdhttp/go.sum +++ b/internal/test/strict-server/stdhttp/go.sum @@ -36,6 +36,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -108,8 +110,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -117,13 +119,13 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -138,21 +140,21 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.25.1 h1:YeIyhd0M7gStYR9jb2IFXVVT+QJhgXu1ZECOuRwofh4= -golang.org/x/tools v0.25.1/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/test/strict-server/stdhttp/server.gen.go b/internal/test/strict-server/stdhttp/server.gen.go index 9dca95522e..d9936e7dfe 100644 --- a/internal/test/strict-server/stdhttp/server.gen.go +++ b/internal/test/strict-server/stdhttp/server.gen.go @@ -11,6 +11,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "mime" @@ -40,6 +41,12 @@ type ServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(w http.ResponseWriter, r *http.Request) + // (POST /required-json-body) + RequiredJSONBody(w http.ResponseWriter, r *http.Request) + + // (POST /required-text-body) + RequiredTextBody(w http.ResponseWriter, r *http.Request) + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request, pType string) @@ -130,6 +137,34 @@ func (siw *ServerInterfaceWrapper) MultipleRequestAndResponseTypes(w http.Respon handler.ServeHTTP(w, r) } +// RequiredJSONBody operation middleware +func (siw *ServerInterfaceWrapper) RequiredJSONBody(w http.ResponseWriter, r *http.Request) { + + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.RequiredJSONBody(w, r) + })) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r) +} + +// RequiredTextBody operation middleware +func (siw *ServerInterfaceWrapper) RequiredTextBody(w http.ResponseWriter, r *http.Request) { + + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.RequiredTextBody(w, r) + })) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r) +} + // ReservedGoKeywordParameters operation middleware func (siw *ServerInterfaceWrapper) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request) { @@ -426,6 +461,8 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H m.HandleFunc("POST "+options.BaseURL+"/multipart", wrapper.MultipartExample) m.HandleFunc("POST "+options.BaseURL+"/multipart-related", wrapper.MultipartRelatedExample) m.HandleFunc("POST "+options.BaseURL+"/multiple", wrapper.MultipleRequestAndResponseTypes) + m.HandleFunc("POST "+options.BaseURL+"/required-json-body", wrapper.RequiredJSONBody) + m.HandleFunc("POST "+options.BaseURL+"/required-text-body", wrapper.RequiredTextBody) m.HandleFunc("GET "+options.BaseURL+"/reserved-go-keyword-parameters/{type}", wrapper.ReservedGoKeywordParameters) m.HandleFunc("POST "+options.BaseURL+"/reusable-responses", wrapper.ReusableResponses) m.HandleFunc("POST "+options.BaseURL+"/text", wrapper.TextExample) @@ -636,6 +673,73 @@ func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestA return nil } +type RequiredJSONBodyRequestObject struct { + Body *RequiredJSONBodyJSONRequestBody +} + +type RequiredJSONBodyResponseObject interface { + VisitRequiredJSONBodyResponse(w http.ResponseWriter) error +} + +type RequiredJSONBody200JSONResponse Example + +func (response RequiredJSONBody200JSONResponse) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type RequiredJSONBody400Response = BadrequestResponse + +func (response RequiredJSONBody400Response) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(400) + return nil +} + +type RequiredJSONBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredJSONBodydefaultResponse) VisitRequiredJSONBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(response.StatusCode) + return nil +} + +type RequiredTextBodyRequestObject struct { + Body *RequiredTextBodyTextRequestBody +} + +type RequiredTextBodyResponseObject interface { + VisitRequiredTextBodyResponse(w http.ResponseWriter) error +} + +type RequiredTextBody200TextResponse string + +func (response RequiredTextBody200TextResponse) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(200) + + _, err := w.Write([]byte(response)) + return err +} + +type RequiredTextBody400Response = BadrequestResponse + +func (response RequiredTextBody400Response) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(400) + return nil +} + +type RequiredTextBodydefaultResponse struct { + StatusCode int +} + +func (response RequiredTextBodydefaultResponse) VisitRequiredTextBodyResponse(w http.ResponseWriter) error { + w.WriteHeader(response.StatusCode) + return nil +} + type ReservedGoKeywordParametersRequestObject struct { Type string `json:"type"` } @@ -983,6 +1087,12 @@ type StrictServerInterface interface { // (POST /multiple) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error) + // (POST /required-json-body) + RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) + + // (POST /required-text-body) + RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) + // (GET /reserved-go-keyword-parameters/{type}) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) @@ -1043,10 +1153,13 @@ func (sh *strictHandler) JSONExample(w http.ResponseWriter, r *http.Request) { var body JSONExampleJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.JSONExample(ctx, request.(JSONExampleRequestObject)) @@ -1141,10 +1254,13 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter, var body MultipleRequestAndResponseTypesJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.JSONBody = &body } - request.JSONBody = &body } if strings.HasPrefix(r.Header.Get("Content-Type"), "application/x-www-form-urlencoded") { if err := r.ParseForm(); err != nil { @@ -1175,8 +1291,10 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter, sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err)) return } - body := MultipleRequestAndResponseTypesTextRequestBody(data) - request.TextBody = &body + if len(data) > 0 { + body := MultipleRequestAndResponseTypesTextRequestBody(data) + request.TextBody = &body + } } handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { @@ -1199,6 +1317,69 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter, } } +// RequiredJSONBody operation middleware +func (sh *strictHandler) RequiredJSONBody(w http.ResponseWriter, r *http.Request) { + var request RequiredJSONBodyRequestObject + + var body RequiredJSONBodyJSONRequestBody + if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + request.Body = &body + + handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { + return sh.ssi.RequiredJSONBody(ctx, request.(RequiredJSONBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredJSONBody") + } + + response, err := handler(r.Context(), w, r, request) + + if err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } else if validResponse, ok := response.(RequiredJSONBodyResponseObject); ok { + if err := validResponse.VisitRequiredJSONBodyResponse(w); err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } + } else if response != nil { + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + } +} + +// RequiredTextBody operation middleware +func (sh *strictHandler) RequiredTextBody(w http.ResponseWriter, r *http.Request) { + var request RequiredTextBodyRequestObject + + data, err := io.ReadAll(r.Body) + if err != nil { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err)) + return + } + body := RequiredTextBodyTextRequestBody(data) + request.Body = &body + + handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { + return sh.ssi.RequiredTextBody(ctx, request.(RequiredTextBodyRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "RequiredTextBody") + } + + response, err := handler(r.Context(), w, r, request) + + if err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } else if validResponse, ok := response.(RequiredTextBodyResponseObject); ok { + if err := validResponse.VisitRequiredTextBodyResponse(w); err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } + } else if response != nil { + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + } +} + // ReservedGoKeywordParameters operation middleware func (sh *strictHandler) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request, pType string) { var request ReservedGoKeywordParametersRequestObject @@ -1231,10 +1412,13 @@ func (sh *strictHandler) ReusableResponses(w http.ResponseWriter, r *http.Reques var body ReusableResponsesJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.ReusableResponses(ctx, request.(ReusableResponsesRequestObject)) @@ -1265,8 +1449,10 @@ func (sh *strictHandler) TextExample(w http.ResponseWriter, r *http.Request) { sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err)) return } - body := TextExampleTextRequestBody(data) - request.Body = &body + if len(data) > 0 { + body := TextExampleTextRequestBody(data) + request.Body = &body + } handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.TextExample(ctx, request.(TextExampleRequestObject)) @@ -1385,10 +1571,13 @@ func (sh *strictHandler) HeadersExample(w http.ResponseWriter, r *http.Request, var body HeadersExampleJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.HeadersExample(ctx, request.(HeadersExampleRequestObject)) @@ -1416,10 +1605,13 @@ func (sh *strictHandler) UnionExample(w http.ResponseWriter, r *http.Request) { var body UnionExampleJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) - return + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + } else { + request.Body = &body } - request.Body = &body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { return sh.ssi.UnionExample(ctx, request.(UnionExampleRequestObject)) @@ -1444,24 +1636,25 @@ func (sh *strictHandler) UnionExample(w http.ResponseWriter, r *http.Request) { // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+xYS3PbNhD+Kxi0p5QUZccn3hpPJm3T1h3ZPnV8gIilhIQE0MVStEaj/94BQb0sWpUS", - "PTqZ3PhY7C6+b3ex2BnPTGmNBk2OpzOO4KzRDpqXoZAI/1TgyL9JcBkqS8ponvJ3Qg7af/OII1RODAtY", - "LPfymdEEulkqrC1UJvzS5JPz62fcZWMohX/6ESHnKf8hWbmShL8ugWdR2gL4fD6PXnhw95FHfAxCAjbe", - "hserTd00tcBT7giVHnGvJIhdd4opTTAC9Na8aOuEF1j4kc64RWMBSQWMJqKooNtS+8UMP0FGYQdK52Yb", - "y1ujSSjtmFR5DgiaWAse8zocc5W1BgkkG06Zt5ARc4ATQB5xUuQd4/fr31nrsOMRnwC6YOiq1+/1PV/G", - "ghZW8ZS/bT5F3AoaNxtaEmRNF++/3d/9yZRjoiJTClKZKIopKwW6sShAMqXJeBerjFyPN5awIf5X2a5+", - "30Lpo6YJoHdGTk8RME1croXzdb9/pricR/wmGOvSsXQqWUuwRk0uqqID80f9WZtaM0A02O4sKauClBVI", - "61xtov3HQmQfyJf6ktxgGUtB4kSoH8vSpYGPEQpBIPcgYBAkD+NhTf1JWfgaOxfloK3HnXXqfmxqx8am", - "ZmSYBFGwWtGYLRa+KLBKM8Gc0qMC2MKpqJPMAtpj72ctB+1eHryOk9ezaEPLc1zXddwkUIUF6MzIL6Mw", - "4qoUI0isHm0u97oF8ZQPp+RDdvuAO1IiR5zgmRJbCKV3n95nKunfkT5aYod0RWi6EhmPTPwZprVBGVuB", - "ogQCdMnMW597xSPoSOW/lpIsE5oNgWlRgmQiJ0D2wbBWpdtK2UFr94P5GERWqpqWZ/mS/j3jHpKmDeIR", - "9wZ4GlAJea3Qk05YQbQDtqf/jM+vImCBZmi24w1T3WVwUaKW0CHkzpfELuY68AuWBmsSl2nadkfc1vXj", - "HGeQZ/L1o/8Bnvdqu45Y+s6d24cCVoWPr2PWrtoHti+spHugOFESTFLamwM1XwxUZyFTuQIZt7uIg2+v", - "lYRbozME2myB/JVOG2JLZf6mSWNgAYGIOcNqYGXliFnhHFPUVJFChduqhK3i8bjy7DZYeliV012svjkR", - "p28uxehN/+rwJW9PHDcbrcwr+Tj4/X2QOfTOfrSe6cCO73h2L5TO/pISrw21ulP4lyCwOtMzUBPfEWnJ", - "EKhCDZJNlFgMYrZys1WworWrFwpurLqhxYDtkIYo2qnrmke7hnBP3/CI6JSjy3PFaaXVrlHho//N2h76", - "5dmgjP6fDgJFQYBakJrAT8e5QW5rMRru8ibTXrAc7Wnh6duLqnnEw+w6lKAKC18niGyaJGHm3XO1GI0A", - "e8okwiqPwr8BAAD//4h9qqfAGAAA", + "H4sIAAAAAAAC/+xZTXPbNhP+Kzt431NKmrbjE2+NJ5O2aeuObJ86PkDESkJCAiiwFK3R6L93QEBfFq1K", + "qT4ynt5Ecr/wPLuLBTRlha6MVqjIsXzKLDqjlcP2oc+Fxb9qdOSfBLrCSkNSK5azD1z04rdZwizWjvdL", + "nKt7+UIrQtWqcmNKWXCvmn1xXn/KXDHCivtf/7c4YDn7X7YMJQtfXYbPvDIlstlslryI4O4zS9gIuUDb", + "Rht+Xq3bpolBljNHVqoh80aC2HWnmFSEQ7TemxeNQXiBeRz5lBmrDVqSAaMxL2vs9hTf6P4XLCisQKqB", + "3sTyViviUjkQcjBAi4ogggfehgNXG6MtoYD+BLyHgsChHaNlCSNJPjB2v/oeYsCOJWyM1gVHVxeXF5ee", + "L21QcSNZzt63rxJmOI3aBS0IMrqL91/u734H6YDXpCtOsuBlOYGKWzfiJQqQirQPsS7IXbDWk22J/1lE", + "7Y8RSp81bQJ90GJyjIRp83Ilna8vL0+Ul7OE3QRnXTYWQWUrBdaaGfC67MD8UX1VulGA1mobV5ZVdUnS", + "cEurXK2j/dtcZBfIF/aygbZVKjjxI6F+KE/nBj61WHJCsQMBvSC5Hw8r5o/Kwr/xc1YOYj/u7FP3I904", + "GOkGSINAXkIjaQRzxRcNVirg4KQalgjzoJJOMkuM296PSvTiWh68jaP3s2TNynPaNE3aFlBtS1SFFt9G", + "YcJkxYeYGTVcV/e2ObGc9SfkU3ZzgztQISeM8JkyU3Kptu/eJ2rp/yF9sMIO5eofpUWRekbSfqyP7sKN", + "5QVeyg8ac90EnIZKOl+l4aMb6boUwMuGT1zoD5sTRy+q+8mjLcyjjx3BgffJcrI1vu0xZEGtz6zzUPuA", + "z/SP1O6R+PvSd+qa2p+i9kwg0qFOv+Kk0VakhlteIaF12dTHOfO2hthh8o+FJBRcQR9B8QoF8AGhhU8a", + "oknXwU/w+0l/DiJLU+2BY/GQ/zllHrz2EMIS5h2wPOD3ko5kC8BPx6VqjmY46qZrrl5L+Cgyh87iwPmB", + "pIvjDvyCp96KxHmOTNtzc+Pwf4qk9ky+Pnj7lrDLsH3AweN77wJ1ePk6ZlFrF9i+cY7ZAcWxFKizytzs", + "aflsoDqDhRxIFGlcRRpie60l3GpVWKT1A4jfDJUmWBiD/gRohBAQaPfHBqGqHYHhzoGktouUMtwVCdxo", + "Ho/LyG6Dp4dlO93G6rsjcfruXIzeXF7tr/L+yHmzdpB4pR57v34MMvvemB3sxLLneetwfs9Uzo2kUbpy", + "pdxdwj8FgeWeXqAc+4lICbBItVUoYCz5/Bp0ozajgSWtXbNQCGM5Dc2vt/cZiJKttq5Zsu0K/OkNX9Ae", + "84+DU+VpreS2i/pH/xniDP1yb5BafafX8LwktIqTHOMPh7m/2bSiFd4N2kp7wXKyo4ent5dVs4SFf45C", + "C6pt6fsEkcmzLPzjdOEaPhyivZA640Z6FP4OAAD//0nTejA+HAAA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/test/strict-server/stdhttp/server.go b/internal/test/strict-server/stdhttp/server.go index 2ac46dc2da..95393d3350 100644 --- a/internal/test/strict-server/stdhttp/server.go +++ b/internal/test/strict-server/stdhttp/server.go @@ -128,6 +128,14 @@ func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableRes return ReusableResponses200JSONResponse{ReusableresponseJSONResponse: ReusableresponseJSONResponse{Body: *request.Body}}, nil } +func (s StrictServer) RequiredJSONBody(ctx context.Context, request RequiredJSONBodyRequestObject) (RequiredJSONBodyResponseObject, error) { + return RequiredJSONBody200JSONResponse(*request.Body), nil +} + +func (s StrictServer) RequiredTextBody(ctx context.Context, request RequiredTextBodyRequestObject) (RequiredTextBodyResponseObject, error) { + return RequiredTextBody200TextResponse(*request.Body), nil +} + func (s StrictServer) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) { return ReservedGoKeywordParameters200TextResponse(""), nil } diff --git a/internal/test/strict-server/stdhttp/types.gen.go b/internal/test/strict-server/stdhttp/types.gen.go index e0781f12f9..9b74c20754 100644 --- a/internal/test/strict-server/stdhttp/types.gen.go +++ b/internal/test/strict-server/stdhttp/types.gen.go @@ -14,6 +14,9 @@ type Reusableresponse = Example // MultipleRequestAndResponseTypesTextBody defines parameters for MultipleRequestAndResponseTypes. type MultipleRequestAndResponseTypesTextBody = string +// RequiredTextBodyTextBody defines parameters for RequiredTextBody. +type RequiredTextBodyTextBody = string + // TextExampleTextBody defines parameters for TextExample. type TextExampleTextBody = string @@ -44,6 +47,12 @@ type MultipleRequestAndResponseTypesMultipartRequestBody = Example // MultipleRequestAndResponseTypesTextRequestBody defines body for MultipleRequestAndResponseTypes for text/plain ContentType. type MultipleRequestAndResponseTypesTextRequestBody = MultipleRequestAndResponseTypesTextBody +// RequiredJSONBodyJSONRequestBody defines body for RequiredJSONBody for application/json ContentType. +type RequiredJSONBodyJSONRequestBody = Example + +// RequiredTextBodyTextRequestBody defines body for RequiredTextBody for text/plain ContentType. +type RequiredTextBodyTextRequestBody = RequiredTextBodyTextBody + // ReusableResponsesJSONRequestBody defines body for ReusableResponses for application/json ContentType. type ReusableResponsesJSONRequestBody = Example diff --git a/internal/test/strict-server/strict-schema.yaml b/internal/test/strict-server/strict-schema.yaml index a0b6a6e054..8b18edd541 100644 --- a/internal/test/strict-server/strict-schema.yaml +++ b/internal/test/strict-server/strict-schema.yaml @@ -247,6 +247,48 @@ paths: $ref: "#/components/responses/badrequest" default: description: Unknown error + /required-json-body: + post: + operationId: RequiredJSONBody + description: Request body is required, so missing body should always error. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/example" + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/example" + 400: + $ref: "#/components/responses/badrequest" + default: + description: Unknown error + /required-text-body: + post: + operationId: RequiredTextBody + description: Request body is required, so missing body should always error. + requestBody: + required: true + content: + text/plain: + schema: + type: string + responses: + 200: + description: OK + content: + text/plain: + schema: + type: string + 400: + $ref: "#/components/responses/badrequest" + default: + description: Unknown error /reserved-go-keyword-parameters/{type}: get: operationId: ReservedGoKeywordParameters diff --git a/internal/test/strict-server/strict_test.go b/internal/test/strict-server/strict_test.go index 7869245599..35ccb13059 100644 --- a/internal/test/strict-server/strict_test.go +++ b/internal/test/strict-server/strict_test.go @@ -13,8 +13,6 @@ import ( "github.com/gin-gonic/gin" "github.com/go-chi/chi/v5" - "github.com/gofiber/fiber/v2" - "github.com/gofiber/fiber/v2/middleware/adaptor" "github.com/kataras/iris/v12" "github.com/labstack/echo/v4" "github.com/stretchr/testify/assert" @@ -22,7 +20,6 @@ import ( chiAPI "github.com/livesession/oapi-codegen/v2/internal/test/strict-server/chi" clientAPI "github.com/livesession/oapi-codegen/v2/internal/test/strict-server/client" echoAPI "github.com/livesession/oapi-codegen/v2/internal/test/strict-server/echo" - fiberAPI "github.com/livesession/oapi-codegen/v2/internal/test/strict-server/fiber" ginAPI "github.com/livesession/oapi-codegen/v2/internal/test/strict-server/gin" irisAPI "github.com/livesession/oapi-codegen/v2/internal/test/strict-server/iris" @@ -63,14 +60,6 @@ func TestGinServer(t *testing.T) { testImpl(t, r) } -func TestFiberServer(t *testing.T) { - server := fiberAPI.StrictServer{} - strictHandler := fiberAPI.NewStrictHandler(server, nil) - r := fiber.New() - fiberAPI.RegisterHandlers(r, strictHandler) - testImpl(t, adaptor.FiberApp(r)) -} - func testImpl(t *testing.T, handler http.Handler) { t.Run("JSONExample", func(t *testing.T) { value := "123" diff --git a/pkg/codegen/codegen.go b/pkg/codegen/codegen.go index 17219b0b77..668211c718 100644 --- a/pkg/codegen/codegen.go +++ b/pkg/codegen/codegen.go @@ -52,6 +52,8 @@ var globalState struct { // initialismsMap stores initialisms as "lower(initialism) -> initialism" map. // List of initialisms was taken from https://staticcheck.io/docs/configuration/options/#initialisms. initialismsMap map[string]string + // typeMapping is the merged type mapping (defaults + user overrides). + typeMapping TypeMapping } // goImport represents a go package to be imported in the generated code @@ -90,8 +92,8 @@ func (im importMap) GoImports() []string { func constructImportMapping(importMapping map[string]string) importMap { var ( - pathToName = map[string]string{} - result = importMap{} + pathToImport = importMap{} + result = importMap{} ) { @@ -102,13 +104,32 @@ func constructImportMapping(importMapping map[string]string) importMap { sort.Strings(packagePaths) for _, packagePath := range packagePaths { - if _, ok := pathToName[packagePath]; !ok && packagePath != importMappingCurrentPackage { - pathToName[packagePath] = fmt.Sprintf("externalRef%d", len(pathToName)) + if _, ok := pathToImport[packagePath]; !ok && packagePath != importMappingCurrentPackage { + split := strings.Split(packagePath, " ") + if len(split) == 2 { + // if we have 2 parts, we assume both the package name and path are provided, and we use them as is + pathToImport[packagePath] = goImport{ + Name: split[0], + Path: split[1], + } + } else { + // otherwise, we auto-generate a package name based on the order of the imports, to ensure deterministic output + pathToImport[packagePath] = goImport{ + Name: fmt.Sprintf("externalRef%d", len(pathToImport)), + Path: packagePath, + } + } } } } for specPath, packagePath := range importMapping { - result[specPath] = goImport{Name: pathToName[packagePath], Path: packagePath} + if packagePath == importMappingCurrentPackage { + result[specPath] = goImport{ + Path: importMappingCurrentPackage, + } + } else { + result[specPath] = pathToImport[packagePath] + } } return result } @@ -121,6 +142,11 @@ func Generate(spec *openapi3.T, opts Configuration) (string, error) { globalState.options = opts globalState.spec = spec globalState.importMapping = constructImportMapping(opts.ImportMapping) + if opts.OutputOptions.TypeMapping != nil { + globalState.typeMapping = DefaultTypeMapping.Merge(*opts.OutputOptions.TypeMapping) + } else { + globalState.typeMapping = DefaultTypeMapping + } filterOperationsByTag(spec, opts) filterOperationsByOperationID(spec, opts) @@ -673,6 +699,8 @@ func GenerateTypesForResponses(t *template.Template, responses openapi3.Response return nil, fmt.Errorf("error making name for components/responses/%s: %w", responseName, err) } + goType.DefinedComp = ComponentTypeResponse + typeDef := TypeDefinition{ JsonName: responseName, Schema: goType, @@ -693,6 +721,7 @@ func GenerateTypesForResponses(t *template.Template, responses openapi3.Response } types = append(types, typeDef) + types = append(types, goType.AdditionalTypes...) } } return types, nil @@ -724,6 +753,8 @@ func GenerateTypesForRequestBodies(t *template.Template, bodies map[string]*open return nil, fmt.Errorf("error making name for components/schemas/%s: %w", requestBodyName, err) } + goType.DefinedComp = ComponentTypeRequestBody + typeDef := TypeDefinition{ JsonName: requestBodyName, Schema: goType, @@ -739,6 +770,7 @@ func GenerateTypesForRequestBodies(t *template.Template, bodies map[string]*open typeDef.TypeName = SchemaNameToTypeName(refType) } types = append(types, typeDef) + types = append(types, goType.AdditionalTypes...) } } return types, nil @@ -750,15 +782,18 @@ func GenerateTypes(t *template.Template, types []TypeDefinition) (string, error) m := map[string]TypeDefinition{} var ts []TypeDefinition + if globalState.options.OutputOptions.ResolveTypeNameCollisions { + types = FixDuplicateTypeNames(types) + } + for _, typ := range types { if prevType, found := m[typ.TypeName]; found { - // If type names collide, we need to see if they refer to the same - // exact type definition, in which case, we can de-dupe. If they don't - // match, we error out. + // If type names collide after auto-rename, we need to see if they + // refer to the same exact type definition, in which case, we can + // de-dupe. If they don't match, we error out. if TypeDefinitionsEquivalent(prevType, typ) { continue } - // We want to create an error when we try to define the same type twice. return "", fmt.Errorf("duplicate typename '%s' detected, can't auto-rename, "+ "please use x-go-name to specify your own name for one of them", typ.TypeName) } diff --git a/pkg/codegen/codegen_test.go b/pkg/codegen/codegen_test.go index 41b8d0c4fa..2f71630cc8 100644 --- a/pkg/codegen/codegen_test.go +++ b/pkg/codegen/codegen_test.go @@ -77,7 +77,14 @@ type GetTestByNameResponse struct { assert.Contains(t, code, "Top *int `form:\"$top,omitempty\" json:\"$top,omitempty\"`") assert.Contains(t, code, "func (c *Client) GetTestByName(ctx context.Context, name string, params *GetTestByNameParams, reqEditors ...RequestEditorFn) (*http.Response, error) {") assert.Contains(t, code, "func (c *ClientWithResponses) GetTestByNameWithResponse(ctx context.Context, name string, params *GetTestByNameParams, reqEditors ...RequestEditorFn) (*GetTestByNameResponse, error) {") - assert.Contains(t, code, "DeadSince *time.Time `json:\"dead_since,omitempty\" tag1:\"value1\" tag2:\"value2\"`") + assert.Contains(t, code, "FavouriteBirds *[]*string `json:\"favourite_birds,omitempty\"`") + assert.Contains(t, code, "DetestedBirds *[]string `json:\"detested_birds,omitempty\"`") + assert.Contains(t, code, "SlicedBirds []string `json:\"sliced_birds\"`") + assert.Contains(t, code, "ForgettableBirds *map[string]*string `json:\"forgettable_birds,omitempty\"`") + assert.Contains(t, code, "MemorableBirds *map[string]string `json:\"memorable_birds,omitempty\"`") + assert.Contains(t, code, "VeryMemorableBirds map[string]string `json:\"very_memorable_birds\"`") + assert.Contains(t, code, "DeadSince *time.Time `json:\"dead_since,omitempty\" tag1:\"value1\" tag2:\"value2\"`") + assert.Contains(t, code, "VeryDeadSince time.Time `json:\"very_dead_since\"`") assert.Contains(t, code, "type EnumTestNumerics int") assert.Contains(t, code, "N2 EnumTestNumerics = 2") assert.Contains(t, code, "type EnumTestEnumNames int") @@ -110,8 +117,8 @@ func TestExtPropGoTypeSkipOptionalPointer(t *testing.T) { assert.NoError(t, err) // Check that optional pointer fields are skipped if requested - assert.Contains(t, code, "NullableFieldSkipFalse *string `json:\"nullableFieldSkipFalse\"`") - assert.Contains(t, code, "NullableFieldSkipTrue string `json:\"nullableFieldSkipTrue\"`") + assert.Contains(t, code, "NullableFieldSkipFalse *string `json:\"nullableFieldSkipFalse,omitempty\"`") + assert.Contains(t, code, "NullableFieldSkipTrue string `json:\"nullableFieldSkipTrue,omitempty\"`") assert.Contains(t, code, "OptionalField *string `json:\"optionalField,omitempty\"`") assert.Contains(t, code, "OptionalFieldSkipFalse *string `json:\"optionalFieldSkipFalse,omitempty\"`") assert.Contains(t, code, "OptionalFieldSkipTrue string `json:\"optionalFieldSkipTrue,omitempty\"`") @@ -227,5 +234,65 @@ func (t *ExampleSchema_Item) FromExternalRef0NewPet(v externalRef0.NewPet) error `) } +func TestDuplicatePathParameter(t *testing.T) { + // Regression test for https://github.com/oapi-codegen/oapi-codegen/issues/1574 + // Some real-world specs (e.g. Keycloak) have paths where the same parameter + // appears more than once: /clients/{client-uuid}/.../clients/{client-uuid} + spec := ` +openapi: "3.0.0" +info: + version: 1.0.0 + title: Duplicate path param test +paths: + /admin/realms/{realm}/clients/{client-uuid}/roles/{role-name}/composites/clients/{client-uuid}: + get: + operationId: getCompositeRoles + parameters: + - name: realm + in: path + required: true + schema: + type: string + - name: client-uuid + in: path + required: true + schema: + type: string + - name: role-name + in: path + required: true + schema: + type: string + responses: + '200': + description: Success +` + loader := openapi3.NewLoader() + swagger, err := loader.LoadFromData([]byte(spec)) + require.NoError(t, err) + + opts := Configuration{ + PackageName: "api", + Generate: GenerateOptions{ + EchoServer: true, + Client: true, + Models: true, + }, + } + + code, err := Generate(swagger, opts) + require.NoError(t, err) + assert.NotEmpty(t, code) + + // Verify the generated code is valid Go. + _, err = format.Source([]byte(code)) + require.NoError(t, err) + + // The path params should appear exactly once in the function signature. + assert.Contains(t, code, "realm string") + assert.Contains(t, code, "clientUuid string") + assert.Contains(t, code, "roleName string") +} + //go:embed test_spec.yaml var testOpenAPIDefinition string diff --git a/pkg/codegen/configuration.go b/pkg/codegen/configuration.go index 58d56119be..129f11d786 100644 --- a/pkg/codegen/configuration.go +++ b/pkg/codegen/configuration.go @@ -302,6 +302,18 @@ type OutputOptions struct { // PreferSkipOptionalPointerOnContainerTypes allows disabling the generation of an "optional pointer" for an optional field that is a container type (such as a slice or a map), which ends up requiring an additional, unnecessary, `... != nil` check PreferSkipOptionalPointerOnContainerTypes bool `yaml:"prefer-skip-optional-pointer-on-container-types,omitempty"` + + // ResolveTypeNameCollisions, when set to true, automatically renames + // types that collide across different OpenAPI component sections + // (schemas, parameters, requestBodies, responses, headers) by appending + // a suffix based on the component section (e.g., "Parameter", "Response", + // "RequestBody"). Without this, the codegen will error on duplicate type + // names, requiring manual resolution via x-go-name. + ResolveTypeNameCollisions bool `yaml:"resolve-type-name-collisions,omitempty"` + + // TypeMapping allows customizing OpenAPI type/format to Go type mappings. + // User-specified mappings are merged on top of the defaults. + TypeMapping *TypeMapping `yaml:"type-mapping,omitempty"` } func (oo OutputOptions) Validate() map[string]string { diff --git a/pkg/codegen/extension.go b/pkg/codegen/extension.go index 91b3282379..60748fc7ab 100644 --- a/pkg/codegen/extension.go +++ b/pkg/codegen/extension.go @@ -30,7 +30,7 @@ const ( extOapiCodegenOnlyHonourGoName = "x-oapi-codegen-only-honour-go-name" ) -func extString(extPropValue interface{}) (string, error) { +func extString(extPropValue any) (string, error) { str, ok := extPropValue.(string) if !ok { return "", fmt.Errorf("failed to convert type: %T", extPropValue) @@ -38,11 +38,11 @@ func extString(extPropValue interface{}) (string, error) { return str, nil } -func extTypeName(extPropValue interface{}) (string, error) { +func extTypeName(extPropValue any) (string, error) { return extString(extPropValue) } -func extParsePropGoTypeSkipOptionalPointer(extPropValue interface{}) (bool, error) { +func extParsePropGoTypeSkipOptionalPointer(extPropValue any) (bool, error) { goTypeSkipOptionalPointer, ok := extPropValue.(bool) if !ok { return false, fmt.Errorf("failed to convert type: %T", extPropValue) @@ -50,11 +50,11 @@ func extParsePropGoTypeSkipOptionalPointer(extPropValue interface{}) (bool, erro return goTypeSkipOptionalPointer, nil } -func extParseGoFieldName(extPropValue interface{}) (string, error) { +func extParseGoFieldName(extPropValue any) (string, error) { return extString(extPropValue) } -func extParseOmitEmpty(extPropValue interface{}) (bool, error) { +func extParseOmitEmpty(extPropValue any) (bool, error) { omitEmpty, ok := extPropValue.(bool) if !ok { return false, fmt.Errorf("failed to convert type: %T", extPropValue) @@ -62,7 +62,7 @@ func extParseOmitEmpty(extPropValue interface{}) (bool, error) { return omitEmpty, nil } -func extParseOmitZero(extPropValue interface{}) (bool, error) { +func extParseOmitZero(extPropValue any) (bool, error) { omitZero, ok := extPropValue.(bool) if !ok { return false, fmt.Errorf("failed to convert type: %T", extPropValue) @@ -70,8 +70,8 @@ func extParseOmitZero(extPropValue interface{}) (bool, error) { return omitZero, nil } -func extExtraTags(extPropValue interface{}) (map[string]string, error) { - tagsI, ok := extPropValue.(map[string]interface{}) +func extExtraTags(extPropValue any) (map[string]string, error) { + tagsI, ok := extPropValue.(map[string]any) if !ok { return nil, fmt.Errorf("failed to convert type: %T", extPropValue) } @@ -86,7 +86,7 @@ func extExtraTags(extPropValue interface{}) (map[string]string, error) { return tags, nil } -func extParseGoJsonIgnore(extPropValue interface{}) (bool, error) { +func extParseGoJsonIgnore(extPropValue any) (bool, error) { goJsonIgnore, ok := extPropValue.(bool) if !ok { return false, fmt.Errorf("failed to convert type: %T", extPropValue) @@ -94,8 +94,8 @@ func extParseGoJsonIgnore(extPropValue interface{}) (bool, error) { return goJsonIgnore, nil } -func extParseEnumVarNames(extPropValue interface{}) ([]string, error) { - namesI, ok := extPropValue.([]interface{}) +func extParseEnumVarNames(extPropValue any) ([]string, error) { + namesI, ok := extPropValue.([]any) if !ok { return nil, fmt.Errorf("failed to convert type: %T", extPropValue) } @@ -110,11 +110,11 @@ func extParseEnumVarNames(extPropValue interface{}) ([]string, error) { return names, nil } -func extParseDeprecationReason(extPropValue interface{}) (string, error) { +func extParseDeprecationReason(extPropValue any) (string, error) { return extString(extPropValue) } -func extParseOapiCodegenOnlyHonourGoName(extPropValue interface{}) (bool, error) { +func extParseOapiCodegenOnlyHonourGoName(extPropValue any) (bool, error) { onlyHonourGoName, ok := extPropValue.(bool) if !ok { return false, fmt.Errorf("failed to convert type: %T", extPropValue) diff --git a/pkg/codegen/extension_test.go b/pkg/codegen/extension_test.go index 7a5f363bd7..0223ee9404 100644 --- a/pkg/codegen/extension_test.go +++ b/pkg/codegen/extension_test.go @@ -39,7 +39,7 @@ func Test_extTypeName(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // kin-openapi no longer returns these as RawMessage - var extPropValue interface{} + var extPropValue any if tt.args.extPropValue != nil { err := json.Unmarshal(tt.args.extPropValue, &extPropValue) assert.NoError(t, err) @@ -93,7 +93,7 @@ func Test_extParsePropGoTypeSkipOptionalPointer(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // kin-openapi no longer returns these as RawMessage - var extPropValue interface{} + var extPropValue any if tt.args.extPropValue != nil { err := json.Unmarshal(tt.args.extPropValue, &extPropValue) assert.NoError(t, err) diff --git a/pkg/codegen/merge_schemas.go b/pkg/codegen/merge_schemas.go index bb333764f6..998b2c49b1 100644 --- a/pkg/codegen/merge_schemas.go +++ b/pkg/codegen/merge_schemas.go @@ -13,9 +13,20 @@ import ( func MergeSchemas(schema *openapi3.Schema, path []string) (Schema, error) { allOf := schema.AllOf + // If the parent schema has its own properties alongside allOf, + // include them as a synthetic schema in the allOf list so they + // are not lost during merging. + if len(schema.Properties) > 0 { + parentOnly := *schema + parentOnly.AllOf = nil + allOf = append(allOf, openapi3.NewSchemaRef("", &parentOnly)) + } + // If someone asked for the old way, for backward compatibility, return the // old style result. - if globalState.options.Compatibility.OldMergeSchemas || schema.Extensions[extGoEmbedding] == true { + // Also use v1 merging when the parent has its own properties, because v1 + // generates struct embedding for $ref types which preserves the type hierarchy. + if globalState.options.Compatibility.OldMergeSchemas || schema.Extensions[extGoEmbedding] == true || len(schema.Properties) > 0 { return mergeSchemasV1(allOf, path) } return mergeSchemas(allOf, path) @@ -89,7 +100,7 @@ func mergeAllOf(allOf []*openapi3.SchemaRef) (openapi3.Schema, error) { func mergeOpenapiSchemas(s1, s2 openapi3.Schema, allOf bool) (openapi3.Schema, error) { var result openapi3.Schema - result.Extensions = make(map[string]interface{}) + result.Extensions = make(map[string]any) for k, v := range s1.Extensions { result.Extensions[k] = v } diff --git a/pkg/codegen/operations.go b/pkg/codegen/operations.go index bbb07a822d..23dd0637ef 100644 --- a/pkg/codegen/operations.go +++ b/pkg/codegen/operations.go @@ -44,6 +44,23 @@ func (pd ParameterDefinition) TypeDef() string { return typeDecl } +// RequiresNilCheck indicates whether the generated property should have a nil check performed on it before other checks. +// This should be used in templates when performing `nil` checks, but NOT when i.e. determining if there should be an optional pointer given to the type - in that case, use `HasOptionalPointer` +func (pd ParameterDefinition) RequiresNilCheck() bool { + return pd.ZeroValueIsNil() || pd.HasOptionalPointer() +} + +// ZeroValueIsNil is a helper function to determine if the given Go type used for this property +// Will return true if the OpenAPI `type` is: +// - `array` +func (pd ParameterDefinition) ZeroValueIsNil() bool { + if pd.Schema.OAPISchema == nil { + return false + } + + return pd.Schema.OAPISchema.Type.Is("array") +} + // JsonTag generates the JSON annotation to map GoType to json type name. If Parameter // Foo is marshaled to json as "foo", this will create the annotation // 'json:"foo"' @@ -925,13 +942,24 @@ func GenerateParamsTypes(op OperationDefinition) []TypeDefinition { Schema: param.Schema, }) } + // Merge extensions from the schema level and the parameter level. + // Parameter-level extensions take precedence over schema-level ones. + extensions := make(map[string]any) + if param.Spec.Schema != nil && param.Spec.Schema.Value != nil { + for k, v := range param.Spec.Schema.Value.Extensions { + extensions[k] = v + } + } + for k, v := range param.Spec.Extensions { + extensions[k] = v + } prop := Property{ Description: param.Spec.Description, JsonFieldName: param.ParamName, Required: param.Required, Schema: pSchema, NeedsFormTag: param.Style() == "form", - Extensions: param.Spec.Extensions, + Extensions: extensions, } s.Properties = append(s.Properties, prop) } @@ -1067,7 +1095,7 @@ func GenerateClientWithResponses(t *template.Template, ops []OperationDefinition } // GenerateTemplates used to generate templates -func GenerateTemplates(templates []string, t *template.Template, ops interface{}) (string, error) { +func GenerateTemplates(templates []string, t *template.Template, ops any) (string, error) { var generatedTemplates []string for _, tmpl := range templates { var buf bytes.Buffer diff --git a/pkg/codegen/prune.go b/pkg/codegen/prune.go index 0d3a889747..e97ba3469e 100644 --- a/pkg/codegen/prune.go +++ b/pkg/codegen/prune.go @@ -2,23 +2,19 @@ package codegen import ( "fmt" + "slices" "github.com/getkin/kin-openapi/openapi3" ) func stringInSlice(a string, list []string) bool { - for _, b := range list { - if b == a { - return true - } - } - return false + return slices.Contains(list, a) } type RefWrapper struct { Ref string HasValue bool - SourceRef interface{} + SourceRef any } func walkSwagger(swagger *openapi3.T, doFn func(RefWrapper) (bool, error)) error { diff --git a/pkg/codegen/schema.go b/pkg/codegen/schema.go index 76c0582850..48fce89369 100644 --- a/pkg/codegen/schema.go +++ b/pkg/codegen/schema.go @@ -39,8 +39,22 @@ type Schema struct { // The original OpenAPIv3 Schema. OAPISchema *openapi3.Schema + + DefinedComp ComponentType // Indicates which component section defined this type } +// ComponentType is used to keep track of where a given schema came from, in order +// to perform type name collision resolution. +type ComponentType int + +const ( + ComponentTypeSchema = iota + ComponentTypeParameter + ComponentTypeRequestBody + ComponentTypeResponse + ComponentTypeHeader +) + func (s Schema) IsRef() bool { return s.RefType != "" } @@ -88,7 +102,7 @@ type Property struct { ReadOnly bool WriteOnly bool NeedsFormTag bool - Extensions map[string]interface{} + Extensions map[string]any Deprecated bool } @@ -256,11 +270,11 @@ func (u UnionElement) String() string { // Method generate union method name for template functions `As/From/Merge`. func (u UnionElement) Method() string { - var method string + var method strings.Builder for _, part := range strings.Split(string(u), `.`) { - method += UppercaseFirstCharacter(part) + method.WriteString(UppercaseFirstCharacter(part)) } - return method + return method.String() } func PropertiesEqual(a, b Property) bool { @@ -311,6 +325,7 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { Description: schema.Description, OAPISchema: schema, SkipOptionalPointer: skipOptionalPointer, + DefinedComp: ComponentTypeSchema, } // Check x-go-type, which will completely override the definition of this @@ -337,19 +352,6 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { return outSchema, nil } } - - // AllOf is interesting, and useful. It's the union of a number of other - // schemas. A common usage is to create a union of an object with an ID, - // so that in a RESTful paradigm, the Create operation can return - // (object, id), so that other operations can refer to (id) - if schema.AllOf != nil { - mergedSchema, err := MergeSchemas(schema, path) - if err != nil { - return Schema{}, fmt.Errorf("error merging schemas: %w", err) - } - mergedSchema.OAPISchema = schema - return mergedSchema, nil - } // AllOf is interesting, and useful. It's the union of a number of other // schemas. A common usage is to create a union of an object with an ID, @@ -612,6 +614,7 @@ func oapiSchemaToGoType(schema *openapi3.Schema, path []string, outSchema *Schem if err != nil { return fmt.Errorf("error generating type for array: %w", err) } + if (arrayType.HasAdditionalProperties || len(arrayType.UnionElements) != 0) && arrayType.RefType == "" { // If we have items which have additional properties or union values, // but are not a pre-defined type, we need to define a type @@ -628,10 +631,18 @@ func oapiSchemaToGoType(schema *openapi3.Schema, path []string, outSchema *Schem arrayType.RefType = typeName } - arrayType.AdditionalPropertiesType = &arrayType - arrayType.AdditionalPropertiesType.OAPISchema = schema + + typeDeclaration := arrayType.TypeDecl() + if arrayType.OAPISchema != nil && arrayType.OAPISchema.Nullable { + if globalState.options.OutputOptions.NullableType { + typeDeclaration = "nullable.Nullable[" + typeDeclaration + "]" + } else { + typeDeclaration = "*" + typeDeclaration + } + } + outSchema.ArrayType = &arrayType - outSchema.GoType = "[]" + additionalPropertiesType(arrayType) + outSchema.GoType = "[]" + typeDeclaration outSchema.AdditionalTypes = arrayType.AdditionalTypes outSchema.Properties = arrayType.Properties outSchema.DefineViaAlias = true @@ -641,62 +652,26 @@ func oapiSchemaToGoType(schema *openapi3.Schema, path []string, outSchema *Schem setSkipOptionalPointerForContainerType(outSchema) } else if t.Is("integer") { - // We default to int if format doesn't ask for something else. - switch f { - case "int64", - "int32", - "int16", - "int8", - "int", - "uint64", - "uint32", - "uint16", - "uint8", - "uint": - outSchema.GoType = f - default: - outSchema.GoType = "int" - } + spec := globalState.typeMapping.Integer.Resolve(f) + outSchema.GoType = spec.Type outSchema.DefineViaAlias = true } else if t.Is("number") { - // We default to float for "number" - switch f { - case "double": - outSchema.GoType = "float64" - case "float", "": - outSchema.GoType = "float32" - default: - return fmt.Errorf("invalid number format: %s", f) - } + spec := globalState.typeMapping.Number.Resolve(f) + outSchema.GoType = spec.Type outSchema.DefineViaAlias = true } else if t.Is("boolean") { - if f != "" { - return fmt.Errorf("invalid format (%s) for boolean", f) - } - outSchema.GoType = "bool" + spec := globalState.typeMapping.Boolean.Resolve(f) + outSchema.GoType = spec.Type outSchema.DefineViaAlias = true } else if t.Is("string") { - // Special case string formats here. - switch f { - case "byte": - outSchema.GoType = "[]byte" + spec := globalState.typeMapping.String.Resolve(f) + outSchema.GoType = spec.Type + // Preserve special behaviors for specific types + if outSchema.GoType == "[]byte" { setSkipOptionalPointerForContainerType(outSchema) - case "email": - outSchema.GoType = "openapi_types.Email" - case "date": - outSchema.GoType = "openapi_types.Date" - case "date-time": - outSchema.GoType = "time.Time" - case "json": - outSchema.GoType = "json.RawMessage" + } + if outSchema.GoType == "json.RawMessage" { outSchema.SkipOptionalPointer = true - case "uuid": - outSchema.GoType = "openapi_types.UUID" - case "binary": - outSchema.GoType = "openapi_types.File" - default: - // All unrecognized formats are simply a regular string. - outSchema.GoType = "string" } outSchema.DefineViaAlias = true } else { @@ -771,11 +746,7 @@ func GenFieldsFromProperties(props []Property) []string { shouldOmitEmpty := (!p.Required || p.ReadOnly || p.WriteOnly) && (!p.Required || !p.ReadOnly || !globalState.options.Compatibility.DisableRequiredReadOnlyAsPointer) - omitEmpty := !p.Nullable && shouldOmitEmpty - - if p.Nullable && globalState.options.OutputOptions.NullableType { - omitEmpty = shouldOmitEmpty - } + omitEmpty := shouldOmitEmpty omitZero := false @@ -874,7 +845,9 @@ func paramToGoType(param *openapi3.Parameter, path []string) (Schema, error) { // We can process the schema through the generic schema processor if param.Schema != nil { - return GenerateGoSchema(param.Schema, path) + schema, err := GenerateGoSchema(param.Schema, path) + schema.DefinedComp = ComponentTypeParameter + return schema, err } // At this point, we have a content type. We know how to deal with @@ -884,6 +857,7 @@ func paramToGoType(param *openapi3.Parameter, path []string) (Schema, error) { return Schema{ GoType: "string", Description: StringToGoComment(param.Description), + DefinedComp: ComponentTypeParameter, }, nil } @@ -894,11 +868,14 @@ func paramToGoType(param *openapi3.Parameter, path []string) (Schema, error) { return Schema{ GoType: "string", Description: StringToGoComment(param.Description), + DefinedComp: ComponentTypeParameter, }, nil } // For json, we go through the standard schema mechanism - return GenerateGoSchema(mt.Schema, path) + schema, err := GenerateGoSchema(mt.Schema, path) + schema.DefinedComp = ComponentTypeParameter + return schema, err } func generateUnion(outSchema *Schema, elements openapi3.SchemaRefs, discriminator *openapi3.Discriminator, path []string) error { @@ -942,7 +919,6 @@ func generateUnion(outSchema *Schema, elements openapi3.SchemaRefs, discriminato if v == element.Ref { outSchema.Discriminator.Mapping[k] = elementSchema.GoType mapped = true - break } } // Implicit mapping. @@ -953,7 +929,7 @@ func generateUnion(outSchema *Schema, elements openapi3.SchemaRefs, discriminato outSchema.UnionElements = append(outSchema.UnionElements, UnionElement(elementSchema.GoType)) } - if (outSchema.Discriminator != nil) && len(outSchema.Discriminator.Mapping) != len(elements) { + if (outSchema.Discriminator != nil) && len(outSchema.Discriminator.Mapping) < len(elements) { return errors.New("discriminator: not all schemas were mapped") } diff --git a/pkg/codegen/template_helpers.go b/pkg/codegen/template_helpers.go index 67f9dba3a3..d36e53d13f 100644 --- a/pkg/codegen/template_helpers.go +++ b/pkg/codegen/template_helpers.go @@ -246,14 +246,16 @@ func genResponseUnmarshal(op *OperationDefinition) string { func buildUnmarshalCase(typeDefinition ResponseTypeDefinition, caseAction string, contentType string) (caseKey string, caseClause string) { caseKey = fmt.Sprintf("%s.%s.%s", prefixLeastSpecific, contentType, typeDefinition.ResponseName) caseClauseKey := getConditionOfResponseName("rsp.StatusCode", typeDefinition.ResponseName) - caseClause = fmt.Sprintf("case strings.Contains(rsp.Header.Get(\"%s\"), \"%s\") && %s:\n%s\n", "Content-Type", contentType, caseClauseKey, caseAction) + contentTypeLiteral := StringToGoString(contentType) + caseClause = fmt.Sprintf("case strings.Contains(rsp.Header.Get(\"%s\"), %s) && %s:\n%s\n", "Content-Type", contentTypeLiteral, caseClauseKey, caseAction) return caseKey, caseClause } func buildUnmarshalCaseStrict(typeDefinition ResponseTypeDefinition, caseAction string, contentType string) (caseKey string, caseClause string) { caseKey = fmt.Sprintf("%s.%s.%s", prefixLeastSpecific, contentType, typeDefinition.ResponseName) caseClauseKey := getConditionOfResponseName("rsp.StatusCode", typeDefinition.ResponseName) - caseClause = fmt.Sprintf("case rsp.Header.Get(\"%s\") == \"%s\" && %s:\n%s\n", "Content-Type", contentType, caseClauseKey, caseAction) + contentTypeLiteral := StringToGoString(contentType) + caseClause = fmt.Sprintf("case rsp.Header.Get(\"%s\") == %s && %s:\n%s\n", "Content-Type", contentTypeLiteral, caseClauseKey, caseAction) return caseKey, caseClause } @@ -343,6 +345,7 @@ var TemplateFunctions = template.FuncMap{ "title": titleCaser.String, "stripNewLines": stripNewLines, "sanitizeGoIdentity": SanitizeGoIdentity, + "toGoString": StringToGoString, "toGoComment": StringWithTypeNameToGoComment, "genServerURLWithVariablesFunctionParams": genServerURLWithVariablesFunctionParams, diff --git a/pkg/codegen/templates/client.tmpl b/pkg/codegen/templates/client.tmpl index 822e11097a..d219432e29 100644 --- a/pkg/codegen/templates/client.tmpl +++ b/pkg/codegen/templates/client.tmpl @@ -197,7 +197,7 @@ func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamAr if params != nil { queryValues := queryURL.Query() {{range $paramIdx, $param := .QueryParams}} - {{if .HasOptionalPointer}} if params.{{.GoName}} != nil { {{end}} + {{if .RequiresNilCheck}} if params.{{.GoName}} != nil { {{end}} {{if .IsPassThrough}} queryValues.Add("{{.ParamName}}", {{if .HasOptionalPointer}}*{{end}}params.{{.GoName}}) {{end}} @@ -210,7 +210,7 @@ func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamAr {{end}} {{if .IsStyled}} - if queryFrag, err := runtime.StyleParamWithLocation("{{.Style}}", {{.Explode}}, "{{.ParamName}}", runtime.ParamLocationQuery, {{if .HasOptionalPointer}}*{{end}}params.{{.GoName}}); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("{{.Style}}", {{.Explode}}, "{{.ParamName}}", runtime.ParamLocationQuery, {{if and .RequiresNilCheck .HasOptionalPointer}}*{{end}}params.{{.GoName}}); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -222,7 +222,7 @@ func New{{$opid}}Request{{if .HasBody}}WithBody{{end}}(server string{{genParamAr } } {{end}} - {{if .HasOptionalPointer}}}{{end}} + {{if .RequiresNilCheck}}}{{end}} {{end}} queryURL.RawQuery = queryValues.Encode() } diff --git a/pkg/codegen/templates/constants.tmpl b/pkg/codegen/templates/constants.tmpl index 8fad8764c4..1c8cbd4922 100644 --- a/pkg/codegen/templates/constants.tmpl +++ b/pkg/codegen/templates/constants.tmpl @@ -12,4 +12,14 @@ const ( {{$name}} {{$Enum.TypeName}} = {{$Enum.ValueWrapper}}{{$value}}{{$Enum.ValueWrapper -}} {{end}} ) + +// Valid indicates whether the value is a known member of the {{$Enum.TypeName}} enum. +func (e {{$Enum.TypeName}}) Valid() bool { + switch e { + {{range $name, $value := $Enum.GetValues}}case {{$name}}: + return true + {{end}}default: + return false + } +} {{end}} diff --git a/pkg/codegen/templates/fiber/fiber-middleware.tmpl b/pkg/codegen/templates/fiber/fiber-middleware.tmpl index e44f4836cb..3213e22a7d 100644 --- a/pkg/codegen/templates/fiber/fiber-middleware.tmpl +++ b/pkg/codegen/templates/fiber/fiber-middleware.tmpl @@ -89,22 +89,26 @@ func (siw *ServerInterfaceWrapper) {{$opid}}(c *fiber.Ctx) error { headers := c.GetReqHeaders() {{range .HeaderParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} header parameter "{{.ParamName}}" ------------- - if value, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found { + if valueList, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found { var {{.GoName}} {{.TypeDef}} + n := len(valueList) + if n != 1 { + return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Too many values for ParamName {{.ParamName}}, 1 is required, but %d found", n)) + } {{if .IsPassThrough}} - params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}value + params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}valueList[0] {{end}} {{if .IsJson}} - err = json.Unmarshal([]byte(value), &{{.GoName}}) + err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}}) if err != nil { return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Error unmarshaling parameter '{{.ParamName}}' as JSON: %w", err).Error()) } {{end}} {{if .IsStyled}} - err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", value, &{{.GoName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: {{.Explode}}, Required: {{.Required}}}) + err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", valueList[0], &{{.GoName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: {{.Explode}}, Required: {{.Required}}}) if err != nil { return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for parameter {{.ParamName}}: %w", err).Error()) } diff --git a/pkg/codegen/templates/server-urls.tmpl b/pkg/codegen/templates/server-urls.tmpl index 0a1ccf14b6..41c0717370 100644 --- a/pkg/codegen/templates/server-urls.tmpl +++ b/pkg/codegen/templates/server-urls.tmpl @@ -1,7 +1,7 @@ {{ range . }} {{ if eq 0 (len .OAPISchema.Variables) }} {{/* URLs without variables are straightforward, so we'll create them a constant */}} -// {{ .GoName }} defines the Server URL for {{ .OAPISchema.Description }} +// {{ .GoName }} defines the Server URL for {{ if len .OAPISchema.Description }}{{ .OAPISchema.Description }}{{ else }}{{ .OAPISchema.URL }}{{ end }} const {{ .GoName}} = "{{ .OAPISchema.URL }}" {{ else }} {{/* URLs with variables are not straightforward, as we may need multiple types, and so will model them as a function */}} diff --git a/pkg/codegen/templates/strict/strict-echo.tmpl b/pkg/codegen/templates/strict/strict-echo.tmpl index 676690fab3..7b470c8ce7 100644 --- a/pkg/codegen/templates/strict/strict-echo.tmpl +++ b/pkg/codegen/templates/strict/strict-echo.tmpl @@ -34,9 +34,16 @@ type strictHandler struct { {{if .IsJSON -}} var body {{$opid}}{{.NameTag}}RequestBody if err := ctx.Bind(&body); err != nil { + {{if not .Required -}} + if !errors.Is(err, io.EOF) { + return err + } + {{else -}} return err - } + {{end -}} + } {{if not .Required -}} else { {{end}} request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body + {{if not .Required -}} } {{end}} {{else if eq .NameTag "Formdata" -}} if form, err := ctx.FormParams(); err == nil { var body {{$opid}}{{.NameTag}}RequestBody @@ -68,8 +75,14 @@ type strictHandler struct { if err != nil { return err } + {{if not .Required -}} + if len(data) > 0 { + {{end -}} body := {{$opid}}{{.NameTag}}RequestBody(data) request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body + {{if not .Required -}} + } + {{end -}} {{else -}} request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = ctx.Request().Body {{end}}{{/* if eq .NameTag "JSON" */ -}} diff --git a/pkg/codegen/templates/strict/strict-fiber-interface.tmpl b/pkg/codegen/templates/strict/strict-fiber-interface.tmpl index 8bcfc89b10..e83f7e38aa 100644 --- a/pkg/codegen/templates/strict/strict-fiber-interface.tmpl +++ b/pkg/codegen/templates/strict/strict-fiber-interface.tmpl @@ -77,7 +77,7 @@ {{if eq .NameTag "Multipart" -}} writer := multipart.NewWriter(ctx.Response().BodyWriter()) {{end -}} - ctx.Response().Header.Set("Content-Type", {{if eq .NameTag "Multipart"}}{{if eq .ContentType "multipart/form-data"}}writer.FormDataContentType(){{else}}mime.FormatMediaType("{{.ContentType}}", map[string]string{"boundary": writer.Boundary()}){{end}}{{else if .HasFixedContentType }}"{{.ContentType}}"{{else}}response.ContentType{{end}}) + ctx.Response().Header.Set("Content-Type", {{if eq .NameTag "Multipart"}}{{if eq .ContentType "multipart/form-data"}}writer.FormDataContentType(){{else}}mime.FormatMediaType("{{.ContentType}}", map[string]string{"boundary": writer.Boundary()}){{end}}{{else if .HasFixedContentType }}{{.ContentType | toGoString}}{{else}}response.ContentType{{end}}) {{if not .IsSupported -}} if response.ContentLength != 0 { ctx.Response().Header.Set("Content-Length", fmt.Sprint(response.ContentLength)) diff --git a/pkg/codegen/templates/strict/strict-fiber.tmpl b/pkg/codegen/templates/strict/strict-fiber.tmpl index 510899c9e0..59a2c0736b 100644 --- a/pkg/codegen/templates/strict/strict-fiber.tmpl +++ b/pkg/codegen/templates/strict/strict-fiber.tmpl @@ -36,9 +36,16 @@ type strictHandler struct { {{if .IsJSON }} var body {{$opid}}{{.NameTag}}RequestBody if err := ctx.BodyParser(&body); err != nil { + {{if not .Required -}} + if !errors.Is(err, io.EOF) { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + {{else -}} return fiber.NewError(fiber.StatusBadRequest, err.Error()) - } + {{end -}} + } {{if not .Required -}} else { {{end}} request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body + {{if not .Required -}} } {{end}} {{else if eq .NameTag "Formdata" -}} var body {{$opid}}{{.NameTag}}RequestBody if err := ctx.BodyParser(&body); err != nil { @@ -59,8 +66,14 @@ type strictHandler struct { {{end -}} {{else if eq .NameTag "Text" -}} data := ctx.Request().Body() + {{if not .Required -}} + if len(data) > 0 { + {{end -}} body := {{$opid}}{{.NameTag}}RequestBody(data) request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body + {{if not .Required -}} + } + {{end -}} {{else -}} request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = bytes.NewReader(ctx.Request().Body()) {{end}}{{/* if eq .NameTag "JSON" */ -}} diff --git a/pkg/codegen/templates/strict/strict-gin.tmpl b/pkg/codegen/templates/strict/strict-gin.tmpl index d4c43164a6..40a7b7bcb1 100644 --- a/pkg/codegen/templates/strict/strict-gin.tmpl +++ b/pkg/codegen/templates/strict/strict-gin.tmpl @@ -34,11 +34,20 @@ type strictHandler struct { {{if .IsJSON }} var body {{$opid}}{{.NameTag}}RequestBody if err := ctx.ShouldBindJSON(&body); err != nil { + {{if not .Required -}} + if !errors.Is(err, io.EOF) { + ctx.Status(http.StatusBadRequest) + ctx.Error(err) + return + } + {{else -}} ctx.Status(http.StatusBadRequest) ctx.Error(err) return - } + {{end -}} + } {{if not .Required -}} else { {{end}} request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body + {{if not .Required -}} } {{end}} {{else if eq .NameTag "Formdata" -}} if err := ctx.Request.ParseForm(); err != nil { ctx.Error(err) @@ -75,8 +84,14 @@ type strictHandler struct { ctx.Error(err) return } + {{if not .Required -}} + if len(data) > 0 { + {{end -}} body := {{$opid}}{{.NameTag}}RequestBody(data) request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body + {{if not .Required -}} + } + {{end -}} {{else -}} request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = ctx.Request.Body {{end}}{{/* if eq .NameTag "JSON" */ -}} diff --git a/pkg/codegen/templates/strict/strict-http.tmpl b/pkg/codegen/templates/strict/strict-http.tmpl index 8d32415ad6..7314c26fd7 100644 --- a/pkg/codegen/templates/strict/strict-http.tmpl +++ b/pkg/codegen/templates/strict/strict-http.tmpl @@ -51,10 +51,18 @@ type strictHandler struct { {{if .IsJSON }} var body {{$opid}}{{.NameTag}}RequestBody if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + {{if not .Required -}} + if !errors.Is(err, io.EOF) { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) + return + } + {{else -}} sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode JSON body: %w", err)) return - } + {{end -}} + } {{if not .Required -}} else { {{end}} request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body + {{if not .Required -}} } {{end}} {{else if eq .NameTag "Formdata" -}} if err := r.ParseForm(); err != nil { sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode formdata: %w", err)) @@ -91,8 +99,14 @@ type strictHandler struct { sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err)) return } + {{if not .Required -}} + if len(data) > 0 { + {{end -}} body := {{$opid}}{{.NameTag}}RequestBody(data) request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body + {{if not .Required -}} + } + {{end -}} {{else -}} request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = r.Body {{end}}{{/* if eq .NameTag "JSON" */ -}} diff --git a/pkg/codegen/templates/strict/strict-interface.tmpl b/pkg/codegen/templates/strict/strict-interface.tmpl index e19936d6a7..62f3d4d9c6 100644 --- a/pkg/codegen/templates/strict/strict-interface.tmpl +++ b/pkg/codegen/templates/strict/strict-interface.tmpl @@ -40,7 +40,7 @@ {{range .Contents}} {{$receiverTypeName := printf "%s%s%s%s" $opid $statusCode .NameTagOrContentType "Response"}} {{if and $fixedStatusCode $isRef -}} - {{ if and (not $hasHeaders) ($fixedStatusCode) (.IsSupported) (eq .NameTag "Multipart") -}} + {{ if and (not $hasHeaders) ($fixedStatusCode) (.IsSupported) (or (eq .NameTag "Multipart") (eq .NameTag "Text")) -}} type {{$receiverTypeName}} {{$ref}}{{.NameTagOrContentType}}Response {{else if $isExternalRef -}} type {{$receiverTypeName}} struct { {{$ref}} } @@ -74,7 +74,7 @@ {{if eq .NameTag "Multipart" -}} writer := multipart.NewWriter(w) {{end -}} - w.Header().Set("Content-Type", {{if eq .NameTag "Multipart"}}{{if eq .ContentType "multipart/form-data"}}writer.FormDataContentType(){{else}}mime.FormatMediaType("{{.ContentType}}", map[string]string{"boundary": writer.Boundary()}){{end}}{{else if .HasFixedContentType }}"{{.ContentType}}"{{else}}response.ContentType{{end}}) + w.Header().Set("Content-Type", {{if eq .NameTag "Multipart"}}{{if eq .ContentType "multipart/form-data"}}writer.FormDataContentType(){{else}}mime.FormatMediaType("{{.ContentType}}", map[string]string{"boundary": writer.Boundary()}){{end}}{{else if .HasFixedContentType }}{{.ContentType | toGoString}}{{else}}response.ContentType{{end}}) {{if not .IsSupported -}} if response.ContentLength != 0 { w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength)) diff --git a/pkg/codegen/templates/strict/strict-iris-interface.tmpl b/pkg/codegen/templates/strict/strict-iris-interface.tmpl index e93fdf6166..95b78d0645 100644 --- a/pkg/codegen/templates/strict/strict-iris-interface.tmpl +++ b/pkg/codegen/templates/strict/strict-iris-interface.tmpl @@ -79,7 +79,7 @@ {{if eq .NameTag "Multipart" -}} writer := multipart.NewWriter(ctx.ResponseWriter()) {{end -}} - ctx.ResponseWriter().Header().Set("Content-Type", {{if eq .NameTag "Multipart"}}{{if eq .ContentType "multipart/form-data"}}writer.FormDataContentType(){{else}}mime.FormatMediaType("{{.ContentType}}", map[string]string{"boundary": writer.Boundary()}){{end}}{{else if .HasFixedContentType }}"{{.ContentType}}"{{else}}response.ContentType{{end}}) + ctx.ResponseWriter().Header().Set("Content-Type", {{if eq .NameTag "Multipart"}}{{if eq .ContentType "multipart/form-data"}}writer.FormDataContentType(){{else}}mime.FormatMediaType("{{.ContentType}}", map[string]string{"boundary": writer.Boundary()}){{end}}{{else if .HasFixedContentType }}{{.ContentType | toGoString}}{{else}}response.ContentType{{end}}) {{if not .IsSupported -}} if response.ContentLength != 0 { ctx.ResponseWriter().Header().Set("Content-Length", fmt.Sprint(response.ContentLength)) @@ -128,7 +128,7 @@ {{end -}} func (response {{$opid}}{{$statusCode}}Response) Visit{{$opid}}Response(ctx iris.Context) error { {{range $headers -}} - ctx.Response().Header.Set("{{.Name}}", fmt.Sprint(response.Headers.{{.GoName}})) + ctx.ResponseWriter().Header().Set("{{.Name}}", fmt.Sprint(response.Headers.{{.GoName}})) {{end -}} ctx.StatusCode({{if $fixedStatusCode}}{{$statusCode}}{{else}}response.StatusCode{{end}}) return nil diff --git a/pkg/codegen/templates/strict/strict-iris.tmpl b/pkg/codegen/templates/strict/strict-iris.tmpl index dfdeb1546f..6ed301574c 100644 --- a/pkg/codegen/templates/strict/strict-iris.tmpl +++ b/pkg/codegen/templates/strict/strict-iris.tmpl @@ -34,10 +34,18 @@ type strictHandler struct { {{if .IsJSON }} var body {{$opid}}{{.NameTag}}RequestBody if err := ctx.ReadJSON(&body); err != nil { + {{if not .Required -}} + if !errors.Is(err, io.EOF) { + ctx.StopWithError(http.StatusBadRequest, err) + return + } + {{else -}} ctx.StopWithError(http.StatusBadRequest, err) return - } + {{end -}} + } {{if not .Required -}} else { {{end}} request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body + {{if not .Required -}} } {{end}} {{else if eq .NameTag "Formdata" -}} if err := ctx.Request().ParseForm(); err != nil { ctx.StopWithError(http.StatusBadRequest, err) @@ -74,8 +82,14 @@ type strictHandler struct { ctx.StopWithError(http.StatusBadRequest, err) return } + {{if not .Required -}} + if len(data) > 0 { + {{end -}} body := {{$opid}}{{.NameTag}}RequestBody(data) request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = &body + {{if not .Required -}} + } + {{end -}} {{else -}} request.{{if $multipleBodies}}{{.NameTag}}{{end}}Body = ctx.Request().Body {{end}}{{/* if eq .NameTag "JSON" */ -}} diff --git a/pkg/codegen/templates/union.tmpl b/pkg/codegen/templates/union.tmpl index b27a2aca3f..61c2bf37fd 100644 --- a/pkg/codegen/templates/union.tmpl +++ b/pkg/codegen/templates/union.tmpl @@ -2,6 +2,7 @@ {{$typeName := .TypeName -}} {{$discriminator := .Schema.Discriminator}} {{$properties := .Schema.Properties -}} + {{$numberOfUnionTypes := len .Schema.UnionElements -}} {{range .Schema.UnionElements}} {{$element := . -}} // As{{ .Method }} returns the union data inside the {{$typeName}} as a {{.}} @@ -14,16 +15,18 @@ // From{{ .Method }} overwrites any union data inside the {{$typeName}} as the provided {{.}} func (t *{{$typeName}}) From{{ .Method }} (v {{.}}) error { {{if $discriminator -}} - {{range $value, $type := $discriminator.Mapping -}} - {{if eq $type $element -}} - {{$hasProperty := false -}} - {{range $properties -}} - {{if eq .GoFieldName $discriminator.PropertyName -}} - t.{{$discriminator.PropertyName}} = "{{$value}}" - {{$hasProperty = true -}} + {{if eq $numberOfUnionTypes (len $discriminator.Mapping) -}} + {{range $value, $type := $discriminator.Mapping -}} + {{if eq $type $element -}} + {{$hasProperty := false -}} + {{range $properties -}} + {{if eq .GoFieldName $discriminator.PropertyName -}} + t.{{$discriminator.PropertyName}} = "{{$value}}" + {{$hasProperty = true -}} + {{end -}} {{end -}} + {{if not $hasProperty}}v.{{$discriminator.PropertyName}} = "{{$value}}"{{end}} {{end -}} - {{if not $hasProperty}}v.{{$discriminator.PropertyName}} = "{{$value}}"{{end}} {{end -}} {{end -}} {{end -}} @@ -35,16 +38,18 @@ // Merge{{ .Method }} performs a merge with any union data inside the {{$typeName}}, using the provided {{.}} func (t *{{$typeName}}) Merge{{ .Method }} (v {{.}}) error { {{if $discriminator -}} - {{range $value, $type := $discriminator.Mapping -}} - {{if eq $type $element -}} - {{$hasProperty := false -}} - {{range $properties -}} - {{if eq .GoFieldName $discriminator.PropertyName -}} - t.{{$discriminator.PropertyName}} = "{{$value}}" - {{$hasProperty = true -}} + {{if eq $numberOfUnionTypes (len $discriminator.Mapping) -}} + {{range $value, $type := $discriminator.Mapping -}} + {{if eq $type $element -}} + {{$hasProperty := false -}} + {{range $properties -}} + {{if eq .GoFieldName $discriminator.PropertyName -}} + t.{{$discriminator.PropertyName}} = "{{$value}}" + {{$hasProperty = true -}} + {{end -}} {{end -}} + {{if not $hasProperty}}v.{{$discriminator.PropertyName}} = "{{$value}}"{{end}} {{end -}} - {{if not $hasProperty}}v.{{$discriminator.PropertyName}} = "{{$value}}"{{end}} {{end -}} {{end -}} {{end -}} diff --git a/pkg/codegen/test_spec.yaml b/pkg/codegen/test_spec.yaml index b50f7491c5..f20cbecdca 100644 --- a/pkg/codegen/test_spec.yaml +++ b/pkg/codegen/test_spec.yaml @@ -164,15 +164,45 @@ components: format: date-time CatDead: + required: + - sliced_birds + - very_dead_since + - very_memorable_birds properties: name: type: string + favourite_birds: + type: array + items: + type: string + nullable: true + detested_birds: + type: array + items: + type: string + sliced_birds: + type: array + items: + type: string + forgettable_birds: + additionalProperties: + type: string + nullable: true + memorable_birds: + additionalProperties: + type: string + very_memorable_birds: + additionalProperties: + type: string dead_since: type: string format: date-time x-oapi-codegen-extra-tags: tag1: value1 tag2: value2 + very_dead_since: + type: string + format: date-time cause: type: string enum: [ car, dog, oldage ] diff --git a/pkg/codegen/typemapping.go b/pkg/codegen/typemapping.go new file mode 100644 index 0000000000..f5e20b54ac --- /dev/null +++ b/pkg/codegen/typemapping.go @@ -0,0 +1,109 @@ +package codegen + +// SimpleTypeSpec defines the Go type for an OpenAPI type/format combination, +// along with any import required to use it. +type SimpleTypeSpec struct { + Type string `yaml:"type" json:"type"` + Import string `yaml:"import,omitempty" json:"import,omitempty"` +} + +// FormatMapping defines the default Go type and format-specific overrides +// for an OpenAPI type. +type FormatMapping struct { + Default SimpleTypeSpec `yaml:"default" json:"default"` + Formats map[string]SimpleTypeSpec `yaml:"formats,omitempty" json:"formats,omitempty"` +} + +// TypeMapping defines the mapping from OpenAPI types to Go types. +type TypeMapping struct { + Integer FormatMapping `yaml:"integer,omitempty" json:"integer,omitempty"` + Number FormatMapping `yaml:"number,omitempty" json:"number,omitempty"` + Boolean FormatMapping `yaml:"boolean,omitempty" json:"boolean,omitempty"` + String FormatMapping `yaml:"string,omitempty" json:"string,omitempty"` +} + +// Merge returns a new TypeMapping with user overrides applied on top of base. +func (base TypeMapping) Merge(user TypeMapping) TypeMapping { + return TypeMapping{ + Integer: base.Integer.merge(user.Integer), + Number: base.Number.merge(user.Number), + Boolean: base.Boolean.merge(user.Boolean), + String: base.String.merge(user.String), + } +} + +func (base FormatMapping) merge(user FormatMapping) FormatMapping { + result := FormatMapping{ + Default: base.Default, + Formats: make(map[string]SimpleTypeSpec), + } + + // Copy base formats + for k, v := range base.Formats { + result.Formats[k] = v + } + + // Override with user default if specified + if user.Default.Type != "" { + result.Default = user.Default + } + + // Override/add user formats + for k, v := range user.Formats { + result.Formats[k] = v + } + + return result +} + +// Resolve returns the SimpleTypeSpec for a given format string. +// If the format has a specific mapping, that is returned; otherwise the default is used. +func (fm FormatMapping) Resolve(format string) SimpleTypeSpec { + if format != "" { + if spec, ok := fm.Formats[format]; ok { + return spec + } + } + return fm.Default +} + +// DefaultTypeMapping provides the default OpenAPI type/format to Go type mappings. +var DefaultTypeMapping = TypeMapping{ + Integer: FormatMapping{ + Default: SimpleTypeSpec{Type: "int"}, + Formats: map[string]SimpleTypeSpec{ + "int": {Type: "int"}, + "int8": {Type: "int8"}, + "int16": {Type: "int16"}, + "int32": {Type: "int32"}, + "int64": {Type: "int64"}, + "uint": {Type: "uint"}, + "uint8": {Type: "uint8"}, + "uint16": {Type: "uint16"}, + "uint32": {Type: "uint32"}, + "uint64": {Type: "uint64"}, + }, + }, + Number: FormatMapping{ + Default: SimpleTypeSpec{Type: "float32"}, + Formats: map[string]SimpleTypeSpec{ + "float": {Type: "float32"}, + "double": {Type: "float64"}, + }, + }, + Boolean: FormatMapping{ + Default: SimpleTypeSpec{Type: "bool"}, + }, + String: FormatMapping{ + Default: SimpleTypeSpec{Type: "string"}, + Formats: map[string]SimpleTypeSpec{ + "byte": {Type: "[]byte"}, + "email": {Type: "openapi_types.Email"}, + "date": {Type: "openapi_types.Date"}, + "date-time": {Type: "time.Time", Import: "time"}, + "json": {Type: "json.RawMessage", Import: "encoding/json"}, + "uuid": {Type: "openapi_types.UUID"}, + "binary": {Type: "openapi_types.File"}, + }, + }, +} diff --git a/pkg/codegen/typemapping_test.go b/pkg/codegen/typemapping_test.go new file mode 100644 index 0000000000..ca593cfd5d --- /dev/null +++ b/pkg/codegen/typemapping_test.go @@ -0,0 +1,88 @@ +package codegen + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFormatMapping_Resolve(t *testing.T) { + fm := FormatMapping{ + Default: SimpleTypeSpec{Type: "int"}, + Formats: map[string]SimpleTypeSpec{ + "int32": {Type: "int32"}, + "int64": {Type: "int64"}, + }, + } + + assert.Equal(t, "int", fm.Resolve("").Type) + assert.Equal(t, "int32", fm.Resolve("int32").Type) + assert.Equal(t, "int64", fm.Resolve("int64").Type) + assert.Equal(t, "int", fm.Resolve("unknown-format").Type) +} + +func TestTypeMapping_Merge(t *testing.T) { + base := DefaultTypeMapping + + user := TypeMapping{ + Integer: FormatMapping{ + Default: SimpleTypeSpec{Type: "int64"}, + }, + String: FormatMapping{ + Formats: map[string]SimpleTypeSpec{ + "date-time": {Type: "civil.DateTime", Import: "cloud.google.com/go/civil"}, + }, + }, + } + + merged := base.Merge(user) + + // Integer default overridden + assert.Equal(t, "int64", merged.Integer.Default.Type) + // Integer formats still inherited from base + assert.Equal(t, "int32", merged.Integer.Formats["int32"].Type) + + // String date-time overridden + assert.Equal(t, "civil.DateTime", merged.String.Formats["date-time"].Type) + assert.Equal(t, "cloud.google.com/go/civil", merged.String.Formats["date-time"].Import) + // String default still inherited from base + assert.Equal(t, "string", merged.String.Default.Type) + // Other string formats still inherited + assert.Equal(t, "openapi_types.UUID", merged.String.Formats["uuid"].Type) + + // Number and Boolean unchanged + assert.Equal(t, "float32", merged.Number.Default.Type) + assert.Equal(t, "bool", merged.Boolean.Default.Type) +} + +func TestDefaultTypeMapping_Completeness(t *testing.T) { + // Verify all the default mappings match what was previously hardcoded + dm := DefaultTypeMapping + + // Integer + assert.Equal(t, "int", dm.Integer.Resolve("").Type) + assert.Equal(t, "int32", dm.Integer.Resolve("int32").Type) + assert.Equal(t, "int64", dm.Integer.Resolve("int64").Type) + assert.Equal(t, "uint32", dm.Integer.Resolve("uint32").Type) + assert.Equal(t, "int", dm.Integer.Resolve("unknown").Type) + + // Number + assert.Equal(t, "float32", dm.Number.Resolve("").Type) + assert.Equal(t, "float32", dm.Number.Resolve("float").Type) + assert.Equal(t, "float64", dm.Number.Resolve("double").Type) + assert.Equal(t, "float32", dm.Number.Resolve("unknown").Type) + + // Boolean + assert.Equal(t, "bool", dm.Boolean.Resolve("").Type) + + // String + assert.Equal(t, "string", dm.String.Resolve("").Type) + assert.Equal(t, "[]byte", dm.String.Resolve("byte").Type) + assert.Equal(t, "openapi_types.Email", dm.String.Resolve("email").Type) + assert.Equal(t, "openapi_types.Date", dm.String.Resolve("date").Type) + assert.Equal(t, "time.Time", dm.String.Resolve("date-time").Type) + assert.Equal(t, "json.RawMessage", dm.String.Resolve("json").Type) + assert.Equal(t, "openapi_types.UUID", dm.String.Resolve("uuid").Type) + assert.Equal(t, "openapi_types.File", dm.String.Resolve("binary").Type) + assert.Equal(t, "string", dm.String.Resolve("unknown").Type) +} diff --git a/pkg/codegen/utils.go b/pkg/codegen/utils.go index 5326e672bf..549d5cffa3 100644 --- a/pkg/codegen/utils.go +++ b/pkg/codegen/utils.go @@ -20,6 +20,7 @@ import ( "net/url" "reflect" "regexp" + "slices" "sort" "strconv" "strings" @@ -205,7 +206,7 @@ func LowercaseFirstCharacters(str string) string { runes := []rune(str) - for i := 0; i < len(runes); i++ { + for i := range runes { next := i + 1 if i != 0 && next < len(runes) && unicode.IsLower(runes[next]) { break @@ -224,25 +225,25 @@ func LowercaseFirstCharacters(str string) string { func ToCamelCase(str string) string { s := strings.Trim(str, " ") - n := "" + var n strings.Builder capNext := true for _, v := range s { if unicode.IsUpper(v) { - n += string(v) + n.WriteString(string(v)) } if unicode.IsDigit(v) { - n += string(v) + n.WriteString(string(v)) } if unicode.IsLower(v) { if capNext { - n += strings.ToUpper(string(v)) + n.WriteString(strings.ToUpper(string(v))) } else { - n += string(v) + n.WriteString(string(v)) } } _, capNext = separatorSet[v] } - return n + return n.String() } // ToCamelCaseWithDigits function will convert query-arg style strings to CamelCase. We will @@ -407,12 +408,7 @@ func schemaXOrder(v *openapi3.SchemaRef) (int64, bool) { // StringInArray checks whether the specified string is present in an array // of strings func StringInArray(str string, array []string) bool { - for _, elt := range array { - if elt == str { - return true - } - } - return false + return slices.Contains(array, str) } // RefPathToObjName returns the name of referenced object without changes. @@ -654,15 +650,29 @@ func ReplacePathParamsWithStr(uri string) string { } // SortParamsByPath reorders the given parameter definitions to match those in the path URI. +// If a parameter appears more than once in the path (e.g. Keycloak's +// /clients/{client-uuid}/roles/{role-name}/composites/clients/{client-uuid}), +// duplicates are removed and only the first occurrence determines the order. func SortParamsByPath(path string, in []ParameterDefinition) ([]ParameterDefinition, error) { pathParams := OrderedParamsFromUri(path) + + // Deduplicate, preserving first-occurrence order. + seen := make(map[string]struct{}, len(pathParams)) + uniqueParams := make([]string, 0, len(pathParams)) + for _, name := range pathParams { + if _, exists := seen[name]; !exists { + seen[name] = struct{}{} + uniqueParams = append(uniqueParams, name) + } + } + n := len(in) - if len(pathParams) != n { + if len(uniqueParams) != n { return nil, fmt.Errorf("path '%s' has %d positional parameters, but spec has %d declared", - path, len(pathParams), n) + path, len(uniqueParams), n) } - out := make([]ParameterDefinition, len(in)) - for i, name := range pathParams { + out := make([]ParameterDefinition, n) + for i, name := range uniqueParams { p := ParameterDefinitions(in).FindByName(name) if p == nil { return nil, fmt.Errorf("path '%s' refers to parameter '%s', which doesn't exist in specification", @@ -864,6 +874,13 @@ func PathToTypeName(path []string) string { return strings.Join(path, "_") } +// StringToGoString takes an arbitrary string and converts it to a valid Go string literal, +// including the quotes. For instance, `foo "bar"` would be converted to `"foo \"bar\""` +func StringToGoString(in string) string { + esc := strings.ReplaceAll(in, "\"", "\\\"") + return fmt.Sprintf("\"%s\"", esc) +} + // StringToGoComment renders a possible multi-line string as a valid Go-Comment. // Each line is prefixed as a comment. func StringToGoComment(in string) string { @@ -1053,7 +1070,7 @@ func ParseGoImportExtension(v *openapi3.SchemaRef) (*goImport, error) { goTypeImportExt := v.Value.Extensions[extPropGoImport] - importI, ok := goTypeImportExt.(map[string]interface{}) + importI, ok := goTypeImportExt.(map[string]any) if !ok { return nil, fmt.Errorf("failed to convert type: %T", goTypeImportExt) } @@ -1105,10 +1122,88 @@ func isAdditionalPropertiesExplicitFalse(s *openapi3.Schema) bool { } func sliceContains[E comparable](s []E, v E) bool { - for _, ss := range s { - if ss == v { + return slices.Contains(s, v) +} + +// FixDuplicateTypeNames renames duplicate type names. +func FixDuplicateTypeNames(typeDefs []TypeDefinition) []TypeDefinition { + if !hasDuplicatedTypeNames(typeDefs) { + return typeDefs + } + + // try to fix duplicate type names with their definition section + typeDefs = fixDuplicateTypeNamesWithCompName(typeDefs) + if !hasDuplicatedTypeNames(typeDefs) { + return typeDefs + } + + const maxIter = 100 + for i := 0; i < maxIter && hasDuplicatedTypeNames(typeDefs); i++ { + typeDefs = fixDuplicateTypeNamesDupCounts(typeDefs) + } + + if hasDuplicatedTypeNames(typeDefs) { + panic("too much duplicate type names") + } + + return typeDefs +} + +func hasDuplicatedTypeNames(typeDefs []TypeDefinition) bool { + dupCheck := make(map[string]int, len(typeDefs)) + + for _, d := range typeDefs { + dupCheck[d.TypeName]++ + + if dupCheck[d.TypeName] != 1 { return true } } + return false } + +func fixDuplicateTypeNamesWithCompName(typeDefs []TypeDefinition) []TypeDefinition { + dupCheck := make(map[string]int, len(typeDefs)) + deDup := make([]TypeDefinition, len(typeDefs)) + + for i, d := range typeDefs { + dupCheck[d.TypeName]++ + + if dupCheck[d.TypeName] != 1 { + switch d.Schema.DefinedComp { + case ComponentTypeSchema: + d.TypeName += "Schema" + case ComponentTypeParameter: + d.TypeName += "Parameter" + case ComponentTypeRequestBody: + d.TypeName += "RequestBody" + case ComponentTypeResponse: + d.TypeName += "Response" + case ComponentTypeHeader: + d.TypeName += "Header" + } + } + + deDup[i] = d + } + + return deDup +} + +func fixDuplicateTypeNamesDupCounts(typeDefs []TypeDefinition) []TypeDefinition { + dupCheck := make(map[string]int, len(typeDefs)) + deDup := make([]TypeDefinition, len(typeDefs)) + + for i, d := range typeDefs { + dupCheck[d.TypeName]++ + + if dupCheck[d.TypeName] != 1 { + d.TypeName = d.TypeName + strconv.Itoa(dupCheck[d.TypeName]) + } + + deDup[i] = d + } + + return deDup +} diff --git a/pkg/codegen/utils_test.go b/pkg/codegen/utils_test.go index af71438473..3f9e0e8b76 100644 --- a/pkg/codegen/utils_test.go +++ b/pkg/codegen/utils_test.go @@ -160,7 +160,7 @@ func TestSortedSchemaKeysWithXOrder(t *testing.T) { withOrder := func(i float64) *openapi3.SchemaRef { return &openapi3.SchemaRef{ Value: &openapi3.Schema{ - Extensions: map[string]interface{}{"x-order": i}, + Extensions: map[string]any{"x-order": i}, }, } } @@ -462,6 +462,53 @@ func TestOrderedParamsFromUri(t *testing.T) { result = OrderedParamsFromUri("/path/foo") assert.EqualValues(t, []string{}, result) + + // A parameter can appear more than once in the URI (e.g. Keycloak API). + // OrderedParamsFromUri faithfully returns all occurrences. + result = OrderedParamsFromUri("/admin/realms/{realm}/clients/{client-uuid}/roles/{role-name}/composites/clients/{client-uuid}") + assert.EqualValues(t, []string{"realm", "client-uuid", "role-name", "client-uuid"}, result) +} + +func TestSortParamsByPath(t *testing.T) { + strSchema := &openapi3.Schema{Type: &openapi3.Types{"string"}} + + t.Run("reorders params to match path order", func(t *testing.T) { + params := []ParameterDefinition{ + {ParamName: "b", In: "path", Spec: &openapi3.Parameter{Name: "b", Schema: &openapi3.SchemaRef{Value: strSchema}}}, + {ParamName: "a", In: "path", Spec: &openapi3.Parameter{Name: "a", Schema: &openapi3.SchemaRef{Value: strSchema}}}, + } + sorted, err := SortParamsByPath("/foo/{a}/bar/{b}", params) + require.NoError(t, err) + require.Len(t, sorted, 2) + assert.Equal(t, "a", sorted[0].ParamName) + assert.Equal(t, "b", sorted[1].ParamName) + }) + + t.Run("errors on missing parameter", func(t *testing.T) { + params := []ParameterDefinition{ + {ParamName: "a", In: "path", Spec: &openapi3.Parameter{Name: "a", Schema: &openapi3.SchemaRef{Value: strSchema}}}, + } + _, err := SortParamsByPath("/foo/{a}/bar/{b}", params) + assert.Error(t, err) + }) + + t.Run("handles duplicate path parameters", func(t *testing.T) { + // This is the Keycloak-style path where {client-uuid} appears twice. + // The spec only declares 3 unique parameters. + params := []ParameterDefinition{ + {ParamName: "realm", In: "path", Spec: &openapi3.Parameter{Name: "realm", Schema: &openapi3.SchemaRef{Value: strSchema}}}, + {ParamName: "client-uuid", In: "path", Spec: &openapi3.Parameter{Name: "client-uuid", Schema: &openapi3.SchemaRef{Value: strSchema}}}, + {ParamName: "role-name", In: "path", Spec: &openapi3.Parameter{Name: "role-name", Schema: &openapi3.SchemaRef{Value: strSchema}}}, + } + path := "/admin/realms/{realm}/clients/{client-uuid}/roles/{role-name}/composites/clients/{client-uuid}" + sorted, err := SortParamsByPath(path, params) + require.NoError(t, err) + // Should return 3 unique params in first-occurrence order + require.Len(t, sorted, 3) + assert.Equal(t, "realm", sorted[0].ParamName) + assert.Equal(t, "client-uuid", sorted[1].ParamName) + assert.Equal(t, "role-name", sorted[2].ParamName) + }) } func TestReplacePathParamsWithStr(t *testing.T) { @@ -469,6 +516,36 @@ func TestReplacePathParamsWithStr(t *testing.T) { assert.EqualValues(t, "/path/%s/%s/%s/foo", result) } +func TestStringToGoStringValue(t *testing.T) { + testCases := []struct { + input string + expected string + message string + }{ + { + input: ``, + expected: `""`, + message: "blank string should be converted to empty Go string literal", + }, + { + input: `application/json`, + expected: `"application/json"`, + message: "typical string should be returned as-is", + }, + { + input: `application/json; foo="bar"`, + expected: `"application/json; foo=\"bar\""`, + message: "string with quotes should include escape characters", + }, + } + for _, testCase := range testCases { + t.Run(testCase.message, func(t *testing.T) { + result := StringToGoString(testCase.input) + assert.EqualValues(t, testCase.expected, result, testCase.message) + }) + } +} + func TestStringToGoComment(t *testing.T) { testCases := []struct { input string @@ -604,6 +681,7 @@ func TestSchemaNameToTypeName(t *testing.T) { "=3": "Equal3", "#Tag": "HashTag", ".com": "DotCom", + "_1": "Underscore1", ">=": "GreaterThanEqual", "<=": "LessThanEqual", "<": "LessThan", diff --git a/pkg/util/loader.go b/pkg/util/loader.go index 89830a8c44..7eea07b156 100644 --- a/pkg/util/loader.go +++ b/pkg/util/loader.go @@ -48,13 +48,17 @@ func LoadSwaggerWithOverlay(filePath string, opts LoadSwaggerWithOverlayOpts) (s } // parse out the yaml.Node, which is required by the overlay library - data, err := yaml.Marshal(spec) + buf := &bytes.Buffer{} + enc := yaml.NewEncoder(buf) + // set to 2 to work around https://github.com/yaml/go-yaml/issues/76 + enc.SetIndent(2) + err = enc.Encode(spec) if err != nil { return nil, fmt.Errorf("failed to marshal spec from %#v as YAML: %w", filePath, err) } var node yaml.Node - err = yaml.NewDecoder(bytes.NewReader(data)).Decode(&node) + err = yaml.NewDecoder(buf).Decode(&node) if err != nil { return nil, fmt.Errorf("failed to parse spec from %#v: %w", filePath, err) } diff --git a/renovate.json b/renovate.json index 85610cfaa1..937309a128 100644 --- a/renovate.json +++ b/renovate.json @@ -6,6 +6,9 @@ "gomod": { "ignorePaths": [] }, + "vulnerabilityAlerts": { + "commitMessageSuffix": "{{#if isGroup }}{{ else }} ({{#if packageFileDir}}{{packageFileDir}}{{else}}{{packageFile}}{{/if}}){{/if}} [SECURITY]" + }, "packageRules": [ { "description": "Ensure that each directory has their own set of dependency updates, split by the parent directory of the package file (`packageFileDir`). Groups will be unaffected.", @@ -15,6 +18,16 @@ "additionalBranchPrefix": "{{#if isGroup }}{{ else }}{{#if packageFileDir}}{{packageFileDir}}/{{else}}{{packageFile}}/{{/if}}{{/if}}", "commitMessageSuffix": "{{#if isGroup }}{{ else }} ({{#if packageFileDir}}{{packageFileDir}}{{else}}{{packageFile}}{{/if}}){{/if}}" }, + { + "description": "Label example/test code separately", + "matchFileNames": [ + "internal/test/**/*", + "examples/**/*" + ], + "labels": [ + "dependencies-test-only" + ] + }, { "description": "Don't attempt to bump dependencies if they're only used in example code, but allow manually forcing them via Dependency Dashboard", "matchFileNames": [ @@ -26,7 +39,7 @@ { "description": "Don't attempt to bump `replace` statements for internal modules", "matchDepNames": [ - "github.com/oapi-codegen/oapi-codegen/v2" + "github.com/livesession/oapi-codegen/v2" ], "matchCurrentVersion": "v2.0.0-00010101000000-000000000000", "enabled": false @@ -34,7 +47,7 @@ { "description": "Don't attempt to bump `replace` statements for internal modules", "matchDepNames": [ - "github.com/oapi-codegen/oapi-codegen/v2/internal/test" + "github.com/livesession/oapi-codegen/v2/internal/test" ], "matchCurrentVersion": "v0.0.0-00010101000000-000000000000", "enabled": false