diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 000000000..be8851996
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+* @oapi-codegen/maintainers
diff --git a/.github/sponsors/devzero-dark.svg b/.github/sponsors/devzero-dark.svg
new file mode 100644
index 000000000..9085ad180
--- /dev/null
+++ b/.github/sponsors/devzero-dark.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.github/sponsors/devzero-light.svg b/.github/sponsors/devzero-light.svg
new file mode 100644
index 000000000..8889a2919
--- /dev/null
+++ b/.github/sponsors/devzero-light.svg
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b5e2385b2..46a81612c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -8,24 +8,24 @@ jobs:
fail-fast: false
# perform matrix testing to give us an earlier insight into issues with different versions of supported major versions of Go
matrix:
- # strategy is used to allow us to pin to a specific Go version, or use the version available in our `go.mod`
- strategy: ['go-version']
- version: [1.21]
- include:
- # pick up the Go version from the `go.mod`
- - strategy: 'go-version-file'
- version: 'go.mod'
+ version:
+ - "1.20"
+ - "1.21"
+ - "1.22"
steps:
- name: Check out source code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up Go
- uses: actions/setup-go@v3
+ uses: actions/setup-go@v5
with:
- ${{ matrix.strategy }}: ${{ matrix.version }}
+ go-version: ${{ matrix.version }}
- name: Test
run: make test
+ 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
diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml
index 7e79884f3..a05186cd5 100644
--- a/.github/workflows/generate.yml
+++ b/.github/workflows/generate.yml
@@ -8,24 +8,24 @@ jobs:
fail-fast: false
# perform matrix testing to give us an earlier insight into issues with different versions of supported major versions of Go
matrix:
- # strategy is used to allow us to pin to a specific Go version, or use the version available in our `go.mod`
- strategy: ['go-version']
- version: [1.21]
- include:
- # pick up the Go version from the `go.mod`
- - strategy: 'go-version-file'
- version: 'go.mod'
+ version:
+ - "1.20"
+ - "1.21"
+ - "1.22"
steps:
- name: Check out source code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up Go
- uses: actions/setup-go@v3
+ uses: actions/setup-go@v5
with:
- ${{ matrix.strategy }}: ${{ matrix.version }}
+ 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 --
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 816093ded..f560f5e6e 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -8,21 +8,21 @@ jobs:
fail-fast: false
# perform matrix testing to give us an earlier insight into issues with different versions of supported major versions of Go
matrix:
- # strategy is used to allow us to pin to a specific Go version, or use the version available in our `go.mod`
- strategy: ['go-version']
- version: [1.21]
- include:
- # pick up the Go version from the `go.mod`
- - strategy: 'go-version-file'
- version: 'go.mod'
+ version:
+ - "1.20"
+ - "1.21"
+ - "1.22"
steps:
- name: Check out source code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up Go
- uses: actions/setup-go@v3
+ uses: actions/setup-go@v5
with:
- ${{ matrix.strategy }}: ${{ matrix.version }}
+ 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
diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml
index e10c997ee..1890eb4a5 100644
--- a/.github/workflows/release-drafter.yml
+++ b/.github/workflows/release-drafter.yml
@@ -16,7 +16,7 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
- - uses: release-drafter/release-drafter@v5
+ - uses: release-drafter/release-drafter@v6
with:
name: next
tag: next
diff --git a/.github/workflows/tidy.yml b/.github/workflows/tidy.yml
index 946208c42..687320a10 100644
--- a/.github/workflows/tidy.yml
+++ b/.github/workflows/tidy.yml
@@ -8,24 +8,24 @@ jobs:
fail-fast: false
# perform matrix testing to give us an earlier insight into issues with different versions of supported major versions of Go
matrix:
- # strategy is used to allow us to pin to a specific Go version, or use the version available in our `go.mod`
- strategy: ['go-version']
- version: [1.21]
- include:
- # pick up the Go version from the `go.mod`
- - strategy: 'go-version-file'
- version: 'go.mod'
+ version:
+ - "1.20"
+ - "1.21"
+ - "1.22"
steps:
- name: Check out source code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up Go
- uses: actions/setup-go@v3
+ uses: actions/setup-go@v5
with:
- ${{ matrix.strategy }}: ${{ matrix.version }}
+ go-version: ${{ matrix.version }}
- name: Install `tidied`
run: go install gitlab.com/jamietanna/tidied@latest
- name: Check for no untracked files
- run: git ls-files go.mod '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $(dirname {}) && tidied -verbose'
+ 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
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..137f45c25
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,96 @@
+## Contributing
+
+If you're interested in contributing to `oapi-codegen`, the first thing we have to say is thank you! We'd like to extend our gratitude to anyone who takes the time to improve this project.
+
+`oapi-codegen` is being actively maintained, however the two people who do so are very busy, and can only set aside time for this project every once in a while, so our release cadence is slow and conservative.
+
+> [!NOTE]
+> We're actively considering what needs to change to make `oapi-codegen` more sustainable, and hope that we can share soon some options.
+
+This guide is a starting point, and we'll absolutely improve it on an ongoing basis. We've managed to go ~4 years without a substantial guide like this - sometimes to the detriment of contributors - and would love to keep improving this guide, and the project, for the best of the community.
+
+### When may we not change things?
+
+Generating code which others depend on, which is based on something as complex as OpenAPI is fraught with many edge cases, and we prefer to leave things as they are if there is a reasonable workaround.
+
+We'll try to avoid adding too much noise into generated code, or introduce breaking changes (as per SemVer). See also "Backwards compatibility" in the README.
+
+### Raising a bug
+
+If you believe you have encountered a bug, please raise an issue.
+
+> [!TIP]
+> Please follow the [minimal reproductions](#minimal-reproductions) documentation to improve our ability to support triaging
+
+This may get converted into a feature request if we don't deem it a bug, but a missing feature.
+
+### Asking a question
+
+We'd prefer that questions about "how do I use (this feature)?" or "what do the community think about ...?" get asked using [GitHub Discussions](https://github.com/deepmap/oapi-codegen/discussions) which allow the community to answer them more easily.
+
+### Making changes that tweak generated code
+
+If you are making changes to the codebase that affects the code that gets generated, you will need to make sure that you have regenerated any generated test cases in the codebase using `make generate`.
+
+These generated test cases and examples provide a means to not only validate the functionality, but as they are checked in to source code, allow us to see if there are any subtle issues or breaking changes.
+
+> [!NOTE]
+> Significant changes to generated code are likely to be merged, especially in cases where there would be a breaking change that all consumers would have to respond to i.e. renaming a function or changing the function signature.
+>
+> However, if we can make this an opt-in feature (using the `output-options` configuration object) then that would be our preference.
+
+### Feature enhancements
+
+It's great that you would like to improve `oapi-codegen` and add new futures.
+
+We would prefer there be an issue raised for a feature request first, especially if it may be a duplicate of existing requests. However, sometimes that isn't possible - or takes longer than the code changes required - so it can be excused.
+
+Features that amend the way existing codegen works should - ideally - be behind an opt-in feature flag using the `output-options` configuration object.
+
+### Minimal reproductions
+
+> [!TIP]
+> The minimal reproductions for bugs may get taken into the codebase (licensed under `Apache-2.0`) as a test-case for future regression testing
+
+When raising a bug report, or asking a question about functionality, it's super helpful if you can share:
+
+- The version of `oapi-codegen` you're using
+ - You _may_ get asked to update to a later - or latest - version, to see if the issue persists
+- The YAML configuration file you're using
+- The OpenAPI spec you're using
+ - However, we would prefer it only be the _absolute minimum_ specification, to limit the noise while trying to debug the issue, and to reduce information exposure from internal API development
+- What problem you're seeing
+- What the expected behaviour is
+- What version of Go you're using
+
+> [!CAUTION]
+> When sharing a minimal reproduction, please be aware of sharing any internal information about the APIs you're developing, or any sensitive Intellectual Property.
+
+### Before you raise a PR
+
+> [!NOTE]
+> Please raise PRs from a branch that isn't the `master` or `main` branch on your repo. This generally means that as maintainers, we can't push changes to the branch directly.
+
+Before you send the PR, please run the following commands locally:
+
+```sh
+make tidy
+make test
+make generate
+make lint
+```
+
+It is important to use the `make` tasks due to the way we're (ab)using the Go module system to split the project into multiple modules to reduce our dependency bloat in the main module.
+
+These are also run in GitHub Actions, across a number of Go releases.
+
+It's recommended to raise a draft PR first, so you can get feedback on the PR from GitHub, and review your own changes, before getting the attention of a maintainer.
+
+### "Should I @-mention the maintainers on an issue"
+
+Please try to avoid pinging the maintainers in an issue, Pull Request, or discussion.
+
+> [!NOTE]
+> We're actively considering what needs to change to make `oapi-codegen` more sustainable, and hope that we can share soon some options.
+
+The project is run on a volunteer basis, and as such, tagging us on issues - especially if you've just raised them - is largely unhelpful. We monitor the issues and work to triage them as best we can with the time we have allocated for it.
diff --git a/Makefile b/Makefile
index 63e8039e3..e7c6f6357 100644
--- a/Makefile
+++ b/Makefile
@@ -6,27 +6,47 @@ help:
@echo "Targets:"
@echo " generate: regenerate all generated files"
@echo " test: run all tests"
- @echo " gin_example generate gin example server code"
@echo " tidy tidy go mod"
+ @echo " lint lint the project"
$(GOBIN)/golangci-lint:
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOBIN) v1.55.2
+ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOBIN) v1.59.0
.PHONY: tools
tools: $(GOBIN)/golangci-lint
lint: tools
- git ls-files go.mod '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && $(GOBIN)/golangci-lint run ./...'
+ # run the root module explicitly, to prevent recursive calls by re-invoking `make ...` top-level
+ $(GOBIN)/golangci-lint run ./...
+ # then, for all child modules, use a module-managed `Makefile`
+ git ls-files '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && env GOBIN=$(GOBIN) make lint'
lint-ci: tools
- git ls-files go.mod '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && $(GOBIN)/golangci-lint run ./... --out-format=github-actions --timeout=5m'
+ # for the root module, explicitly run the step, to prevent recursive calls
+ $(GOBIN)/golangci-lint run ./... --out-format=colored-line-number --timeout=5m
+ # then, for all child modules, use a module-managed `Makefile`
+ git ls-files '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && env GOBIN=$(GOBIN) make lint-ci'
generate:
- git ls-files go.mod '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && go generate ./...'
+ # for the root module, explicitly run the step, to prevent recursive calls
+ go generate ./...
+ # then, for all child modules, use a module-managed `Makefile`
+ git ls-files '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && make generate'
test:
- git ls-files go.mod '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && go test -cover ./...'
+ # for the root module, explicitly run the step, to prevent recursive calls
+ go test -cover ./...
+ # then, for all child modules, use a module-managed `Makefile`
+ git ls-files '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && make test'
tidy:
- @echo "tidy..."
- git ls-files go.mod '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && go mod tidy'
+ # for the root module, explicitly run the step, to prevent recursive calls
+ go mod tidy
+ # then, for all child modules, use a module-managed `Makefile`
+ git ls-files '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && make tidy'
+
+tidy-ci:
+ # for the root module, explicitly run the step, to prevent recursive calls
+ tidied -verbose
+ # then, for all child modules, use a module-managed `Makefile`
+ git ls-files '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && make tidy-ci'
diff --git a/README.md b/README.md
index aaa94da28..7ef5b8dff 100644
--- a/README.md
+++ b/README.md
@@ -1,992 +1,3913 @@
-## OpenAPI Client and Server Code Generator
+# `oapi-codegen`
-⚠️ This README may be for the latest development version, which may contain
-unreleased changes. Please ensure you're looking at the README for the latest
-release version.
+`oapi-codegen` is a command-line tool and library to convert OpenAPI specifications to Go code, be it [server-side implementations](#generating-server-side-boilerplate), [API clients](#generating-api-clients), or simply [HTTP models](#generating-api-models).
-This package contains a set of utilities for generating Go boilerplate code for
-services based on
-[OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md)
-API definitions. When working with services, it's important to have an API
-contract which servers and clients both implement to minimize the chances of
-incompatibilities. It's tedious to generate Go models which precisely correspond to
-OpenAPI specifications, so let our code generator do that work for you, so that
-you can focus on implementing the business logic for your service.
+Using `oapi-codegen` allows you to reduce the boilerplate required to create or integrate with services based on [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md), and instead focus on writing your business logic, and working on the real value-add for your organisation.
-We have chosen to focus on [Echo](https://github.com/labstack/echo) as
-our default HTTP routing engine, due to its speed and simplicity for the generated
-stubs. [Chi](https://github.com/go-chi/chi), [Gin](https://github.com/gin-gonic/gin),
-[gorilla/mux](https://github.com/gorilla/mux), [Fiber](https://github.com/gofiber/fiber), and
-[Iris](https://github.com/kataras/iris) have also been added by contributors as additional routers.
-We chose Echo because the `Context` object is a mockable interface, and it allows for some advanced
-testing.
+With `oapi-codegen`, there are a few [Key Design Decisions](#key-design-decisions) we've made, including:
-This package tries to be too simple rather than too generic, so we've made some
-design decisions in favor of simplicity, knowing that we can't generate strongly
-typed Go code for all possible OpenAPI Schemas. If there is a way to accomplish
-something via utility code or reflection, it's probably a better approach than
-code generation, which is fragile due to the very dynamic nature of OpenAPI and
-the very static nature of Go.
+- idiomatic Go, where possible
+- fairly simple generated code, erring on the side of duplicate code over nicely refactored code
+- supporting as much of OpenAPI 3.x as is possible, alongside Go's type system
-## Contributing
+`oapi-codegen` is one part of a wider ecosystem, which can be found described in further detail in the [oapi-codegen organisation on GitHub](https://github.com/oapi-codegen).
-I would like to pre-emptively extend my gratitude to anyone who takes the time
-to improve this project.
+⚠️ This README may be for the latest development version, which may contain unreleased changes. Please ensure you're looking at the README for the latest release version.
-Oapi-codegen is being actively maintained, however the two people who do so
-are very busy, and can only set aside time for this project every once in a while,
-so our release cadence is slow and conservative.
+## Action Required: The repository for this project has changed
-Generating code which others depend on, which is based on something as complex
-as OpenAPI is fraught with many edge cases, and we prefer to leave things as
-they are if there is a reasonable workaround.
+As announced in [May 2024](https://github.com/oapi-codegen/oapi-codegen/discussions/1605),
+we have moved the project from the deepmap organization to our own organization, and you will need to update your
+import paths to pull updates past this point. You need to do a recursive search/replace from
+`github.com/oapi-codegen/oapi-codegen/v2` to `github.com/oapi-codegen/oapi-codegen/v2`.
-If you do find a case where oapi-codegen is broken, and would like to submit a PR,
-we are very grateful, and will happily look at it.
+`oapi-codegen` moved to its new home with the version tag `v2.3.0`. If you
+are installing a version prior to `v2.3.0`, please use `github.com/deepmap/oapi-codegen/v2',
+otherwise, use `github.com/oapi-codegen/oapi-codegen/v2`
-Since most commits affect generated code, before sending your PR, please
-ensure that all boilerplate has been regenerated. You can do this from the top level
-of the repository by running:
+## Install
- make generate
+It is recommended to follow [the `tools.go` pattern](https://www.jvt.me/posts/2022/06/15/go-tools-dependency-management/) for managing the dependency of `oapi-codegen` alongside your core application.
-I realize that our code isn't entirely idiomatic with respect to comments, and
-variable naming and initialisms, especially the generated code, but I'm reluctant
-to merge PR's which change this, due to the breakage they will cause for others. If
-you rename anything under `/pkg` or change the names of variables in generated
-code, you will break other people's code. It's safe to rename internal names.
+This would give you a `tools/tools.go`:
-## Overview
+```go
+//go:build tools
+// +build tools
+
+package main
-We're going to use the OpenAPI example of the
-[Expanded Petstore](https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/petstore-expanded.yaml)
-in the descriptions below, please have a look at it.
+import (
+ _ "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen"
+)
+```
-In order to create a Go server to serve this exact schema, you would have to
-write a lot of boilerplate code to perform all the marshaling and unmarshaling
-into objects which match the OpenAPI 3.0 definition. The code generator in this
-directory does a lot of that for you. You would run it like so:
+Then, each invocation of `oapi-codegen` would be used like so:
- go install github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@latest
- oapi-codegen -package petstore petstore-expanded.yaml > petstore.gen.go
+```go
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../../api.yaml
+```
-Let's go through that `petstore.gen.go` file to show you everything which was
-generated.
+Alternatively, you can install it as a binary with:
-## Generated Server Boilerplate
+```sh
+$ go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest
+$ oapi-codegen -version
+```
-The `/components/schemas` section in OpenAPI defines reusable objects, so Go
-types are generated for these. The Pet Store example defines `Error`, `Pet`,
-`Pets` and `NewPet`, so we do the same in Go:
+Which then means you can invoke it like so:
```go
-// Error defines model for Error.
-type Error struct {
- // Error code
- Code int32 `json:"code"`
+//go:generate oapi-codegen --config=config.yaml ../../api.yaml
+```
- // Error message
- Message string `json:"message"`
-}
+### Pinning to commits
-// NewPet defines model for NewPet.
-type NewPet struct {
- // Name of the pet
- Name string `json:"name"`
+While the project does not ([yet](https://github.com/deepmap/oapi-codegen/issues/1519)) have a defined release cadence, there may be cases where you want to pull in yet-unreleased changes to your codebase.
- // Type of the pet
- Tag *string `json:"tag,omitempty"`
-}
+Therefore, you may want to pin your dependency on `oapi-codegen` to a given commit hash, rather than a tag.
-// Pet defines model for Pet.
-type Pet struct {
- // Unique id of the pet
- Id int64 `json:"id"`
+This is **officially recommended** for consumers of `oapi-codegen`, who want features/bug fixes that haven't yet been released.
- // Name of the pet
- Name string `json:"name"`
+We aim to keep the default branch ready-to-release so you should be able to safely pin.
- // Type of the pet
- Tag *string `json:"tag,omitempty"`
-}
+To do so, you can run:
-// Type definition for component schema "Pets"
-type Pets []Pet
+```sh
+# pin to the latest version on the default branch
+$ go get github.com/oapi-codegen/oapi-codegen/v2@main
+# alternatively, to a commit hash i.e. https://github.com/deepmap/oapi-codegen/commit/71e916c59688a6379b5774dfe5904ec222b9a537
+$ go get github.com/oapi-codegen/oapi-codegen/v2@71e916c59688a6379b5774dfe5904ec222b9a537
```
-It's best to define objects under `/components` field in the schema, since
-those will be turned into named Go types. If you use inline types in your
-handler definitions, we will generate inline, anonymous Go types, but those
-are more tedious to deal with since you will have to redeclare them at every
-point of use.
+This will then make a change such as:
-For each element in the `paths` map in OpenAPI, we will generate a Go handler
-function in an interface object. Here is the generated Go interface for our
-Echo server.
-
-```go
-type ServerInterface interface {
- // (GET /pets)
- FindPets(ctx echo.Context, params FindPetsParams) error
- // (POST /pets)
- AddPet(ctx echo.Context) error
- // (DELETE /pets/{id})
- DeletePet(ctx echo.Context, id int64) error
- // (GET /pets/{id})
- FindPetById(ctx echo.Context, id int64) error
-}
+```diff
+diff --git go.mod go.mod
+index 44f29a4..436a780 100644
+--- go.mod
++++ go.mod
+@@ -2,21 +2,20 @@
+-require github.com/oapi-codegen/oapi-codegen/v2 v2.1.0
++require github.com/oapi-codegen/oapi-codegen/v2 v2.1.1-0.20240331212514-80f0b978ef16
```
-These are the functions which you will implement yourself in order to create
-a server conforming to the API specification. Normally, all the arguments and
-parameters are stored on the `echo.Context` in handlers, so we do the tedious
-work of unmarshaling the JSON automatically, simply passing values into
-your handlers.
+## Usage
-Notice that `FindPetById` takes a parameter `id int64`. All path arguments
-will be passed as arguments to your function, since they are mandatory.
+`oapi-codegen` is largely configured using a YAML configuration file, to simplify the number of flags that users need to remember, and to make reading the `go:generate` command less daunting.
-Remaining arguments can be passed in headers, query arguments or cookies. Those
-will be written to a `params` object. Look at the `FindPets` function above, it
-takes as input `FindPetsParams`, which is defined as follows:
+For full details of what is supported, it's worth checking out [the GoDoc for `codegen.Configuration`](https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen#Configuration).
-```go
-// Parameters object for FindPets
-type FindPetsParams struct {
- Tags *[]string `json:"tags,omitempty"`
- Limit *int32 `json:"limit,omitempty"`
-}
+We also have [a JSON Schema](configuration-schema.json) that can be used by IDEs/editors with the Language Server Protocol (LSP) to perform intelligent suggestions, i.e.:
+
+```yaml
+# yaml-language-server: $schema=https://raw.githubusercontent.com/deepmap/oapi-codegen/HEAD/configuration-schema.json
+package: api
+# ...
```
-The HTTP query parameter `limit` turns into a Go field named `Limit`. It is
-passed by pointer, since it is an optional parameter. If the parameter is
-specified, the pointer will be non-`nil`, and you can read its value.
+### Backwards compatibility
-If you changed the OpenAPI specification to make the parameter required, the
-`FindPetsParams` structure will contain the type by value:
+Although we strive to retain backwards compatibility - as a project that's using a stable API per SemVer - there are sometimes opportunities we must take to fix a bug that could cause a breaking change for [people relying upon the behaviour](https://xkcd.com/1172/).
-```go
-type FindPetsParams struct {
- Tags *[]string `json:"tags,omitempty"`
- Limit int32 `json:"limit"`
-}
-```
+In this case, we will expose a [compatibility option](https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen#CompatibilityOptions) to restore old behaviour.
-### Registering handlers
+## Features
-There are a few ways of registering your http handler based on the type of server generated i.e. `-generate server` or `-generate chi-server`
+At a high level, `oapi-codegen` supports:
-Echo
+- Generating server-side boilerplate for [a number of servers](#supported-servers) ([docs](#generating-server-side-boilerplate))
+- Generating client API boilerplate ([docs](#generating-api-clients))
+- Generating the types ([docs](#generating-api-models))
+- Splitting large OpenAPI specs across multiple packages([docs](#import-mapping))
+ - This is also known as "Import Mapping" or "external references" across our documentation / discussion in GitHub issues
-Code generated using `-generate server`.
+## What does it look like?
-The usage of `Echo` is out of scope of this doc, but once you have an
-echo instance, we generate a utility function to help you associate your handlers
-with this autogenerated code. For the pet store, it looks like this:
+Below we can see a trimmed down example taken from the OpenAPI Petstore [example](examples/petstore-expanded/stdhttp/api/petstore.gen.go):
```go
-func RegisterHandlers(router codegen.EchoRouter, si ServerInterface) {
- wrapper := ServerInterfaceWrapper{
- Handler: si,
- }
- router.GET("/pets", wrapper.FindPets)
- router.POST("/pets", wrapper.AddPet)
- router.DELETE("/pets/:id", wrapper.DeletePet)
- router.GET("/pets/:id", wrapper.FindPetById)
-}
-```
+// generated code
-The wrapper functions referenced above contain generated code which pulls
-parameters off the `Echo` request context, and unmarshals them into Go objects.
+type ServerInterface interface {
+ // ...
+ // Returns all pets
+ // (GET /pets)
+ FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams)
+ // ...
+}
-You would register the generated handlers as follows:
+// FindPets operation middleware
+func (siw *ServerInterfaceWrapper) FindPets(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
-```go
-func SetupHandler() {
- var myApi PetStoreImpl // This implements the pet store interface
- e := echo.New()
- petstore.RegisterHandlers(e, &myApi)
- ...
-}
-```
+ var err error
-
+ // Parameter object where we will unmarshal all parameters from the context
+ var params FindPetsParams
-Chi
+ // ------------- Optional query parameter "tags" -------------
-Code generated using `-generate chi-server`.
+ err = runtime.BindQueryParameter("form", true, false, "tags", r.URL.Query(), ¶ms.Tags)
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "tags", Err: err})
+ return
+ }
-```go
-type PetStoreImpl struct {}
-func (*PetStoreImpl) GetPets(w http.ResponseWriter, r *http.Request) {
- // Implement me
-}
+ // ------------- Optional query parameter "limit" -------------
-func SetupHandler() {
- var myApi PetStoreImpl
+ 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
+ }
- r := chi.NewRouter()
- r.Mount("/", Handler(&myApi))
-}
-```
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.FindPets(w, r, params)
+ }))
-
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
-Gin
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
-Code generated using `-generate gin`.
+// HandlerWithOptions creates http.Handler with additional options
+func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.Handler {
+ m := options.BaseRouter
-The usage of `gin` is out of scope of this doc, but once you have an
-gin instance, we generate a utility function to help you associate your handlers
-with this autogenerated code. For the pet store, it looks like this:
+ 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)
+ }
+ }
-```go
-// RegisterHandlersWithOptions creates http.Handler with additional options
-func RegisterHandlersWithOptions(router *gin.Engine, si ServerInterface, options GinServerOptions) *gin.Engine {
wrapper := ServerInterfaceWrapper{
Handler: si,
HandlerMiddlewares: options.Middlewares,
+ ErrorHandlerFunc: options.ErrorHandlerFunc,
}
- router.GET(options.BaseURL+"/pets", wrapper.FindPets)
- router.POST(options.BaseURL+"/pets", wrapper.AddPet)
- router.DELETE(options.BaseURL+"/pets/:id", wrapper.DeletePet)
- router.GET(options.BaseURL+"/pets/:id", wrapper.FindPetByID)
- return router
+ m.HandleFunc("GET "+options.BaseURL+"/pets", wrapper.FindPets)
+
+ return m
}
```
+Then, in your own code, you implement the underlying logic for the `FindPets` implementation:
+
```go
-import (
- "github.com/gin-gonic/gin"
- "github.com/deepmap/oapi-codegen/examples/petstore-expanded/gin/api"
- middleware "github.com/oapi-codegen/gin-middleware"
-)
+type PetStore struct {
+ Pets map[int64]Pet
+ NextId int64
+ Lock sync.Mutex
+}
+
+// Make sure we conform to ServerInterface
-type PetStoreImpl struct {}
-func (*PetStoreImpl) GetPets(w http.ResponseWriter, r *http.Request) {
- // Implement me
+var _ ServerInterface = (*PetStore)(nil)
+
+func NewPetStore() *PetStore {
+ return &PetStore{
+ Pets: make(map[int64]Pet),
+ NextId: 1000,
+ }
}
-func SetupHandler() {
- var myApi PetStoreImpl
+// FindPets implements all the handlers in the ServerInterface
+func (p *PetStore) FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams) {
+ p.Lock.Lock()
+ defer p.Lock.Unlock()
+
+ var result []Pet
+
+ for _, pet := range p.Pets {
+ if params.Tags != nil {
+ // If we have tags, filter pets by tag
+ for _, t := range *params.Tags {
+ if pet.Tag != nil && (*pet.Tag == t) {
+ result = append(result, pet)
+ }
+ }
+ } else {
+ // Add all pets if we're not filtering
+ result = append(result, pet)
+ }
+
+ if params.Limit != nil {
+ l := int(*params.Limit)
+ if len(result) >= l {
+ // We're at the limit
+ break
+ }
+ }
+ }
- r := gin.Default()
- r.Use(middleware.OapiRequestValidator(swagger))
- r = api.RegisterHandlers(r, petStore)
+ w.WriteHeader(http.StatusOK)
+ _ = json.NewEncoder(w).Encode(result)
}
```
-
+As we can see, `oapi-codegen` simplifies some of the boilerplate by taking parameters out of the request and instead allows us to focus on the implementation.
-net/http
+You'll note that there's still a bit more marshaling of request/response data, which is further reduced by using the [Strict server](#strict-server) functionality.
-[Chi](https://github.com/go-chi/chi) is 100% compatible with `net/http` allowing the following with code generated using `-generate chi-server`.
+
+When using the strict server, you'll have the following generated code:
```go
-type PetStoreImpl struct {}
-func (*PetStoreImpl) GetPets(w http.ResponseWriter, r *http.Request) {
- // Implement me
+// StrictServerInterface represents all server handlers.
+type StrictServerInterface interface {
+ // ...
+ // Returns all pets
+ // (GET /pets)
+ FindPets(ctx context.Context, request FindPetsRequestObject) (FindPetsResponseObject, error)
+ // ...
}
-func SetupHandler() {
- var myApi PetStoreImpl
-
- http.Handle("/", Handler(&myApi))
+func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface {
+ return &strictHandler{ssi: ssi, middlewares: middlewares, options: options}
}
-```
-Alternatively, [Gorilla](https://github.com/gorilla/mux) is also 100% compatible with `net/http` and can be generated with `-generate gorilla`.
+// FindPets operation middleware
+func (sh *strictHandler) FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams) {
+ var request FindPetsRequestObject
+
+ request.Params = params
-
+ handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
+ return sh.ssi.FindPets(ctx, request.(FindPetsRequestObject))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "FindPets")
+ }
-Iris
+ response, err := handler(r.Context(), w, r, request)
-Code generated using `-generate iris`.
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(FindPetsResponseObject); ok {
+ if err := validResponse.VisitFindPetsResponse(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))
+ }
+}
+```
-The usage of `iris` is out of scope of this doc, but once you have an
-gin instance, we generate a utility function to help you associate your handlers
-with this autogenerated code. For the pet store, it looks like this:
+Then, in your own code, you implement the underlying logic for the `FindPets` implementation:
```go
-// RegisterHandlersWithOptions creates http.Handler with additional options
-func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, options IrisServerOptions) {
+// Make sure we conform to StrictServerInterface
- wrapper := ServerInterfaceWrapper{
- Handler: si,
+var _ StrictServerInterface = (*PetStore)(nil)
+
+func NewPetStore() *PetStore {
+ return &PetStore{
+ Pets: make(map[int64]Pet),
+ NextId: 1000,
}
+}
- router.Get(options.BaseURL+"/pets", wrapper.FindPets)
- router.Post(options.BaseURL+"/pets", wrapper.AddPet)
- router.Delete(options.BaseURL+"/pets/:id", wrapper.DeletePet)
- router.Get(options.BaseURL+"/pets/:id", wrapper.FindPetByID)
+// FindPets implements all the handlers in the ServerInterface
+func (p *PetStore) FindPets(ctx context.Context, request FindPetsRequestObject) (FindPetsResponseObject, error) {
+ p.Lock.Lock()
+ defer p.Lock.Unlock()
+
+ var result []Pet
+
+ for _, pet := range p.Pets {
+ if request.Params.Tags != nil {
+ // If we have tags, filter pets by tag
+ for _, t := range *request.Params.Tags {
+ if pet.Tag != nil && (*pet.Tag == t) {
+ result = append(result, pet)
+ }
+ }
+ } else {
+ // Add all pets if we're not filtering
+ result = append(result, pet)
+ }
+
+ if request.Params.Limit != nil {
+ l := int(*request.Params.Limit)
+ if len(result) >= l {
+ // We're at the limit
+ break
+ }
+ }
+ }
- router.Build()
+ return FindPets200JSONResponse(result), nil
}
```
-```go
-import (
- "github.com/kataras/iris/v12"
- "github.com/deepmap/oapi-codegen/examples/petstore-expanded/iris/api"
- middleware "github.com/oapi-codegen/iris-middleware"
-)
-```
+We can see that this provides the best means to focus on the implementation of the business logic within the endpoint, rather than (un)marshalling types to and from JSON, or wrangling cookies or headers.
-The wrapper functions referenced above contain generated code which pulls
-parameters off the `Iris` request context, and unmarshals them into Go objects.
+## Key design decisions
-You would register the generated handlers as follows:
+- Produce an interface that can be satisfied by your implementation, with reduced boilerplate
+- Bulk processing and parsing of OpenAPI document in Go
+- Resulting output is using Go's `text/template`s, which are user-overridable
+- Attempts to produce Idiomatic Go
+- Single-file output
+- Support multiple OpenAPI files by having a package-per-OpenAPI file
+- Support of OpenAPI 3.0
+ - OpenAPI 3.1 support is [awaiting upstream support](https://github.com/deepmap/oapi-codegen/issues/373)
+ - Note that this does not include OpenAPI 2.0 (aka Swagger)
+- Extract parameters from requests, to reduce work required by your implementation
+- Implicit `additionalProperties` are ignored by default ([more details](#additional-properties-additionalproperties))
+- Prune unused types by default
-```go
-func SetupHandler() {
- var myApi PetStoreImpl
+## Generating server-side boilerplate
- i := iris.Default()
- i.Use(middleware.OapiRequestValidator(swagger))
- api.RegisterHandlers(r, &myApi)
-}
-```
+`oapi-codegen` shines by making it fairly straightforward (note that this is a purposeful choice of wording here - we want to avoid words like "easy") to generate the server-side boilerplate for a backend API.
-
+Below you can find the supported servers, and more information about how to implement a server using them.
-#### Strict server generation
+To provide you a fully Test Driven Development style test harness to confirm you are following the specification, you could use a tool such as [openapi.tanna.dev/go/validator](https://openapi.tanna.dev/go/validator/), or craft your own.
-oapi-codegen also supports generating RPC inspired strict server, that will parse request bodies and encode responses.
-The main points of this code is to automate some parsing, abstract user code from server specific code,
-and also to force user code to comply with the schema.
-It supports binding of `application/json` and `application/x-www-form-urlencoded` to a struct, for `multipart` requests
-it generates a `multipart.Reader`, which can be used to either manually iterating over parts or using `runtime.BindMultipart`
-function to bind the form to a struct. All other content types are represented by a `io.Reader` interface.
+### Supported Servers
-To form a response simply return one of the generated structs with corresponding status code and content type. For example,
-to return a status code 200 JSON response for a AddPet use the `AddPet200JSONResponse` struct which will set the correct
-Content-Type header, status code and will marshal the response data. You can also return an error, that will
-cause an `Internal Server Error` response.
+Right now, we support the following servers, and are supportive of adding new servers, too!
-Short example:
+
-```go
-type PetStoreImpl struct {}
-func (*PetStoreImpl) GetPets(ctx context.Context, request GetPetsRequestObject) (GetPetsResponseObject, error) {
- var result []Pet
- // Implement me
- return GetPets200JSONResponse(result), nil
-}
-```
+
+
+Server
+
+
+generate
flag to enable code generation
+
+
+Example usage
+
+
-For a complete example see [`examples/petstore-expanded/strict`](https://github.com/deepmap/oapi-codegen/tree/master/examples/petstore-expanded/strict).
+
+
-Code is generated with a configuration flag `generate: strict-server: true` along with any other server (echo, chi, gin and gorilla are supported).
-The generated strict wrapper can then be used as an implementation for `ServerInterface`. Setup example:
+[Chi](https://github.com/go-chi/chi)
-```go
-func SetupHandler() {
- var myApi PetStoreImpl
- myStrictApiHandler := api.NewStrictHandler(myApi, nil)
- e := echo.New()
- petstore.RegisterHandlers(e, &myStrictApiHandler)
-}
+
+
+chi-server
+
+
+
+
+For a Chi server, you will want a configuration file such as:
+
+```yaml
+# yaml-language-server: ...
+package: api
+generate:
+ chi-server: true
+ models: true
+output: gen.go
```
-Strict server also has its own middlewares. It can access to both request and response structs,
-as well as raw request\response data. It can be used for logging the parsed request\response objects, transforming go errors into response structs,
-authorization, etc. Note that middlewares are server-specific.
+To implement this, check out [the Chi docs](#impl-chi).
-#### Additional Properties in type definitions
+
+
-[OpenAPI Schemas](https://swagger.io/specification/#schemaObject) implicitly
-accept `additionalProperties`, meaning that any fields provided, but not explicitly
-defined via properties on the schema are accepted as input, and propagated. When
-unspecified, the `additionalProperties` field is assumed to be `true`.
+
+
-Additional properties are tricky to support in Go with typing, and require
-lots of boilerplate code, so in this library, we assume that `additionalProperties`
-defaults to `false` and we don't generate this boilerplate. If you would like
-an object to accept `additionalProperties`, specify a schema for `additionalProperties`.
+[Echo](https://github.com/labstack/echo)
-Say we declared `NewPet` above like so:
+
+
+echo-server
+
+
+
+For an Echo server, you will want a configuration file such as:
```yaml
-NewPet:
- required:
- - name
- properties:
- name:
- type: string
- tag:
- type: string
- additionalProperties:
- type: string
+# yaml-language-server: ...
+package: api
+generate:
+ echo-server: true
+ models: true
+output: gen.go
```
-The Go code for `NewPet` would now look like this:
+To implement this, check out [the Echo docs](#impl-echo).
-```go
-// NewPet defines model for NewPet.
-type NewPet struct {
- Name string `json:"name"`
- Tag *string `json:"tag,omitempty"`
- AdditionalProperties map[string]string `json:"-"`
-}
-```
+
+
-The additionalProperties, of type `string` become `map[string]string`, which maps
-field names to instances of the `additionalProperties` schema.
+
+
-```go
-// Getter for additional properties for NewPet. Returns the specified
-// element and whether it was found
-func (a NewPet) Get(fieldName string) (value string, found bool) {...}
+[Fiber](https://github.com/gofiber/fiber)
-// Setter for additional properties for NewPet
-func (a *NewPet) Set(fieldName string, value string) {...}
+
+
+fiber-server
+
-// Override default JSON handling for NewPet to handle additionalProperties
-func (a *NewPet) UnmarshalJSON(b []byte) error {...}
+
-// Override default JSON handling for NewPet to handle additionalProperties
-func (a NewPet) MarshalJSON() ([]byte, error) {...}w
+For a Fiber server, you will want a configuration file such as:
+
+```yaml
+# yaml-language-server: ...
+package: api
+generate:
+ fiber-server: true
+ models: true
+output: gen.go
```
-There are many special cases for `additionalProperties`, such as having to
-define types for inner fields which themselves support additionalProperties, and
-all of them are tested via the [`internal/test/components`](https://github.com/deepmap/oapi-codegen/tree/master/internal/test/components) schemas and tests. Please
-look through those tests for more usage examples.
+To implement this, check out [the Fiber docs](#impl-fiber).
+
+
+
-#### oneOf/anyOf/allOf support
-- `oneOf` and `anyOf` are implemented using delayed parsing with the help of `json.RawMessage`.
- The following schema will result in a type that has methods such as `AsCat`, `AsDog`, `FromCat`, `FromDog`, `MergeCat`, `MergeDog`. If the schema also includes a discriminator the generated code will also have methods such as `Discriminator`, `ValueByDiscriminator` and will force discriminator value in `From` methods.
+
+
+
+[Gin](https://github.com/gin-gonic/gin)
+
+
+
+gin-server
+
+
+
+For a Gin server, you will want a configuration file such as:
```yaml
-schema:
- oneOf:
- - $ref: '#/components/schemas/Cat'
- - $ref: '#/components/schemas/Dog'
+# yaml-language-server: ...
+package: api
+generate:
+ gin-server: true
+ models: true
+output: gen.go
```
-- `allOf` is supported, by taking the union of all the fields in all the
- component schemas. This is the most useful of these operations, and is
- commonly used to merge objects with an identifier, as in the
- `petstore-expanded` example.
+To implement this, check out [the Gin docs](#impl-gin).
-## Generated Client Boilerplate
+
-Once your server is up and running, you probably want to make requests to it. If
-you're going to do those requests from your Go code, we also generate a client
-which is conformant with your schema to help in marshaling objects to JSON. It
-uses the same types and similar function signatures to your request handlers.
+
-The interface for the pet store looks like this:
+
+
-```go
-// The interface specification for the client above.
-type ClientInterface interface {
+[gorilla/mux](https://github.com/gorilla/mux)
- // FindPets request
- FindPets(ctx context.Context, params *FindPetsParams, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+
+gorilla-server
+
- // AddPet request with JSON body
- AddPet(ctx context.Context, body NewPet, reqEditors ...RequestEditorFn) (*http.Response, error)
+
- // DeletePet request
- DeletePet(ctx context.Context, id int64, reqEditors ...RequestEditorFn) (*http.Response, error)
+For a gorilla/mux server, you will want a configuration file such as:
- // FindPetById request
- FindPetById(ctx context.Context, id int64, reqEditors ...RequestEditorFn) (*http.Response, error)
-}
+```yaml
+# yaml-language-server: ...
+package: api
+generate:
+ gorilla-server: true
+ models: true
+output: gen.go
```
-A Client object which implements the above interface is also generated:
-
-```go
-// Client which conforms to the OpenAPI3 specification for this service.
-type Client struct {
- // The endpoint of the server conforming to this interface, with scheme,
- // https://api.deepmap.com for example.
- Server string
+To implement this, check out [the gorilla/mux docs](#impl-gorillamux).
- // HTTP client with any customized settings, such as certificate chains.
- Client http.Client
+
+
- // A callback for modifying requests which are generated before sending over
- // the network.
- RequestEditors []func(ctx context.Context, req *http.Request) error
-}
-```
+
+
-Each operation in your OpenAPI spec will result in a client function which
-takes the same arguments. It's difficult to handle any arbitrary body that
-Swagger supports, so we've done some special casing for bodies, and you may get
-more than one function for an operation with a request body.
+[Iris](https://github.com/kataras/iris)
-1. If you have more than one request body type, meaning more than one media
- type, you will have a generic handler of this form:
+
+
+iris-server
+
- AddPet(ctx context.Context, contentType string, body io.Reader)
+
-2. If you have only a JSON request body, you will get:
+For a Iris server, you will want a configuration file such as:
- AddPet(ctx context.Context, body NewPet)
+```yaml
+# yaml-language-server: ...
+package: api
+generate:
+ iris-server: true
+ models: true
+output: gen.go
+```
-3. If you have multiple request body types, which include a JSON type you will
- get two functions. We've chosen to give the JSON version a shorter name, as
- we work with JSON and don't want to wear out our keyboards.
+To implement this, check out [the Iris docs](#impl-iris).
- AddPet(ctx context.Context, body NewPet)
- AddPetWithBody(ctx context.Context, contentType string, body io.Reader)
+
+
-The Client object above is fairly flexible, since you can pass in your own
-`http.Client` and a request editing callback. You can use that callback to add
-headers. In our middleware stack, we annotate the context with additional
-information such as the request ID and function tracing information, and we
-use the callback to propagate that information into the request headers. Still, we
-can't foresee all possible usages, so those functions call through to helper
-functions which create requests. In the case of the pet store, we have:
+
+
-```go
-// Request generator for FindPets
-func NewFindPetsRequest(server string, params *FindPetsParams) (*http.Request, error) {...}
+[1.22+ `net/http`](https://pkg.go.dev/net/http)
-// Request generator for AddPet with JSON body
-func NewAddPetRequest(server string, body NewPet) (*http.Request, error) {...}
+
+
+std-http-server
+
-// Request generator for AddPet with non-JSON body
-func NewAddPetRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) {...}
+
-// Request generator for DeletePet
-func NewDeletePetRequest(server string, id int64) (*http.Request, error) {...}
+To use purely `net/http` (for Go 1.22+), you will want a configuration file such as:
-// Request generator for FindPetById
-func NewFindPetByIdRequest(server string, id int64) (*http.Request, error) {...}
+```yaml
+# yaml-language-server: ...
+package: api
+generate:
+ std-http-server: true
+ models: true
+output: gen.go
```
-You can call these functions to build an `http.Request` from Go objects, which
-will correspond to your request schema. They map one-to-one to the functions on
-the client, except that we always generate the generic non-JSON body handler.
+To implement this, check out [the Go 1.22+ `net/http` docs](#impl-stdhttp).
+
+
+
+
+
-There are some caveats to using this code.
+### Go 1.22+ `net/http`
+
-- exploded, form style query arguments, which are the default argument format
- in OpenAPI 3.0 are undecidable. Say that I have two objects, one composed of
- the fields `(name=bob, id=5)` and another which has `(name=shoe, color=brown)`.
- The first parameter is named `person` and the second is named `item`. The
- default marshaling style for query args would result in
- `/path/?name=bob,id=5&name=shoe,color=brown`. In order to tell what belongs
- to which object, we'd have to look at all the parameters and try to deduce it,
- but we're lazy, so we didn't. Don't use exploded form style arguments if
- you're passing around objects which have similar field names. If you
- used unexploded form parameters, you'd have
- `/path/?person=name,bob,id,5&item=name,shoe,color,brown`, which an be
- parsed unambiguously.
+As of Go 1.22, enhancements have been made to the routing of the `net/http` package in the standard library, which makes it a great starting point for implementing a server with, before needing to reach for another router or a full framework.
-- Parameters can be defined via `schema` or via `content`. Use the `content` form
- for anything other than trivial objects, they can marshal to arbitrary JSON
- structures. When you send them as cookie (`in: cookie`) arguments, we will
- URL encode them, since JSON delimiters aren't allowed in cookies.
+For instance, let's take this straightforward specification:
-## Using SecurityProviders
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Minimal ping API server
+paths:
+ /ping:
+ get:
+ responses:
+ '200':
+ description: pet response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pong'
+components:
+ schemas:
+ # base types
+ Pong:
+ type: object
+ required:
+ - ping
+ properties:
+ ping:
+ type: string
+ example: pong
+```
-If you generate client-code, you can use some default-provided security providers
-which help you to use the various OpenAPI 3 Authentication mechanism.
+This then generates code such as:
```go
- import (
- "github.com/deepmap/oapi-codegen/pkg/securityprovider"
- )
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
- func CreateSampleProviders() error {
- // Example BasicAuth
- // See: https://swagger.io/docs/specification/authentication/basic-authentication/
- basicAuthProvider, basicAuthProviderErr := securityprovider.NewSecurityProviderBasicAuth("MY_USER", "MY_PASS")
- if basicAuthProviderErr != nil {
- panic(basicAuthProviderErr)
- }
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
- // Example BearerToken
- // See: https://swagger.io/docs/specification/authentication/bearer-authentication/
- bearerTokenProvider, bearerTokenProviderErr := securityprovider.NewSecurityProviderBearerToken("MY_TOKEN")
- if bearerTokenProviderErr != nil {
- panic(bearerTokenProviderErr)
- }
+ // (GET /ping)
+ GetPing(w http.ResponseWriter, r *http.Request)
+}
- // Example ApiKey provider
- // See: https://swagger.io/docs/specification/authentication/api-keys/
- apiKeyProvider, apiKeyProviderErr := securityprovider.NewSecurityProviderApiKey("query", "myApiKeyParam", "MY_API_KEY")
- if apiKeyProviderErr != nil {
- panic(apiKeyProviderErr)
- }
+func HandlerFromMux(si ServerInterface, m *http.ServeMux) http.Handler {
+ return HandlerWithOptions(si, StdHTTPServerOptions{
+ BaseRouter: m,
+ })
+}
- // Example providing your own provider using an anonymous function wrapping in the
- // InterceptorFn adapter. The behaviour between the InterceptorFn and the Interceptor interface
- // are the same as http.HandlerFunc and http.Handler.
- customProvider := func(req *http.Request, ctx context.Context) error {
- // Just log the request header, nothing else.
- log.Println(req.Header)
- return nil
- }
+// HandlerWithOptions creates http.Handler with additional options
+func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.Handler {
+ m := options.BaseRouter
+
+ // ... omitted for brevity
- // Exhaustive list of some defaults you can use to initialize a Client.
- // If you need to override the underlying httpClient, you can use the option
- //
- // WithHTTPClient(httpClient *http.Client)
- //
- client, clientErr := NewClient("https://api.deepmap.com", WithRequestEditorFn(apiKeyProvider.Intercept))
+ m.HandleFunc("GET "+options.BaseURL+"/ping", wrapper.GetPing)
- return nil
- }
+ return m
+}
```
-## Extensions
+To implement this HTTP server, we need to write the following code in our [`api/impl.go`](examples/minimal-server/stdhttp/api/impl.go):
+
+```go
+import (
+ "encoding/json"
+ "net/http"
+)
+
+// optional code omitted
-`oapi-codegen` supports the following extended properties:
+type Server struct{}
-- `x-go-type`: specifies Go type name. It allows you to specify the type name for a schema, and
- will override any default value. This extended property isn't supported in all parts of
- OpenAPI, so please refer to the spec as to where it's allowed. Swagger validation tools will
- flag incorrect usage of this property.
-- `x-go-type-skip-optional-pointer`: specifies if the Go type should or should not be a pointer
- when the property is optional. If set to true, the type will not be a pointer if the field is
- optional or nullable. If set to false, the type will be a pointer.
-
- ```yaml
- properties:
- field:
- type: string
- x-go-type-skip-optional-pointer: true
- ```
-
- In the example above, the `field` field will be of type `string` instead of `*string`. This is
- useful when you want to handle the case of an empty string differently than a null value.
-
-- `x-go-name`: specifies Go field name. It allows you to specify the field name for a schema, and
- will override any default value. This extended property isn't supported in all parts of
- OpenAPI, so please refer to the spec as to where it's allowed. Swagger validation tools will
- flag incorrect usage of this property.
-- `x-go-type-name`: This property allows for assigning a Go type name to some part of a schema,
- such as generating a type name for an anonymous object inside another object, or renaming
- an enum. It differs from `x-go-type`, in that it doesn't completely replace some type reference,
- but simply names it.
-- `x-go-json-ignore`: sets tag to `-` to ignore the field in json completely.
-- `x-oapi-codegen-extra-tags`: adds extra Go field tags to the generated struct field. This is
- useful for interfacing with tag based ORM or validation libraries. The extra tags that
- are added are in addition to the regular json tags that are generated. If you specify your
- own `json` tag, you will override the default one.
-
- ```yaml
- components:
- schemas:
- Object:
- properties:
- name:
- type: string
- x-oapi-codegen-extra-tags:
- tag1: value1
- tag2: value2
- ```
+func NewServer() Server {
+ return Server{}
+}
- In the example above, field `name` will be declared as:
+// (GET /ping)
+func (Server) GetPing(w http.ResponseWriter, r *http.Request) {
+ resp := Pong{
+ Ping: "pong",
+ }
- ```
- Name string `json:"name" tag1:"value1" tag2:"value2"`
- ```
+ w.WriteHeader(http.StatusOK)
+ _ = json.NewEncoder(w).Encode(resp)
+}
+```
-- `x-go-type-import`: adds extra Go imports to your generated code. It can help you, when you want to
- choose your own import package for `x-go-type`.
+Now we've got our implementation, we can then write the following code to wire it up and get a running server:
- ```yaml
- schemas:
- Pet:
- properties:
- age:
- x-go-type: myuuid.UUID
- x-go-type-import:
- name: myuuid
- path: github.com/google/uuid
- ```
+```go
+import (
+ "log"
+ "net/http"
- After code generation you will get this:
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/stdhttp/api"
+)
- ```go
- import (
- ...
- myuuid "github.com/google/uuid"
- )
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
- //Pet defines model for Pet.
- type Pet struct {
- Age *myuuid.UUID `json:"age,omitempty"`
- }
+ r := http.NewServeMux()
- ```
+ // get an `http.Handler` that we can use
+ h := api.HandlerFromMux(server, r)
- `name` is an optional parameter. Example:
+ s := &http.Server{
+ Handler: h,
+ Addr: "0.0.0.0:8080",
+ }
- ```yaml
- components:
- schemas:
- Pet:
- properties:
- age:
- x-go-type: uuid.UUID
- x-go-type-import:
- path: github.com/google/uuid
- required:
- - age
- ```
+ // And we serve HTTP until the world ends.
+ log.Fatal(s.ListenAndServe())
+}
+```
- After code generation you will get this result:
+> [!NOTE]
+> This doesn't include [validation of incoming requests](#requestresponse-validation-middleware).
- ```go
- import (
- "github.com/google/uuid"
- )
+> [!NOTE]
+> If you feel like you've done everything right, but are still receiving `404 page not found` errors, make sure that you've got the `go` directive in your `go.mod` updated to:
- // Pet defines model for Pet.
- type Pet struct {
- Age uuid.UUID `json:"age"`
- }
- ```
+```go.mod
+go 1.22
+```
-- `x-enum-varnames`: supplies other enum names for the corresponding values. (alias: `x-enumNames`)
+
- ```yaml
- components:
- schemas:
- Object:
- properties:
- category:
- type: integer
- enum: [0, 1, 2]
- x-enum-varnames:
- - notice
- - warning
- - urgent
- ```
-
- After code generation you will get this result:
-
- ```go
- // Defines values for ObjectCategory.
- const (
- Notice ObjectCategory = 0
- Urgent ObjectCategory = 2
- Warning ObjectCategory = 1
- )
-
- // ObjectCategory defines model for Object.Category.
- type ObjectCategory int
- ```
-
-- `x-order`: specifies the order of the fields in the structure. It allows you to specify the order
- of the fields in the generated structure and will override any default value. This extended
- property is not supported in all parts of OpenAPI, so check the specification to see where it is
- allowed.
-
- ```yaml
- DateInterval:
+### Chi
+
+
+For instance, let's take this straightforward specification:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Minimal ping API server
+paths:
+ /ping:
+ get:
+ responses:
+ '200':
+ description: pet response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pong'
+components:
+ schemas:
+ # base types
+ Pong:
type: object
required:
- - name
+ - ping
properties:
- end:
- type: string
- format: date
- x-order: 2
- start:
+ ping:
type: string
- format: date
- x-order: 1
- ```
- In the example above, struct will be declared as:
-
- ```go
- type DateInterval struct {
- Start *openapi_types.Date `json:"start,omitempty"`
- End *openapi_types.Date `json:"end,omitempty"`
- }
- ```
-
-## Using `oapi-codegen`
-
-The default options for `oapi-codegen` will generate everything; client, server,
-type definitions and embedded swagger spec, but you can generate subsets of
-those via the `-generate` flag. It defaults to `types,client,server,spec`, but
-you can specify any combination of those.
-
-- `types`: generate all type definitions for all types in the OpenAPI spec. This
- will be everything under `#components`, as well as request parameter, request
- body, and response type objects.
-- `server`: generate the Echo server boilerplate. `server` requires the types in the
- same package to compile.
-- `chi-server`: generate the Chi server boilerplate. This code is dependent on
- that produced by the `types` target.
-- `fiber`: generate the Fiber server boilerplate. This code is dependent
- on that produced by the `types` target.
-- `iris`: generate the Iris server boilerplate. This code is dependent
- on that produced by the `types` target.
-- `client`: generate the client boilerplate. It, too, requires the types to be
- present in its package.
-- `spec`: embed the OpenAPI spec into the generated code as a gzipped blob.
- This is then usable with the `OapiRequestValidator`, or to be used by other
- methods that need access to the parsed OpenAPI specification
-- `skip-fmt`: skip running `goimports` on the generated code. This is useful for debugging
- the generated file in case the spec contains weird strings.
-- `skip-prune`: skip pruning unused components from the spec prior to generating
- the code.
-- `import-mapping`: specifies a map of references external OpenAPI specs to go
- Go include paths. Please see below.
-
-So, for example, if you would like to produce only the server code, you could
-run `oapi-codegen -generate types,server`. You could generate `types` and
-`server` into separate files, but both are required for the server code.
-
-`oapi-codegen` can filter paths base on their tags or operationId in the openapi definition.
-Use either `-include-tags`, `include-operation-ids` or `-exclude-tags`, `-exclude-operation-ids`
-followed by a comma-separated list of tags or operation ids. For instance, to generate a server
-that serves all paths except those tagged with `auth` or `admin`, use the argument, `-exclude-tags="auth,admin"`.
-To generate a server that only handles `admin` paths, use the argument
-`-include-tags="admin"` or use `-include-operation-ids="getPets"` to include this specific operation.
-When neither of these arguments is present, all paths are generated.
-
-`oapi-codegen` can filter schemas based on the option `--exclude-schemas`, which is
-a comma separated list of schema names. For instance, `--exclude-schemas=Pet,NewPet`
-will exclude from generation schemas `Pet` and `NewPet`. This allow to have a
-in the same package a manually defined structure or interface and refer to it
-in the openapi spec.
-
-Since `go generate` commands must be a single line, all the options above can make
-them pretty unwieldy, so you can specify all of the options in a configuration
-file via the `--config` option. Please see the test under
-[`/internal/test/externalref/`](https://github.com/deepmap/oapi-codegen/blob/master/internal/test/externalref/externalref.cfg.yaml)
-for an example. The structure of the file is as follows:
-
-```yaml
-package: externalref
-generate:
- models: true
- embedded-spec: true
-import-mapping:
- ./packageA/spec.yaml: github.com/deepmap/oapi-codegen/internal/test/externalref/packageA
- ./packageB/spec.yaml: github.com/deepmap/oapi-codegen/internal/test/externalref/packageB
-output: externalref.gen.go
-output-options:
- skip-prune: true
+ example: pong
```
-Have a look at [`cmd/oapi-codegen/oapi-codegen.go`](https://github.com/deepmap/oapi-codegen/blob/master/cmd/oapi-codegen/oapi-codegen.go#L48)
-to see all the fields on the configuration structure.
+This then generates code such as:
-### Import Mappings
+```go
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
-OpenAPI specifications may contain references to other OpenAPI specifications,
-and we need some additional information in order to be able to generate correct
-Go code.
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
-An external reference looks like this:
+ // (GET /ping)
+ GetPing(w http.ResponseWriter, r *http.Request)
+}
- $ref: ./some_spec.yaml#/components/schemas/Type
+// HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
+func HandlerFromMux(si ServerInterface, r *mux.Router) http.Handler {
+ return HandlerWithOptions(si, ChiServerOptions{
+ BaseRouter: r,
+ })
+}
-We assume that you have already generated the boilerplate code for `./some_spec.yaml`
-using `oapi-codegen`, and you have a package which contains the generated code,
-let's call it `github.com/deepmap/some-package`. You need to tell `oapi-codegen` that
-`some_spec.yaml` corresponds to this package, and you would do it by specifying
-this command line argument:
+// HandlerWithOptions creates http.Handler with additional options
+func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handler {
+ r := options.BaseRouter
- -import-mapping=./some_spec.yaml:github.com/deepmap/some-package
+ // ...
-This tells us that in order to resolve references generated from `some_spec.yaml` we
-need to import `github.com/deepmap/some-package`. You may specify multiple mappings
-by comma separating them in the form `key1:value1,key2:value2`.
+ r.Group(func(r chi.Router) {
+ r.Get(options.BaseURL+"/ping", wrapper.GetPing)
+ })
-## What's missing or incomplete
+ return r
+}
+```
-This code is still young, and not complete, since we're filling it in as we
-need it. We've not yet implemented several things:
+To implement this HTTP server, we need to write the following code in our [`api/impl.go`](examples/minimal-server/chi/api/impl.go):
-- `patternProperties` isn't yet supported and will exit with an error. Pattern
- properties were defined in JSONSchema, and the `kin-openapi` Swagger object
- knows how to parse them, but they're not part of OpenAPI 3.0, so we've left
- them out, as support is very complicated.
+```go
+import (
+ "encoding/json"
+ "net/http"
+)
-## Making changes to code generation
+// optional code omitted
-The code generator uses a tool to inline all the template definitions into
-code, so that we don't have to deal with the location of the template files.
-When you update any of the files under the `templates/` directory, you will
-need to regenerate the template inlines:
+type Server struct{}
- go generate ./pkg/codegen/templates
+func NewServer() Server {
+ return Server{}
+}
-All this command does is inline the files ending in `.tmpl` into the specified
-Go file.
+// (GET /ping)
+func (Server) GetPing(w http.ResponseWriter, r *http.Request) {
+ resp := Pong{
+ Ping: "pong",
+ }
-Afterwards you should run `go generate ./...`, and the templates will be updated
-accordingly.
+ w.WriteHeader(http.StatusOK)
+ _ = json.NewEncoder(w).Encode(resp)
+}
+```
-Alternatively, you can provide custom templates to override built-in ones using
-the `-templates` flag specifying a path to a directory containing templates
-files. These files **must** be named identically to built-in template files
-(see `pkg/codegen/templates/*.tmpl` in the source code), and will be interpreted
-on-the-fly at run time. Example:
+Now we've got our implementation, we can then write the following code to wire it up and get a running server:
- $ ls -1 my-templates/
- client.tmpl
- typedef.tmpl
- $ oapi-codegen \
- -templates my-templates/ \
- -generate types,client \
- petstore-expanded.yaml
+```go
+import (
+ "log"
+ "net/http"
-When using the configuration file, it is possible to provide templates directly
-as text, as a local path, or as a URL. If the data provided to the
-configuration file is more than one line, the local path and URL checks will be
-ignored and will be treated as raw template text. If one line, the string
-will be used to check for a local file, followed by checking performing a HTTP
-GET request. If the file lookup returns any error other than not found, or the
-HTTP request returns a non 200 response code, the generator will error.
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/chi/api"
+ "github.com/go-chi/chi/v5"
+)
-⚠️ Warning: If using urls that tracks against git repositories such as
-`raw.githubusercontent.com`, it is strongly encouraged to use a tag or a hash
-instead of a branch like `main`. Tracking a branch can lead to unexpected API
-drift, and loss of the ability to reproduce a build.
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
-Examples:
+ r := chi.NewMux()
-```yaml
-output: api.gen.go
-package: api
-output-options:
- user-templates:
- # using a local file
- client-with-responses.tmpl: /home/username/workspace/templatesProject/my-client-with-responses.tmpl
-
- # The following are referencing a version of the default
- # client-with-responses.tmpl file, but loaded in through
- # github's raw.githubusercontent.com. The general form
- # to use raw.githubusercontent.com is as follows
- # https://raw.githubusercontent.com////path/to/template/template.tmpl
-
- # using raw.githubusercontent.com with a hash
- client-with-responses.tmpl: https://raw.githubusercontent.com/deepmap/oapi-codegen/7b010099dcf1192b3bfaa3898b5f375bb9590ddf/pkg/codegen/templates/client-with-responses.tmpl
- # using raw.githubusercontent.com with a tag
- client-with-responses.tmpl: https://raw.githubusercontent.com/deepmap/oapi-codegen/v1.12.4/pkg/codegen/templates/client-with-responses.tmpl
- # using raw.githubusercontent.com with a branch
- client-with-responses.tmpl: https://raw.githubusercontent.com/deepmap/oapi-codegen/master/pkg/codegen/templates/client-with-responses.tmpl
+ // get an `http.Handler` that we can use
+ h := api.HandlerFromMux(server, r)
- #This example is directly embedding the template into the config file.
- client-with-responses.tmpl: |
- // ClientWithResponses builds on ClientInterface to offer response payloads
- type ClientWithResponses struct {
- ClientInterface
- }
- ...
- # template shortened for brevity
+ s := &http.Server{
+ Handler: h,
+ Addr: "0.0.0.0:8080",
+ }
+ // And we serve HTTP until the world ends.
+ log.Fatal(s.ListenAndServe())
+}
+```
+
+> [!NOTE]
+> This doesn't include [validation of incoming requests](#requestresponse-validation-middleware).
+
+### gorilla/mux
+
+
+For instance, let's take this straightforward specification:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Minimal ping API server
+paths:
+ /ping:
+ get:
+ responses:
+ '200':
+ description: pet response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pong'
+components:
+ schemas:
+ # base types
+ Pong:
+ type: object
+ required:
+ - ping
+ properties:
+ ping:
+ type: string
+ example: pong
```
-Using the configuration file to load in templates **will** load in templates
-with names other than those defined by the built in templates. These user
-templates will not be called unless the user overrides a built in template to
-call them however.
+This then generates code such as:
+
+```go
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /ping)
+ GetPing(w http.ResponseWriter, r *http.Request)
+}
+
+// HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
+func HandlerFromMux(si ServerInterface, r *mux.Router) http.Handler {
+ return HandlerWithOptions(si, GorillaServerOptions{
+ BaseRouter: r,
+ })
+}
+
+// HandlerWithOptions creates http.Handler with additional options
+func HandlerWithOptions(si ServerInterface, options GorillaServerOptions) http.Handler {
+ r := options.BaseRouter
+
+ // ...
+
+ r.HandleFunc(options.BaseURL+"/ping", wrapper.GetPing).Methods("GET")
+
+ return r
+}
+```
+
+To implement this HTTP server, we need to write the following code in our [`api/impl.go`](examples/minimal-server/gorillamux/api/impl.go):
+
+```go
+import (
+ "encoding/json"
+ "net/http"
+)
+
+// optional code omitted
+
+type Server struct{}
+
+func NewServer() Server {
+ return Server{}
+}
+
+// (GET /ping)
+func (Server) GetPing(w http.ResponseWriter, r *http.Request) {
+ resp := Pong{
+ Ping: "pong",
+ }
+
+ w.WriteHeader(http.StatusOK)
+ _ = json.NewEncoder(w).Encode(resp)
+}
+```
+
+Now we've got our implementation, we can then write the following code to wire it up and get a running server:
+
+```go
+import (
+ "log"
+ "net/http"
+
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/gorillamux/api"
+ "github.com/gorilla/mux"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ r := mux.NewRouter()
+
+ // get an `http.Handler` that we can use
+ h := api.HandlerFromMux(server, r)
+
+ s := &http.Server{
+ Handler: h,
+ Addr: "0.0.0.0:8080",
+ }
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(s.ListenAndServe())
+}
+```
+
+> [!NOTE]
+> This doesn't include [validation of incoming requests](#requestresponse-validation-middleware).
+
+### Echo server
+
+
+For instance, let's take this straightforward specification:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Minimal ping API server
+paths:
+ /ping:
+ get:
+ responses:
+ '200':
+ description: pet response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pong'
+components:
+ schemas:
+ # base types
+ Pong:
+ type: object
+ required:
+ - ping
+ properties:
+ ping:
+ type: string
+ example: pong
+```
+
+This then generates code such as:
+
+```go
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /ping)
+ GetPing(ctx echo.Context) error
+}
+
+// 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 {
+ // ...
+ GET(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) {
+ // ...
+
+ router.GET(baseURL+"/ping", wrapper.GetPing)
+
+}
+```
+
+To implement this HTTP server, we need to write the following code in our [`api/impl.go`](examples/minimal-server/echo/api/impl.go):
+
+```go
+import (
+ "net/http"
+
+ "github.com/labstack/echo/v4"
+)
+
+// optional code omitted
+
+type Server struct{}
+
+func NewServer() Server {
+ return Server{}
+}
+
+// (GET /ping)
+func (Server) GetPing(ctx echo.Context) error {
+ resp := Pong{
+ Ping: "pong",
+ }
+
+ return ctx.JSON(http.StatusOK, resp)
+}
+```
+
+Now we've got our implementation, we can then write the following code to wire it up and get a running server:
+
+```go
+import (
+ "log"
+
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/echo/api"
+ "github.com/labstack/echo/v4"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ e := echo.New()
+
+ api.RegisterHandlers(e, server)
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(e.Start("0.0.0.0:8080"))
+}
+```
+
+> [!NOTE]
+> This doesn't include [validation of incoming requests](#requestresponse-validation-middleware).
+
+### Fiber server
+
+
+For instance, let's take this straightforward specification:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Minimal ping API server
+paths:
+ /ping:
+ get:
+ responses:
+ '200':
+ description: pet response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pong'
+components:
+ schemas:
+ # base types
+ Pong:
+ type: object
+ required:
+ - ping
+ properties:
+ ping:
+ type: string
+ example: pong
+```
+
+This then generates code such as:
+
+```go
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /ping)
+ GetPing(c *fiber.Ctx) error
+}
+
+// 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) {
+ // ...
+
+ router.Get(options.BaseURL+"/ping", wrapper.GetPing)
+}
+```
+
+To implement this HTTP server, we need to write the following code in our [`api/impl.go`](examples/minimal-server/fiber/api/impl.go):
+
+```go
+import (
+ "net/http"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+// ensure that we've conformed to the `ServerInterface` with a compile-time check
+var _ ServerInterface = (*Server)(nil)
+
+type Server struct{}
+
+func NewServer() Server {
+ return Server{}
+}
+
+// (GET /ping)
+func (Server) GetPing(ctx *fiber.Ctx) error {
+ resp := Pong{
+ Ping: "pong",
+ }
+
+ return ctx.
+ Status(http.StatusOK).
+ JSON(resp)
+}
+```
+
+Now we've got our implementation, we can then write the following code to wire it up and get a running server:
+
+```go
+import (
+ "log"
+
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/fiber/api"
+ "github.com/gofiber/fiber/v2"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ app := fiber.New()
+
+ api.RegisterHandlers(app, server)
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(app.Listen("0.0.0.0:8080"))
+}
+```
+
+> [!NOTE]
+> This doesn't include [validation of incoming requests](#requestresponse-validation-middleware).
+
+### Gin server
+
+
+For instance, let's take this straightforward specification:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Minimal ping API server
+paths:
+ /ping:
+ get:
+ responses:
+ '200':
+ description: pet response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pong'
+components:
+ schemas:
+ # base types
+ Pong:
+ type: object
+ required:
+ - ping
+ properties:
+ ping:
+ type: string
+ example: pong
+```
+
+This then generates code such as:
+
+```go
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /ping)
+ GetPing(c *gin.Context)
+}
+
+// RegisterHandlers creates http.Handler with routing matching OpenAPI spec.
+func RegisterHandlers(router gin.IRouter, si ServerInterface) {
+ RegisterHandlersWithOptions(router, si, GinServerOptions{})
+}
+
+// RegisterHandlersWithOptions creates http.Handler with additional options
+func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) {
+ // ...
+
+ router.GET(options.BaseURL+"/ping", wrapper.GetPing)
+}
+```
+
+To implement this HTTP server, we need to write the following code in our [`api/impl.go`](examples/minimal-server/gorillamux/api/impl.go):
+
+```go
+import (
+ "net/http"
+
+ "github.com/gin-gonic/gin"
+)
+
+// optional code omitted
+
+type Server struct{}
+
+func NewServer() Server {
+ return Server{}
+}
+
+// (GET /ping)
+func (Server) GetPing(ctx *gin.Context) {
+ resp := Pong{
+ Ping: "pong",
+ }
+
+ ctx.JSON(http.StatusOK, resp)
+}
+```
+
+Now we've got our implementation, we can then write the following code to wire it up and get a running server:
+
+```go
+import (
+ "log"
+ "net/http"
+
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/gin/api"
+ "github.com/gin-gonic/gin"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ r := gin.Default()
+
+ api.RegisterHandlers(r, server)
+
+ // And we serve HTTP until the world ends.
+
+ s := &http.Server{
+ Handler: r,
+ Addr: "0.0.0.0:8080",
+ }
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(s.ListenAndServe())
+}
+```
+
+> [!NOTE]
+> This doesn't include [validation of incoming requests](#requestresponse-validation-middleware).
+
+### Iris server
+
+
+For instance, let's take this straightforward specification:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Minimal ping API server
+paths:
+ /ping:
+ get:
+ responses:
+ '200':
+ description: pet response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pong'
+components:
+ schemas:
+ # base types
+ Pong:
+ type: object
+ required:
+ - ping
+ properties:
+ ping:
+ type: string
+ example: pong
+```
+
+This then generates code such as:
+
+```go
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /ping)
+ GetPing(ctx iris.Context)
+}
+
+// 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) {
+ // ...
+
+ router.Get(options.BaseURL+"/ping", wrapper.GetPing)
+
+ router.Build()
+}
+```
+
+To implement this HTTP server, we need to write the following code in our [`api/impl.go`](examples/minimal-server/gorillamux/api/impl.go):
+
+```go
+import (
+ "net/http"
+
+ "github.com/kataras/iris/v12"
+)
+
+// optional code omitted
+
+type Server struct{}
+
+func NewServer() Server {
+ return Server{}
+}
+
+// (GET /ping)
+func (Server) GetPing(ctx iris.Context) {
+ resp := Pong{
+ Ping: "pong",
+ }
+
+ ctx.StatusCode(http.StatusOK)
+ _ = ctx.JSON(resp)
+}
+```
+
+Now we've got our implementation, we can then write the following code to wire it up and get a running server:
+
+```go
+import (
+ "log"
+
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/iris/api"
+ "github.com/kataras/iris/v12"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ i := iris.Default()
+
+ api.RegisterHandlers(i, server)
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(i.Listen("0.0.0.0:8080"))
+}
+```
+
+> [!NOTE]
+> This doesn't include [validation of incoming requests](#requestresponse-validation-middleware).
+
+### Strict server
+
+`oapi-codegen` also supports generating a server that is much more strict with the contract that the implementer requires, and takes inspiration from server-side code generation for RPC servers.
+
+This takes the boilerplate reduction from the non-strict servers and adds additional boilerplate reduction, allowing you to make the following changes to your function signatures:
+
+```diff
+-FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams)
++FindPets(ctx context.Context, request FindPetsRequestObject) (FindPetsResponseObject, error)
+```
+
+This is the highest level of strictness that `oapi-codegen` supports right now, and it's a good idea to start with this if you want the most guardrails to simplify developing your APIs.
+
+The strict server has support for:
+
+- multiple request/response media types and status codes on a given operation
+- first-class support for `multipart/form-data` and `application/x-www-form-urlencoded` requests
+- returning an [HTTP 500 Internal Server Error](https://http.cat/500), when an `error` is returned from a function
+- automagic (un)marshalling of request/responses, and setting `content-type` and HTTP status codes on responses
+- binding request values to a struct, a `multipart.Reader` or providing a `io.Reader`
+
+You can see a little more detail of the generated code in the ["What does it look like"](#what-does-it-look-like-strict) section.
+
+> [!NOTE]
+> To configure the strict server generation, you must specify another server to be generated. For instance:
+
+```yaml
+# yaml-language-server: $schema=https://raw.githubusercontent.com/deepmap/oapi-codegen/HEAD/configuration-schema.json
+package: api
+generate:
+ # NOTE another server must be added!
+ chi-server: true
+ strict-server: true
+output: server.gen.go
+```
+
+> [!NOTE]
+> This doesn't include [validation of incoming requests](#requestresponse-validation-middleware).
+
+## Generating API clients
+
+As well as generating the server-side boilerplate, `oapi-codegen` can also generate API clients.
+
+This aims to be an API client that can be used to interact with the methods of the API, and is perfectly suited for production usage.
+
+However, if you were looking for a slightly more SDK-style approach, or a mix of generated tests and/or documentation, this API client may not be for you, and you may want to look at alternate tooling.
+
+For instance, given an `api.yaml`:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Generate models
+paths:
+ /client:
+ get:
+ operationId: getClient
+ responses:
+ 200:
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ClientType"
+ put:
+ operationId: updateClient
+ responses:
+ 400:
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ code:
+ type: string
+ required:
+ - code
+components:
+ schemas:
+ ClientType:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ # NOTE that this is not generated by default because it's not referenced. If you want it, you need to use the following YAML configuration:
+ #
+ # output-options:
+ # skip-prune: true
+ Unreferenced:
+ type: object
+ required:
+ - id
+ properties:
+ id:
+ type: integer
+```
+
+And a `cfg.yaml`:
+
+```yaml
+# yaml-language-server: $schema=https://raw.githubusercontent.com/deepmap/oapi-codegen/HEAD/configuration-schema.json
+package: client
+output: client.gen.go
+generate:
+ models: true
+ client: true
+```
+
+And a `generate.go`:
+
+```go
+package client
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
+```
+
+This would then generate:
+
+```go
+package client
+
+// ...
+
+// ClientType defines model for ClientType.
+type ClientType struct {
+ Name string `json:"name"`
+}
+
+// ...
+
+// 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
+}
+
+// ...
+
+// The interface specification for the client above.
+type ClientInterface interface {
+ // GetClient request
+ GetClient(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ // UpdateClient request
+ UpdateClient(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+// ...
+
+// ClientWithResponsesInterface is the interface specification for the client with responses above.
+type ClientWithResponsesInterface interface {
+ // GetClientWithResponse request
+ GetClientWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetClientResponse, error)
+
+ // UpdateClientWithResponse request
+ UpdateClientWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*UpdateClientResponse, error)
+}
+
+type GetClientResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *ClientType
+}
+
+// ...
+```
+
+With this generated client, it is then possible to construct and utilise the client, for instance:
+
+```go
+package client_test
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "net/http"
+
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/client"
+)
+
+func TestClient_canCall() {
+ // custom HTTP client
+ hc := http.Client{}
+
+ // with a raw http.Response
+ {
+ c, err := client.NewClient("http://localhost:1234", client.WithHTTPClient(&hc))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ resp, err := c.GetClient(context.TODO())
+ if err != nil {
+ log.Fatal(err)
+ }
+ if resp.StatusCode != http.StatusOK {
+ log.Fatalf("Expected HTTP 200 but received %d", resp.StatusCode)
+ }
+ }
+
+ // or to get a struct with the parsed response body
+ {
+ c, err := client.NewClientWithResponses("http://localhost:1234", client.WithHTTPClient(&hc))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ resp, err := c.GetClientWithResponse(context.TODO())
+ if err != nil {
+ log.Fatal(err)
+ }
+ if resp.StatusCode() != http.StatusOK {
+ log.Fatalf("Expected HTTP 200 but received %d", resp.StatusCode())
+ }
+
+ fmt.Printf("resp.JSON200: %v\n", resp.JSON200)
+ }
+
+}
+```
+
+## Generating API models
+
+If you're looking to only generate the models for interacting with a remote service, for instance if you need to hand-roll the API client for whatever reason, you can do this as-is.
+
+> [!TIP]
+> Try to define as much as possible within the `#/components/schemas` object, as `oapi-codegen` will generate all the types here.
+>
+> Although we can generate some types based on inline definitions in i.e. a path's response type, it isn't always possible to do this, or if it is generated, can be a little awkward to work with as it may be defined as an anonymous struct.
+
+For instance, given an `api.yaml`:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Generate models
+paths:
+ /client:
+ get:
+ operationId: getClient
+ responses:
+ 200:
+ content:
+ application/json:
+ schema:
+ # NOTE that Client is generated here, because it's within #/components/schemas
+ $ref: "#/components/schemas/Client"
+ put:
+ operationId: updateClient
+ responses:
+ 400:
+ content:
+ application/json:
+ # NOTE that this anonymous object is /not/ generated because it's an anonymous, but would be generated if using `generate: client`
+ # See https://github.com/deepmap/oapi-codegen/issues/1512
+ schema:
+ type: object
+ properties:
+ code:
+ type: string
+ required:
+ - code
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ # NOTE that this is not generated by default because it's not referenced. If you want it, you need to use the following YAML configuration:
+ #
+ # output-options:
+ # skip-prune: true
+ Unreferenced:
+ type: object
+ required:
+ - id
+ properties:
+ id:
+ type: integer
+```
+
+And a `cfg.yaml`:
+
+```yaml
+# yaml-language-server: $schema=https://raw.githubusercontent.com/deepmap/oapi-codegen/HEAD/configuration-schema.json
+package: onlymodels
+output: only-models.gen.go
+generate:
+ models: true
+```
+
+And a `generate.go`:
+
+```go
+package onlymodels
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
+```
+
+This would then generate:
+
+```go
+package onlymodels
+
+// Client defines model for Client.
+type Client struct {
+ Name string `json:"name"`
+}
+```
+
+If you wish to also generate the `Unreferenced` type, you would need the following `cfg.yaml`:
+
+```yaml
+# yaml-language-server: $schema=https://raw.githubusercontent.com/deepmap/oapi-codegen/HEAD/configuration-schema.json
+package: onlymodels
+output: only-models.gen.go
+generate:
+ models: true
+output-options:
+ # NOTE that this is only required for the `Unreferenced` type
+ skip-prune: true
+```
+
+For a complete example see [`examples/only-models`](examples/only-models).
+
+## Splitting large OpenAPI specs across multiple packages (aka "Import Mapping" or "external references")
+
+
+When you've got a large OpenAPI specification, you may find it useful to split the contents of the spec across multiple files, using external references, such as:
+
+```yaml
+components:
+ schemas:
+ User:
+ $ref: '../common/api.yaml#/components/schemas/User'
+```
+
+This is supported by `oapi-codegen`, through the ability to perform "Import Mapping".
+
+For instance, let's say that we have a large API, which has a user-facing API and an admin API, both of which use a common set of API models.
+
+In this case, we may have an Admin API that looks like:
+
+```yaml
+# admin/api.yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Admin API
+ description: The admin-only portion of the API, which has its own separate OpenAPI spec
+tags:
+ - name: admin
+ description: Admin API endpoints
+ - name: user
+ description: API endpoint that pertains to user data
+paths:
+ /admin/user/{id}:
+ get:
+ tags:
+ - admin
+ - user
+ summary: Get a user's details
+ operationId: getUserById
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ 200:
+ description: Success
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+components:
+ schemas:
+ User:
+ $ref: '../common/api.yaml#/components/schemas/User'
+```
+
+This references the common spec:
+
+```yaml
+# common/api.yaml
+components:
+ schemas:
+ User:
+ type: object
+ additionalProperties: false
+ properties:
+ name:
+ type: string
+ required:
+ - name
+```
+
+And finally we have our configuration file:
+
+```yaml
+# yaml-language-server: $schema=https://raw.githubusercontent.com/deepmap/oapi-codegen/HEAD/configuration-schema.json
+# admin/cfg.yaml
+package: admin
+output: server.gen.go
+generate:
+ models: true
+ chi-server: true
+output-options:
+ # to make sure that all types are generated
+ skip-prune: true
+# NOTE that this won't work, as it's missing `import-mapping`
+```
+
+If we were to run `oapi-codegen`, this will fail with the following error
+
+```
+error generating code: error creating operation definitions: error generating response definitions: error generating request body definition: error turning reference (../common/api.yaml#/components/schemas/User) into a Go type: unrecognized external reference '../common/api.yaml'; please provide the known import for this reference using option --import-mapping
+```
+
+This is because `oapi-codegen` requires:
+
+```yaml
+# yaml-language-server: $schema=https://raw.githubusercontent.com/deepmap/oapi-codegen/HEAD/configuration-schema.json
+package: admin
+output: server.gen.go
+generate:
+ models: true
+ chi-server: true
+output-options:
+ # to make sure that all types are generated
+ skip-prune: true
+import-mapping:
+ # for a given file/URL that is $ref'd, point `oapi-codegen` to the Go package that this spec is generated into, to perform Go package imports
+ ../common/api.yaml: github.com/oapi-codegen/oapi-codegen/v2/examples/import-mapping/common
+```
+
+This will then generate the following code:
+
+```go
+package admin
+
+import (
+ // ...
+ externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/examples/import-mapping/common"
+)
+
+// User defines model for User.
+type User = externalRef0.User
+```
+
+If you don't want to do this, an alternate option is to [bundle your multiple OpenAPI files](https://www.jvt.me/posts/2022/02/10/bundle-openapi/) into a single spec.
+
+Check out [the import-mapping example](examples/import-mapping/) for the full code.
+
+## Generating Nullable types
+
+It's possible that you want to be able to determine whether a field isn't sent, is sent as `null` or has a value.
+
+For instance, if you had the following OpenAPI property:
+
+```yaml
+S:
+ type: object
+ properties:
+ Field:
+ type: string
+ nullable: true
+ required: []
+```
+
+The default behaviour in `oapi-codegen` is to generate:
+
+```go
+type S struct {
+ Field *string `json:"field,omitempty"`
+}
+```
+
+However, you lose the ability to understand the three cases, as there's no way to distinguish two of the types from each other:
+
+- is this field not sent? (Can be checked with `S.Field == nil`)
+- is this field `null`? (Can be checked with `S.Field == nil`)
+- does this field have a value? (`S.Field != nil && *S.Field == "123"`)
+
+As of `oapi-codegen` [v2.1.0](https://github.com/deepmap/oapi-codegen/releases/tag/v2.1.0) it is now possible to represent this with the `nullable.Nullable` type from [our new library, oapi-codegen/nullable](https://github.com/oapi-codegen/nullable).
+
+If you configure your generator's Output Options to opt-in to this behaviour, as so:
+
+```yaml
+output-options:
+ nullable-type: true
+```
+
+You will now receive the following output:
+
+```go
+type S struct {
+ // note that there's no pointer here, just `omitempty`
+ Field nullable.Nullable[string] `json:"field,omitempty"`
+}
+```
+
+## OpenAPI extensions
+
+As well as the core OpenAPI support, we also support the following OpenAPI extensions, as denoted by the [OpenAPI Specification Extensions](https://spec.openapis.org/oas/v3.0.3#specification-extensions).
+
+
+
+
+
+Extension
+
+
+Description
+
+
+Example usage
+
+
+
+
+
+
+`x-go-type`
+`x-go-type-import`
+
+
+
+Override the generated type definition (and optionally, add an import from another package)
+
+
+
+
+Using the `x-go-type` (and optionally, `x-go-type-import` when you need to import another package) allows overriding the type that `oapi-codegen` determined the generated type should be.
+
+We can see this at play with the following schemas:
+
+```yaml
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ # this is a bit of a contrived example, as you could instead use
+ # `format: uuid` but it explains how you'd do this when there may be
+ # a clash, for instance if you already had a `uuid` package that was
+ # being imported, or ...
+ x-go-type: googleuuid.UUID
+ x-go-type-import:
+ path: github.com/google/uuid
+ name: googleuuid
+ id:
+ type: number
+ # ... this is also a bit of a contrived example, as you could use
+ # `type: integer` but in the case that you know better than what
+ # oapi-codegen is generating, like so:
+ x-go-type: int64
+```
+
+From here, we now get two different models:
+
+```go
+// Client defines model for Client.
+type Client struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ Id *int64 `json:"id,omitempty"`
+ Name googleuuid.UUID `json:"name"`
+}
+```
+
+You can see this in more detail in [the example code](examples/extensions/xgotype/).
+
+
+
+
+
+
+
+
+`x-go-type-skip-optional-pointer`
+
+
+
+Do not add a pointer type for optional fields in structs
+
+
+
+
+By default, `oapi-codegen` will generate a pointer for optional fields.
+
+Using the `x-go-type-skip-optional-pointer` extension allows omitting that pointer.
+
+We can see this at play with the following schemas:
+
+```yaml
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ x-go-type-skip-optional-pointer: true
+```
+
+From here, we now get two different models:
+
+```go
+// Client defines model for Client.
+type Client struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ Id float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+```
+
+You can see this in more detail in [the example code](examples/extensions/xgotypeskipoptionalpointer/).
+
+
+
+
+
+
+
+
+`x-go-name`
+
+
+
+Override the generated name of a field or a type
+
+
+
+
+By default, `oapi-codegen` will attempt to generate the name of fields and types in as best a way it can.
+
+However, sometimes, the name doesn't quite fit what your codebase standards are, or the intent of the field, so you can override it with `x-go-name`.
+
+We can see this at play with the following schemas:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-go-name
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ # can be used on a type
+ x-go-name: ClientRenamedByExtension
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ # or on a field
+ x-go-name: AccountIdentifier
+```
+
+From here, we now get two different models:
+
+```go
+// Client defines model for Client.
+type Client struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientRenamedByExtension defines model for ClientWithExtension.
+type ClientRenamedByExtension struct {
+ AccountIdentifier *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+```
+
+You can see this in more detail in [the example code](examples/extensions/xgoname/).
+
+
+
+
+
+
+
+
+`x-go-type-name`
+
+
+
+Override the generated name of a type
+
+
+
+
+> [!NOTE]
+> Notice that this is subtly different to the `x-go-name`, which also applies to _fields_ within `struct`s.
+
+By default, `oapi-codegen` will attempt to generate the name of types in as best a way it can.
+
+However, sometimes, the name doesn't quite fit what your codebase standards are, or the intent of the field, so you can override it with `x-go-name`.
+
+We can see this at play with the following schemas:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-go-type-name
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ x-go-type-name: ClientRenamedByExtension
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ # NOTE attempting a `x-go-type-name` here is a no-op, as we're not producing a _type_ only a _field_
+ x-go-type-name: ThisWillNotBeUsed
+```
+
+From here, we now get two different models and a type alias:
+
+```go
+// Client defines model for Client.
+type Client struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension = ClientRenamedByExtension
+
+// ClientRenamedByExtension defines model for .
+type ClientRenamedByExtension struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+```
+
+You can see this in more detail in [the example code](examples/extensions/xgotypename/).
+
+
+
+
+
+
+
+
+`x-omitempty`
+
+
+
+Force the presence of the JSON tag `omitempty` on a field
+
+
+
+
+In a case that you may want to add the JSON struct tag `omitempty` to types that don't have one generated by default - for instance a required field - you can use the `x-omitempty` extension.
+
+We can see this at play with the following schemas:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-omitempty
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ # for some reason, you may want this behaviour, even though it's a required field
+ x-omitempty: true
+ id:
+ type: number
+```
+
+From here, we now get two different models:
+
+```go
+// Client defines model for Client.
+type Client struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name,omitempty"`
+}
+```
+
+Notice that the `ComplexField` is still generated in full, but the type will then be ignored with JSON marshalling.
+
+You can see this in more detail in [the example code](examples/extensions/xgojsonignore/).
+
+
+
+
+
+
+
+
+`x-go-json-ignore`
+
+
+
+When (un)marshaling JSON, ignore field(s)
+
+
+
+
+By default, `oapi-codegen` will generate `json:"..."` struct tags for all fields in a struct, so JSON (un)marshaling works.
+
+However, sometimes, you want to omit fields, which can be done with the `x-go-json-ignore` extension.
+
+We can see this at play with the following schemas:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-go-json-ignore
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ complexField:
+ type: object
+ properties:
+ name:
+ type: string
+ accountName:
+ type: string
+ # ...
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ complexField:
+ type: object
+ properties:
+ name:
+ type: string
+ accountName:
+ type: string
+ # ...
+ x-go-json-ignore: true
+```
+
+From here, we now get two different models:
+
+```go
+// Client defines model for Client.
+type Client struct {
+ ComplexField *struct {
+ AccountName *string `json:"accountName,omitempty"`
+ Name *string `json:"name,omitempty"`
+ } `json:"complexField,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ ComplexField *struct {
+ AccountName *string `json:"accountName,omitempty"`
+ Name *string `json:"name,omitempty"`
+ } `json:"-"`
+ Name string `json:"name"`
+}
+```
+
+Notice that the `ComplexField` is still generated in full, but the type will then be ignored with JSON marshalling.
+
+You can see this in more detail in [the example code](examples/extensions/xgojsonignore/).
+
+
+
+
+
+
+
+
+`x-oapi-codegen-extra-tags`
+
+
+
+Generate arbitrary struct tags to fields
+
+
+
+
+If you're making use of a field's struct tags to i.e. apply validation, decide whether something should be logged, etc, you can use `x-oapi-codegen-extra-tags` to set additional tags for your generated types.
+
+We can see this at play with the following schemas:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-oapi-codegen-extra-tags
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ - id
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ - id
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ x-oapi-codegen-extra-tags:
+ validate: "required,min=1,max=256"
+ safe-to-log: "true"
+ gorm: primarykey
+```
+
+From here, we now get two different models:
+
+```go
+// Client defines model for Client.
+type Client struct {
+ Id float32 `json:"id"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ Id float32 `gorm:"primarykey" json:"id" safe-to-log:"true" validate:"required,min=1,max=256"`
+ Name string `json:"name"`
+}
+```
+
+You can see this in more detail in [the example code](examples/extensions/xoapicodegenextratags/).
+
+
+
+
+
+
+
+
+`x-enum-varnames` / `x-enumNames`
+
+
+
+Override generated variable names for enum constants
+
+
+
+
+When consuming an enum value from an external system, the name may not produce a nice variable name. Using the `x-enum-varnames` extension allows overriding the name of the generated variable names.
+
+We can see this at play with the following schemas:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-enumNames and x-enum-varnames
+components:
+ schemas:
+ ClientType:
+ type: string
+ enum:
+ - ACT
+ - EXP
+ ClientTypeWithNamesExtension:
+ type: string
+ enum:
+ - ACT
+ - EXP
+ x-enumNames:
+ - Active
+ - Expired
+ ClientTypeWithVarNamesExtension:
+ type: string
+ enum:
+ - ACT
+ - EXP
+ x-enum-varnames:
+ - Active
+ - Expired
+```
+
+From here, we now get two different forms of the same enum definition.
+
+```go
+// Defines values for ClientType.
+const (
+ ACT ClientType = "ACT"
+ EXP ClientType = "EXP"
+)
+
+// ClientType defines model for ClientType.
+type ClientType string
+
+// Defines values for ClientTypeWithExtension.
+const (
+ Active ClientTypeWithExtension = "ACT"
+ Expired ClientTypeWithExtension = "EXP"
+)
+
+// ClientTypeWithExtension defines model for ClientTypeWithExtension.
+type ClientTypeWithExtension string
+```
+
+You can see this in more detail in [the example code](examples/extensions/xenumvarnames/).
+
+
+
+
+
+
+
+
+`x-deprecated-reason`
+
+
+
+Add a GoDoc deprecation warning to a type
+
+
+
+
+When an OpenAPI type is deprecated, a deprecation warning can be added in the GoDoc using `x-deprecated-reason`.
+
+We can see this at play with the following schemas:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-deprecated-reason
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ deprecated: true
+ x-deprecated-reason: Don't use because reasons
+ id:
+ type: number
+ # NOTE that this doesn't generate, as no `deprecated: true` is set
+ x-deprecated-reason: NOTE you shouldn't see this, as you've not deprecated this field
+```
+
+From here, we now get two different forms of the same enum definition.
+
+```go
+// Client defines model for Client.
+type Client struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ Id *float32 `json:"id,omitempty"`
+ // Deprecated: Don't use because reasons
+ Name string `json:"name"`
+}
+```
+
+Notice that because we've not set `deprecated: true` to the `name` field, it doesn't generate a deprecation warning.
+
+You can see this in more detail in [the example code](examples/extensions/xdeprecatedreason/).
+
+
+
+
+
+
+
+
+`x-order`
+
+
+
+Explicitly order struct fields
+
+
+
+
+Whether you like certain fields being ordered before others, or you want to perform more efficient packing of your structs, the `x-order` extension is here for you.
+
+Note that `x-order` is 1-indexed - `x-order: 0` is not a valid value.
+
+When an OpenAPI type is deprecated, a deprecation warning can be added in the GoDoc using `x-deprecated-reason`.
+
+We can see this at play with the following schemas:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-order
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ a_name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ properties:
+ a_name:
+ type: string
+ x-order: 2
+ id:
+ type: number
+ x-order: 1
+```
+
+From here, we now get two different forms of the same type definition.
+
+```go
+// Client defines model for Client.
+type Client struct {
+ AName *string `json:"a_name,omitempty"`
+ Id *float32 `json:"id,omitempty"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ Id *float32 `json:"id,omitempty"`
+ AName *string `json:"a_name,omitempty"`
+}
+```
+
+You can see this in more detail in [the example code](examples/extensions/xorder/).
+
+
+
+
+
+
+
+
+## Request/response validation middleware
+
+The generated code that `oapi-codegen` produces has some validation for some incoming data, such as checking for required headers, and when using the [strict server](#strict-server) you get some more validation around the correct usage of the response types.
+
+However, this leaves a lot of validation that needs to be done, which can be tedious to hand-write this logic, especially for large or complex OpenAPI specifications.
+
+To simplify this, we use a middleware, which provides the request validation. The middleware you want to use depends on the server you're using:
+
+
+
+
+
+Server
+
+
+Middleware library
+
+
+
+
+
+
+[Chi](https://github.com/go-chi/chi)
+
+
+
+
+[nethttp-middleware](https://github.com/oapi-codegen/nethttp-middleware)
+
+
+
+
+
+
+
+[Echo](https://github.com/labstack/echo)
+
+
+
+
+[echo-middleware](https://github.com/oapi-codegen/echo-middleware)
+
+
+
+
+
+
+
+[Fiber](https://github.com/gofiber/fiber)
+
+
+
+
+[fiber-middleware](https://github.com/oapi-codegen/fiber-middleware)
+
+
+
+
+
+
+
+
+
+[Gin](https://github.com/gin-gonic/gin)
+
+
+
+
+[gin-middleware](https://github.com/oapi-codegen/gin-middleware)
+
+
+
+
+
+
+
+[gorilla/mux](https://github.com/gorilla/mux)
+
+
+
+
+[nethttp-middleware](https://github.com/oapi-codegen/nethttp-middleware)
+
+
+
+
+
+
+
+
+[Iris](https://github.com/kataras/iris)
+
+
+
+
+[iris-middleware](https://github.com/oapi-codegen/iris-middleware)
+
+
+
+
+
+
+
+
+[1.22+ `net/http`](https://pkg.go.dev/net/http)
+
+
+
+
+[nethttp-middleware](https://github.com/oapi-codegen/nethttp-middleware)
+
+
+
+
+
+
+
+> [!NOTE]
+> It is [not currently possible](https://github.com/deepmap/oapi-codegen/issues/1038) to validate the HTTP response with a middleware.
+
+> [!NOTE]
+> We're also [exploring](https://github.com/oapi-codegen/exp/issues/1) the use of [libopenapi-validator](https://github.com/pb33f/libopenapi-validator/) for request/response validation middleware
+
+## Implementing security
+
+If you're using a specification with [Security Schemes](https://spec.openapis.org/oas/v3.0.3#security-scheme-object) and [Security Requirements](https://spec.openapis.org/oas/v3.0.3#security-requirement-object), you'll want to authenticate and authorize requests.
+
+### On the server
+
+> [!NOTE]
+> Out-of-the-box, the server-side code generated by `oapi-codegen` does not provide security validation.
+>
+> To perform authentication, you will need to use the [validation middleware](#request-response-validation-middleware).
+>
+> In the future, we plan to [implement server-side validation in the generated code](https://github.com/deepmap/oapi-codegen/issues/1524)
+
+To see how this can work, check out the [authenticated API example](examples/authenticated-api/echo).
+
+### On the client
+
+With a generated client, you'll want to use the client's generated `WithRequestEditorFn` function to pass in a given request editor `RequestEditorFn`.
+
+For instance:
+
+```go
+import (
+ "context"
+ "fmt"
+ "log"
+
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider"
+)
+
+func main() {
+ basicAuth, err := securityprovider.NewSecurityProviderBasicAuth("my_user", "my_pass")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ client, err := NewClient("https://....", WithRequestEditorFn(basicAuth.Intercept))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ resp, err := client.GetClient(context.TODO())
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Printf("resp.StatusCode: %v\n", resp.StatusCode)
+}
+```
+
+Notice that we're using a pre-built provider from the [`pkg/securityprovider` package](https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider), which has some inbuilt support for other types of authentication, too.
+
+## Custom code generation
+
+It is possible to extend the inbuilt code generation from `oapi-codegen` using Go's `text/template`s.
+
+You can specify, through your configuration file, the `output-options.user-templates` setting to override the inbuilt templates and use a user-defined template.
+
+> [!NOTE]
+> Filenames given to the `user-templates` configuration must **exactly** match the filename that `oapi-codegen` is looking for
+
+### Local paths
+
+Within your configuration file, you can specify relative or absolute paths to a file to reference for the template, such as:
+
+```yaml
+# yaml-language-server: $schema=https://raw.githubusercontent.com/deepmap/oapi-codegen/HEAD/configuration-schema.json
+# ...
+output-options:
+ user-templates:
+ client-with-responses.tmpl: ./custom-template.tmpl
+ additional-properties.tmpl: /tmp/foo.bar
+ typedef.tmpl: no-prefix.tmpl
+```
+
+> [!WARN]
+> We do not interpolate `~` or `$HOME` (or other environment variables) in paths given
+
+### HTTPS paths
+
+It is also possible to use HTTPS URLs.
+
+> [!WARNING]
+> Although possible, this does lead to `oapi-codegen` executions not necessarily being reproducible. It's recommended to vendor (copy) the OpenAPI spec into your codebase and reference it locally
+>
+> See [this blog post](https://www.jvt.me/posts/2024/04/27/github-actions-update-file/) for an example of how to use GitHub Actions to manage the updates of files across repos
+>
+> This will be disabled by default (but possible to turn back on via configuration) [in the future](https://github.com/deepmap/oapi-codegen/issues/1564)
+
+To use it, you can use the following configuration:
+
+```yaml
+# yaml-language-server: $schema=https://raw.githubusercontent.com/deepmap/oapi-codegen/HEAD/configuration-schema.json
+# ...
+output-options:
+ user-templates:
+ # The following are referencing a version of the default client-with-responses.tmpl file, but loaded in through GitHub's raw.githubusercontent.com. The general form to use raw.githubusercontent.com is as follows https://raw.githubusercontent.com////path/to/template/template.tmpl
+
+ # Alternatively using raw.githubusercontent.com with a hash
+ client-with-responses.tmpl: https://raw.githubusercontent.com/deepmap/oapi-codegen/ad5eada4f3ccc28a88477cef62ea21c17fc8aa01/pkg/codegen/templates/client-with-responses.tmpl
+ # Alternatively using raw.githubusercontent.com with a tag
+ client-with-responses.tmpl: https://raw.githubusercontent.com/deepmap/oapi-codegen/v2.1.0/pkg/codegen/templates/client-with-responses.tmpl
+ # Alternatively using raw.githubusercontent.com with a branch
+ client-with-responses.tmpl: https://raw.githubusercontent.com/deepmap/oapi-codegen/master/pkg/codegen/templates/client-with-responses.tmpl
+```
+
+> [!WARNING]
+> If using URLs that pull locations from a Git repo, such as `raw.githubusercontent.com`, it is strongly encouraged to use a tag or a raw commit hash instead of a branch like `main`. Tracking a branch can lead to unexpected API drift, and loss of the ability to reproduce a build.
+
+### Inline template
+
+It's also possible to set the templates inline in the configuration file:
+
+```yaml
+# yaml-language-server: $schema=https://raw.githubusercontent.com/deepmap/oapi-codegen/HEAD/configuration-schema.json
+# ...
+output-options:
+ user-templates:
+ # NOTE the use of the `|` (pipe symbol) here to denote that this is a
+ # multi-line statement that should preserve newlines. More reading:
+ # https://stackoverflow.com/a/18708156/2257038 and
+ # https://stackoverflow.com/a/15365296/2257038
+ client-with-responses.tmpl: |
+ // ClientWithResponses builds on ClientInterface to offer response payloads
+ type ClientWithResponses struct {
+ ClientInterface
+ }
+ ...
+```
+
+### Using the Go package
+
+Alternatively, you are able to use the underlying code generation as a package, which [will be documented in the future](https://github.com/deepmap/oapi-codegen/issues/1487).
+
+## Additional Properties (`additionalProperties`)
+
+[OpenAPI Schemas](https://spec.openapis.org/oas/v3.0.3.html#schema-object) implicitly accept `additionalProperties`, meaning that any fields provided, but not explicitly defined via properties on the schema are accepted as input, and propagated. When unspecified, OpenAPI defines that the `additionalProperties` field is assumed to be `true`.
+
+For simplicity, and to remove a fair bit of duplication and boilerplate, `oapi-codegen` decides to ignore the implicit `additionalProperties: true`, and instead requires you to specify the `additionalProperties` key to generate the boilerplate.
+
+> [!NOTE]
+> In the future [this will be possible](https://github.com/deepmap/oapi-codegen/issues/1514) to disable this functionality, and honour the implicit `additionalProperties: true`
+
+Below you can see some examples of how `additionalProperties` affects the generated code.
+
+### Implicit `additionalProperties: true` / no `additionalProperties` set
+
+```yaml
+components:
+ schemas:
+ Thing:
+ type: object
+ required:
+ - id
+ properties:
+ id:
+ type: integer
+ # implicit additionalProperties: true
+```
+
+Will generate:
+
+```go
+// Thing defines model for Thing.
+type Thing struct {
+ Id int `json:"id"`
+}
+
+// with no generated boilerplate nor the `AdditionalProperties` field
+```
+
+### Explicit `additionalProperties: true`
+
+```yaml
+components:
+ schemas:
+ Thing:
+ type: object
+ required:
+ - id
+ properties:
+ id:
+ type: integer
+ # explicit true
+ additionalProperties: true
+```
+
+Will generate:
+
+```go
+// Thing defines model for Thing.
+type Thing struct {
+ Id int `json:"id"`
+ AdditionalProperties map[string]interface{} `json:"-"`
+}
+
+// with generated boilerplate below
+```
+
+
+
+Boilerplate
+
+```go
+
+// Getter for additional properties for Thing. Returns the specified
+// element and whether it was found
+func (a Thing) Get(fieldName string) (value interface{}, found bool) {
+ if a.AdditionalProperties != nil {
+ value, found = a.AdditionalProperties[fieldName]
+ }
+ return
+}
+
+// Setter for additional properties for Thing
+func (a *Thing) Set(fieldName string, value interface{}) {
+ if a.AdditionalProperties == nil {
+ a.AdditionalProperties = make(map[string]interface{})
+ }
+ a.AdditionalProperties[fieldName] = value
+}
+
+// Override default JSON handling for Thing to handle AdditionalProperties
+func (a *Thing) UnmarshalJSON(b []byte) error {
+ object := make(map[string]json.RawMessage)
+ err := json.Unmarshal(b, &object)
+ if err != nil {
+ return err
+ }
+
+ if raw, found := object["id"]; found {
+ err = json.Unmarshal(raw, &a.Id)
+ if err != nil {
+ return fmt.Errorf("error reading 'id': %w", err)
+ }
+ delete(object, "id")
+ }
+
+ if len(object) != 0 {
+ a.AdditionalProperties = make(map[string]interface{})
+ for fieldName, fieldBuf := range object {
+ var fieldVal interface{}
+ err := json.Unmarshal(fieldBuf, &fieldVal)
+ if err != nil {
+ return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err)
+ }
+ a.AdditionalProperties[fieldName] = fieldVal
+ }
+ }
+ return nil
+}
+
+// Override default JSON handling for Thing to handle AdditionalProperties
+func (a Thing) MarshalJSON() ([]byte, error) {
+ var err error
+ object := make(map[string]json.RawMessage)
+
+ object["id"], err = json.Marshal(a.Id)
+ if err != nil {
+ return nil, fmt.Errorf("error marshaling 'id': %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)
+}
+```
+
+
+
+
+### `additionalProperties` as `integer`s
+
+```yaml
+components:
+ schemas:
+ Thing:
+ type: object
+ required:
+ - id
+ properties:
+ id:
+ type: integer
+ # simple type
+ additionalProperties:
+ type: integer
+```
+
+Will generate:
+
+```go
+// Thing defines model for Thing.
+type Thing struct {
+ Id int `json:"id"`
+ AdditionalProperties map[string]int `json:"-"`
+}
+
+// with generated boilerplate below
+```
+
+
+
+Boilerplate
+
+```go
+// Getter for additional properties for Thing. Returns the specified
+// element and whether it was found
+func (a Thing) Get(fieldName string) (value int, found bool) {
+ if a.AdditionalProperties != nil {
+ value, found = a.AdditionalProperties[fieldName]
+ }
+ return
+}
+
+// Setter for additional properties for Thing
+func (a *Thing) Set(fieldName string, value int) {
+ if a.AdditionalProperties == nil {
+ a.AdditionalProperties = make(map[string]int)
+ }
+ a.AdditionalProperties[fieldName] = value
+}
+
+// Override default JSON handling for Thing to handle AdditionalProperties
+func (a *Thing) UnmarshalJSON(b []byte) error {
+ object := make(map[string]json.RawMessage)
+ err := json.Unmarshal(b, &object)
+ if err != nil {
+ return err
+ }
+
+ if raw, found := object["id"]; found {
+ err = json.Unmarshal(raw, &a.Id)
+ if err != nil {
+ return fmt.Errorf("error reading 'id': %w", err)
+ }
+ delete(object, "id")
+ }
+
+ if len(object) != 0 {
+ a.AdditionalProperties = make(map[string]int)
+ for fieldName, fieldBuf := range object {
+ var fieldVal int
+ err := json.Unmarshal(fieldBuf, &fieldVal)
+ if err != nil {
+ return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err)
+ }
+ a.AdditionalProperties[fieldName] = fieldVal
+ }
+ }
+ return nil
+}
+
+// Override default JSON handling for Thing to handle AdditionalProperties
+func (a Thing) MarshalJSON() ([]byte, error) {
+ var err error
+ object := make(map[string]json.RawMessage)
+
+ object["id"], err = json.Marshal(a.Id)
+ if err != nil {
+ return nil, fmt.Errorf("error marshaling 'id': %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)
+}
+```
+
+
+
+### `additionalProperties` with an object
+
+```yaml
+components:
+ schemas:
+ Thing:
+ type: object
+ required:
+ - id
+ properties:
+ id:
+ type: integer
+ # object
+ additionalProperties:
+ type: object
+ properties:
+ foo:
+ type: string
+```
+
+Will generate:
+
+```go
+// Thing defines model for Thing.
+type Thing struct {
+ Id int `json:"id"`
+ AdditionalProperties map[string]struct {
+ Foo *string `json:"foo,omitempty"`
+ } `json:"-"`
+}
+
+// with generated boilerplate below
+```
+
+
+
+Boilerplate
+
+```go
+// Getter for additional properties for Thing. Returns the specified
+// element and whether it was found
+func (a Thing) Get(fieldName string) (value struct {
+ Foo *string `json:"foo,omitempty"`
+}, found bool) {
+ if a.AdditionalProperties != nil {
+ value, found = a.AdditionalProperties[fieldName]
+ }
+ return
+}
+
+// Setter for additional properties for Thing
+func (a *Thing) Set(fieldName string, value struct {
+ Foo *string `json:"foo,omitempty"`
+}) {
+ if a.AdditionalProperties == nil {
+ a.AdditionalProperties = make(map[string]struct {
+ Foo *string `json:"foo,omitempty"`
+ })
+ }
+ a.AdditionalProperties[fieldName] = value
+}
+
+// Override default JSON handling for Thing to handle AdditionalProperties
+func (a *Thing) UnmarshalJSON(b []byte) error {
+ object := make(map[string]json.RawMessage)
+ err := json.Unmarshal(b, &object)
+ if err != nil {
+ return err
+ }
+
+ if raw, found := object["id"]; found {
+ err = json.Unmarshal(raw, &a.Id)
+ if err != nil {
+ return fmt.Errorf("error reading 'id': %w", err)
+ }
+ delete(object, "id")
+ }
+
+ if len(object) != 0 {
+ a.AdditionalProperties = make(map[string]struct {
+ Foo *string `json:"foo,omitempty"`
+ })
+ for fieldName, fieldBuf := range object {
+ var fieldVal struct {
+ Foo *string `json:"foo,omitempty"`
+ }
+ 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 Thing to handle AdditionalProperties
+func (a Thing) MarshalJSON() ([]byte, error) {
+ var err error
+ object := make(map[string]json.RawMessage)
+
+ object["id"], err = json.Marshal(a.Id)
+ if err != nil {
+ return nil, fmt.Errorf("error marshaling 'id': %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)
+}
+```
+
+
+
+## Changing the names of generated types
+
+As of `oapi-codegen` v2.2.0, it is now possible to use the `output-options` configuration's `name-normalizer` to define the logic for how to convert an OpenAPI name (i.e. an Operation ID or a Schema name) and construct a Go type name.
+
+
+
+Example, using default configuration
+
+By default, `oapi-codegen` will perform camel-case conversion, so for a spec such as:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Example code for the `name-normalizer` output option
+paths:
+ /api/pets/{petId}:
+ get:
+ summary: Get pet given identifier.
+ operationId: getHttpPet
+ parameters:
+ - name: petId
+ in: path
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: valid pet
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet'
+components:
+ schemas:
+ Pet:
+ type: object
+ required:
+ - uuid
+ - name
+ properties:
+ uuid:
+ type: string
+ description: The pet uuid.
+ name:
+ type: string
+ description: The name of the pet.
+ Error:
+ required:
+ - code
+ - message
+ properties:
+ code:
+ type: integer
+ format: int32
+ description: Error code
+ message:
+ type: string
+ description: Error message
+ OneOf2things:
+ description: "Notice that the `things` is not capitalised"
+ oneOf:
+ - type: object
+ required:
+ - id
+ properties:
+ id:
+ type: integer
+ - type: object
+ required:
+ - id
+ properties:
+ id:
+ type: string
+ format: uuid
+```
+
+This will produce:
+
+```go
+// OneOf2things Notice that the `things` is not capitalised
+type OneOf2things struct {
+ union json.RawMessage
+}
+
+// Pet defines model for Pet.
+type Pet struct {
+ // Name The name of the pet.
+ Name string `json:"name"`
+
+ // Uuid The pet uuid.
+ Uuid string `json:"uuid"`
+}
+
+// The interface specification for the client above.
+type ClientInterface interface {
+ // GetHttpPet request
+ GetHttpPet(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+```
+
+
+
+
+
+Example, using ToCamelCaseWithInitialisms
+
+By default, `oapi-codegen` will perform camel-case conversion, so for a spec such as:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Example code for the `name-normalizer` output option
+paths:
+ /api/pets/{petId}:
+ get:
+ summary: Get pet given identifier.
+ operationId: getHttpPet
+ parameters:
+ - name: petId
+ in: path
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: valid pet
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet'
+components:
+ schemas:
+ Pet:
+ type: object
+ required:
+ - uuid
+ - name
+ properties:
+ uuid:
+ type: string
+ description: The pet uuid.
+ name:
+ type: string
+ description: The name of the pet.
+ Error:
+ required:
+ - code
+ - message
+ properties:
+ code:
+ type: integer
+ format: int32
+ description: Error code
+ message:
+ type: string
+ description: Error message
+ OneOf2things:
+ description: "Notice that the `things` is not capitalised"
+ oneOf:
+ - type: object
+ required:
+ - id
+ properties:
+ id:
+ type: integer
+ - type: object
+ required:
+ - id
+ properties:
+ id:
+ type: string
+ format: uuid
+```
+
+This will produce:
+
+```go
+// OneOf2things Notice that the `things` is not capitalised
+type OneOf2things struct {
+ union json.RawMessage
+}
+
+// Pet defines model for Pet.
+type Pet struct {
+ // Name The name of the pet.
+ Name string `json:"name"`
+
+ // UUID The pet uuid.
+ UUID string `json:"uuid"`
+}
+
+// The interface specification for the client above.
+type ClientInterface interface {
+ // GetHTTPPet request
+ GetHTTPPet(ctx context.Context, petID string, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+```
+
+
+
+
+For more details of what the resulting code looks like, check out [the test cases](internal/test/outputoptions/name-normalizer/).
+
+## Examples
+
+The [examples directory](examples) contains some additional cases which are useful examples for how to use `oapi-codegen`, including how you'd take the Petstore API and implement it with `oapi-codegen`.
+
+You could also find some cases of how the project can be used by checking out our [internal test cases](internal/test) which are real-world usages that make up our regression tests.
+
+### Blog posts
+
+We love reading posts by the community about how to use the project.
+
+Here are a few we've found around the Web:
+
+- [Building a Go RESTful API with design-first OpenAPI contracts](https://www.jvt.me/posts/2022/07/12/go-openapi-server/)
+- [A Practical Guide to Using oapi-codegen in Golang API Development with the Fiber Framework](https://medium.com/@fikihalan/a-practical-guide-to-using-oapi-codegen-in-golang-api-development-with-the-fiber-framework-bce2a59380ae)
+- [Generating Go server code from OpenAPI 3 definitions](https://ldej.nl/post/generating-go-from-openapi-3/)
+- [Go Client Code Generation from Swagger and OpenAPI](https://medium.com/@kyodo-tech/go-client-code-generation-from-swagger-and-openapi-a0576831836c)
+- [Go oapi-codegen + request validation](https://blog.commitsmart.com/go-oapi-codegen-request-validation-285398b37dc8)
+
+Got one to add? Please raise a PR!
+
+## Frequently Asked Questions (FAQs)
+
+### How does `oapi-codegen` handle `anyOf`, `allOf` and `oneOf`?
+
+`oapi-codegen` supports `anyOf`, `allOf` and `oneOf` for generated code.
+
+For instance, through the following OpenAPI spec:
+
+```yaml
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Using complex schemas
+ description: An example of `anyOf`, `allOf` and `oneOf`
+components:
+ schemas:
+ # base types
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ Identity:
+ type: object
+ required:
+ - issuer
+ properties:
+ issuer:
+ type: string
+
+ # allOf performs a union of all types defined
+ ClientWithId:
+ allOf:
+ - $ref: '#/components/schemas/Client'
+ - properties:
+ id:
+ type: integer
+ required:
+ - id
+
+ # allOf performs a union of all types defined, but if there's a duplicate field defined, it'll be overwritten by the last schema
+ # https://github.com/deepmap/oapi-codegen/issues/1569
+ IdentityWithDuplicateField:
+ allOf:
+ # `issuer` will be ignored
+ - $ref: '#/components/schemas/Identity'
+ # `issuer` will be ignored
+ - properties:
+ issuer:
+ type: integer
+ # `issuer` will take precedence
+ - properties:
+ issuer:
+ type: object
+ properties:
+ name:
+ type: string
+ required:
+ - name
+
+ # anyOf results in a type that has an `AsClient`/`MergeClient`/`FromClient` and an `AsIdentity`/`MergeIdentity`/`FromIdentity` method so you can choose which of them you want to retrieve
+ ClientAndMaybeIdentity:
+ anyOf:
+ - $ref: '#/components/schemas/Client'
+ - $ref: '#/components/schemas/Identity'
+
+ # oneOf results in a type that has an `AsClient`/`MergeClient`/`FromClient` and an `AsIdentity`/`MergeIdentity`/`FromIdentity` method so you can choose which of them you want to retrieve
+ ClientOrIdentity:
+ oneOf:
+ - $ref: '#/components/schemas/Client'
+ - $ref: '#/components/schemas/Identity'
+```
+
+This results in the following types:
+
+
+
+Base types
+
+```go
+// Client defines model for Client.
+type Client struct {
+ Name string `json:"name"`
+}
+
+// Identity defines model for Identity.
+type Identity struct {
+ Issuer string `json:"issuer"`
+}
+```
+
+
+
+
+
+allOf
+
+```go
+// ClientWithId defines model for ClientWithId.
+type ClientWithId struct {
+ Id int `json:"id"`
+ Name string `json:"name"`
+}
+
+// IdentityWithDuplicateField defines model for IdentityWithDuplicateField.
+type IdentityWithDuplicateField struct {
+ Issuer struct {
+ Name string `json:"name"`
+ } `json:"issuer"`
+}
+```
+
+
+
+
+
+anyOf
+
+```go
+import (
+ "encoding/json"
+
+ "github.com/oapi-codegen/runtime"
+)
+
+// ClientAndMaybeIdentity defines model for ClientAndMaybeIdentity.
+type ClientAndMaybeIdentity struct {
+ union json.RawMessage
+}
+
+// AsClient returns the union data inside the ClientAndMaybeIdentity as a Client
+func (t ClientAndMaybeIdentity) AsClient() (Client, error) {
+ var body Client
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromClient overwrites any union data inside the ClientAndMaybeIdentity as the provided Client
+func (t *ClientAndMaybeIdentity) FromClient(v Client) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeClient performs a merge with any union data inside the ClientAndMaybeIdentity, using the provided Client
+func (t *ClientAndMaybeIdentity) MergeClient(v Client) error {
+ b, err := json.Marshal(v)
+ if err != nil {
+ return err
+ }
+
+ merged, err := runtime.JSONMerge(t.union, b)
+ t.union = merged
+ return err
+}
+
+// AsIdentity returns the union data inside the ClientAndMaybeIdentity as a Identity
+func (t ClientAndMaybeIdentity) AsIdentity() (Identity, error) {
+ var body Identity
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromIdentity overwrites any union data inside the ClientAndMaybeIdentity as the provided Identity
+func (t *ClientAndMaybeIdentity) FromIdentity(v Identity) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeIdentity performs a merge with any union data inside the ClientAndMaybeIdentity, using the provided Identity
+func (t *ClientAndMaybeIdentity) MergeIdentity(v Identity) 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 ClientAndMaybeIdentity) MarshalJSON() ([]byte, error) {
+ b, err := t.union.MarshalJSON()
+ return b, err
+}
+
+func (t *ClientAndMaybeIdentity) UnmarshalJSON(b []byte) error {
+ err := t.union.UnmarshalJSON(b)
+ return err
+}
+
+
+```
+
+
+
+
+
+oneOf
+
+```go
+// AsClient returns the union data inside the ClientOrIdentity as a Client
+func (t ClientOrIdentity) AsClient() (Client, error) {
+ var body Client
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromClient overwrites any union data inside the ClientOrIdentity as the provided Client
+func (t *ClientOrIdentity) FromClient(v Client) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeClient performs a merge with any union data inside the ClientOrIdentity, using the provided Client
+func (t *ClientOrIdentity) MergeClient(v Client) error {
+ b, err := json.Marshal(v)
+ if err != nil {
+ return err
+ }
+
+ merged, err := runtime.JSONMerge(t.union, b)
+ t.union = merged
+ return err
+}
+
+// AsIdentity returns the union data inside the ClientOrIdentity as a Identity
+func (t ClientOrIdentity) AsIdentity() (Identity, error) {
+ var body Identity
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromIdentity overwrites any union data inside the ClientOrIdentity as the provided Identity
+func (t *ClientOrIdentity) FromIdentity(v Identity) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeIdentity performs a merge with any union data inside the ClientOrIdentity, using the provided Identity
+func (t *ClientOrIdentity) MergeIdentity(v Identity) 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 ClientOrIdentity) MarshalJSON() ([]byte, error) {
+ b, err := t.union.MarshalJSON()
+ return b, err
+}
+
+func (t *ClientOrIdentity) UnmarshalJSON(b []byte) error {
+ err := t.union.UnmarshalJSON(b)
+ return err
+}
+```
+
+
+
+For more info, check out [the example code](examples/anyof-allof-oneof/).
+
+### How can I ignore parts of the spec I don't care about?
+
+By default, `oapi-codegen` will generate everything from the specification.
+
+If you'd like to reduce what's generated, you can use one of a few options in [the configuration file](#usage) to tune the generation of the resulting output:
+
+```yaml
+# yaml-language-server: $schema=https://raw.githubusercontent.com/deepmap/oapi-codegen/HEAD/configuration-schema.json
+output-options:
+ include-tags: []
+ exclude-tags: []
+ include-operation-ids: []
+ exclude-operation-ids: []
+ exclude-schemas: []
+```
+
+Check [the docs](https://pkg.go.dev/github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen#OutputOptions) for more details of usage.
+
+### Should I commit the generated code?
+
+We recommend doing so, yes, for the following reasons:
+
+- It means it's easier to view the impact of a change - be it due to an upgrade of `oapi-codegen`, or a change to your spec - and has helped catch (possibly) breaking changes in the past more easily
+- It then allows your codebase to be consumed as a library, as all the files are committed
+
+This means you'll need to have your CI/CD pipeline validate that generated files are all up-to-date, but that's a fairly straightforward piece of work.
+
+### Should I lint the generated code?
+
+We really ask that you don't. Although it intends to be idiomatic Go code, it's not expected to pass all the various linting rules that your project may apply.
+
+> [!NOTE]
+> We will, on occasion, improve the generated code to fix some linting warnings, such as those from `go vet`, but this should not be an expected change.
+
+### I've just updated my version of `kin-openapi`, and now I can't build my code 😠
+
+The [kin-openapi](https://github.com/getkin/kin-openapi) project - which we 💜 for providing a great library and set of tooling for interacting with OpenAPI - is a pre-v1 release, which means that they're within their rights to push breaking changes.
+
+This may lead to breakage in your consuming code, and if so, sorry that's happened!
+
+We'll be aware of the issue, and will work to update both the core `oapi-codegen` and the middlewares accordingly.
+
+## Sponsors
+
+For the most part, `oapi-codegen` is maintained in two busy peoples' free time. As noted in [Creating a more sustainable model for `oapi-codegen` in the future](https://github.com/deepmap/oapi-codegen/discussions/1606), we're looking to make this a more sustainable project in the future.
+
+We're very appreciative of [the many contributors over the years](https://github.com/deepmap/oapi-codegen/graphs/contributors) and the ongoing use of the project 💜
+
+Please consider sponsoring us through GitHub Sponsors either [on the organisation](https://github.com/sponsors/oapi-codegen/) or [directly for Jamie](https://github.com/sponsors/jamietanna/), which helps work towards us being able to maintain the project long term.
+
+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.
+
+We are currently generously sponsored by the following folks, each of whom provide sponsorship for 1 hour of work a month:
+
+
+
+
+
+
+
+
+
+
diff --git a/cmd/oapi-codegen/oapi-codegen.go b/cmd/oapi-codegen/oapi-codegen.go
index 3864879ca..cba80bf2c 100644
--- a/cmd/oapi-codegen/oapi-codegen.go
+++ b/cmd/oapi-codegen/oapi-codegen.go
@@ -25,8 +25,8 @@ import (
"gopkg.in/yaml.v2"
- "github.com/deepmap/oapi-codegen/v2/pkg/codegen"
- "github.com/deepmap/oapi-codegen/v2/pkg/util"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/util"
)
func errExit(format string, args ...interface{}) {
@@ -99,7 +99,7 @@ func main() {
// All flags below are deprecated, and will be removed in a future release. Please do not
// update their behavior.
flag.StringVar(&flagGenerate, "generate", "types,client,server,spec",
- `Comma-separated list of code to generate; valid options: "types", "client", "chi-server", "server", "gin", "gorilla", "spec", "skip-fmt", "skip-prune", "fiber", "iris".`)
+ `Comma-separated list of code to generate; valid options: "types", "client", "chi-server", "server", "gin", "gorilla", "spec", "skip-fmt", "skip-prune", "fiber", "iris", "std-http".`)
flag.StringVar(&flagIncludeTags, "include-tags", "", "Only include operations with the given tags. Comma-separated list of tags.")
flag.StringVar(&flagExcludeTags, "exclude-tags", "", "Exclude operations that are tagged with the given tags. Comma-separated list of tags.")
flag.StringVar(&flagIncludeOperationIDs, "include-operation-ids", "", "Only include operations with the given operation-ids. Comma-separated list of operation-ids.")
@@ -283,6 +283,10 @@ func main() {
errExit("error loading swagger spec in %s\n: %s", flag.Arg(0), err)
}
+ if strings.HasPrefix(swagger.OpenAPI, "3.1.") {
+ fmt.Println("WARNING: You are using an OpenAPI 3.1.x specification, which is not yet supported by oapi-codegen (https://github.com/deepmap/oapi-codegen/issues/373) and so some functionality may not be available. Until oapi-codegen supports OpenAPI 3.1, it is recommended to downgrade your spec to 3.0.x")
+ }
+
if len(noVCSVersionOverride) > 0 {
opts.Configuration.NoVCSVersionOverride = &noVCSVersionOverride
}
@@ -486,6 +490,8 @@ func generationTargets(cfg *codegen.Configuration, targets []string) error {
opts.GinServer = true
case "gorilla", "gorilla-server":
opts.GorillaServer = true
+ case "std-http", "std-http-server":
+ opts.StdHTTPServer = true
case "strict-server":
opts.Strict = true
case "client":
diff --git a/cmd/oapi-codegen/oapi-codegen_test.go b/cmd/oapi-codegen/oapi-codegen_test.go
index 689a8e9a0..9d9f06c20 100644
--- a/cmd/oapi-codegen/oapi-codegen_test.go
+++ b/cmd/oapi-codegen/oapi-codegen_test.go
@@ -3,7 +3,7 @@ package main
import (
"testing"
- "github.com/deepmap/oapi-codegen/v2/pkg/util"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/util"
)
func TestLoader(t *testing.T) {
diff --git a/configuration-schema.json b/configuration-schema.json
new file mode 100644
index 000000000..212c13073
--- /dev/null
+++ b/configuration-schema.json
@@ -0,0 +1,233 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "description": "Configuration files for oapi-codegen",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "package": {
+ "type": "string",
+ "description": "Go package name to generate the code under"
+ },
+ "generate": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Generate specifies which supported output formats to generate",
+ "properties": {
+ "iris-server": {
+ "type": "boolean",
+ "description": "IrisServer specifies whether to generate iris server boilerplate"
+ },
+ "chi-server": {
+ "type": "boolean",
+ "description": "ChiServer specifies whether to generate chi server boilerplate"
+ },
+ "fiber-server": {
+ "type": "boolean",
+ "description": "FiberServer specifies whether to generate fiber server boilerplate"
+ },
+ "echo-server": {
+ "type": "boolean",
+ "description": "EchoServer specifies whether to generate echo server boilerplate"
+ },
+ "gin-server": {
+ "type": "boolean",
+ "description": "GinServer specifies whether to generate gin server boilerplate"
+ },
+ "gorilla-server": {
+ "type": "boolean",
+ "description": "GorillaServer specifies whether to generate Gorilla server boilerplate"
+ },
+ "std-http-server": {
+ "type": "boolean",
+ "description": "StdHTTPServer specifies whether to generate stdlib http server boilerplate"
+ },
+ "strict-server": {
+ "type": "boolean",
+ "description": "Strict specifies whether to generate strict server wrapper"
+ },
+ "client": {
+ "type": "boolean",
+ "description": "Client specifies whether to generate client boilerplate"
+ },
+ "models": {
+ "type": "boolean",
+ "description": "Models specifies whether to generate type definitions"
+ },
+ "embedded-spec": {
+ "type": "boolean",
+ "description": "EmbeddedSpec indicates whether to embed the swagger spec in the generated code"
+ }
+ }
+ },
+ "compatibility": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "",
+ "properties": {
+ "old-merge-schemas": {
+ "type": "boolean",
+ "description": "In the past, we merged schemas for `allOf` by inlining each schema within the schema list. This approach, though, is incorrect because `allOf` merges at the schema definition level, not at the resulting model level. So, new behavior merges OpenAPI specs but generates different code than we have in the past. Set OldMergeSchemas to true for the old behavior. Please see https://github.com/deepmap/oapi-codegen/issues/531"
+ },
+ "old-enum-conflicts": {
+ "type": "boolean",
+ "description": "Enum values can generate conflicting typenames, so we've updated the code for enum generation to avoid these conflicts, but it will result in some enum types being renamed in existing code. Set OldEnumConflicts to true to revert to old behavior. Please see: Please see https://github.com/deepmap/oapi-codegen/issues/549"
+ },
+ "old-aliasing": {
+ "type": "boolean",
+ "description": "It was a mistake to generate a go type definition for every $ref in the OpenAPI schema. New behavior uses type aliases where possible, but this can generate code which breaks existing builds. Set OldAliasing to true for old behavior. Please see https://github.com/deepmap/oapi-codegen/issues/549"
+ },
+ "disable-flatten-additional-properties": {
+ "type": "boolean",
+ "description": "When an object contains no members, and only an additionalProperties specification, it is flattened to a map"
+ },
+ "disable-required-readonly-as-pointer": {
+ "type": "boolean",
+ "description": "When an object property is both required and readOnly the go model is generated as a pointer. Set DisableRequiredReadOnlyAsPointer to true to mark them as non pointer. Please see https://github.com/deepmap/oapi-codegen/issues/604"
+ },
+ "always-prefix-enum-values": {
+ "type": "boolean",
+ "description": "When set to true, always prefix enum values with their type name instead of only when typenames would be conflicting."
+ },
+ "apply-chi-middleware-first-to-last": {
+ "type": "boolean",
+ "description": "Our generated code for Chi has historically inverted the order in which Chi middleware is applied such that the last invoked middleware ends up executing first in the Chi chain This resolves the behavior such that middlewares are chained in the order they are invoked. Please see https://github.com/deepmap/oapi-codegen/issues/786"
+ },
+ "apply-gorilla-middleware-first-to-last": {
+ "type": "boolean",
+ "description": "Our generated code for gorilla/mux has historically inverted the order in which gorilla/mux middleware is applied such that the last invoked middleware ends up executing first in the middlewares chain This resolves the behavior such that middlewares are chained in the order they are invoked. Please see https://github.com/deepmap/oapi-codegen/issues/841"
+ },
+ "circular-reference-limit": {
+ "type": "integer",
+ "description": "CircularReferenceLimit allows controlling the limit for circular reference checking. In some OpenAPI specifications, we have a higher number of circular references than is allowed out-of-the-box, but can be tuned to allow traversing them."
+ }
+ }
+ },
+ "output-options": {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "OutputOptions are used to modify the output code in some way",
+ "properties": {
+ "skip-fmt": {
+ "type": "boolean",
+ "description": "Whether to skip go imports on the generated code"
+ },
+ "skip-prune": {
+ "type": "boolean",
+ "description": "Whether to skip pruning unused components on the generated code"
+ },
+ "include-tags": {
+ "type": "array",
+ "description": "Only include operations that have one of these tags. Ignored when empty.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-tags": {
+ "type": "array",
+ "description": "Exclude operations that have one of these tags. Ignored when empty.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "include-operation-ids": {
+ "type": "array",
+ "description": "Only include operations that have one of these operation-ids. Ignored when empty.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exclude-operation-ids": {
+ "type": "array",
+ "description": "Exclude operations that have one of these operation-ids. Ignored when empty.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "user-templates": {
+ "type": "object",
+ "description": "Override built-in templates from user-provided files",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "exclude-schemas": {
+ "type": "array",
+ "description": "Exclude from generation schemas with given names. Ignored when empty.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "response-type-suffix": {
+ "type": "string",
+ "description": "The suffix used for responses types"
+ },
+ "client-type-name": {
+ "type": "string",
+ "description": "Override the default generated client type with the value"
+ },
+ "initialism-overrides": {
+ "type": "boolean",
+ "description": "Whether to use the initialism overrides"
+ },
+ "nullable-type": {
+ "type": "boolean",
+ "description": "Whether to generate nullable type for nullable fields"
+ },
+ "disable-type-aliases-for-type": {
+ "type": "array",
+ "description": "DisableTypeAliasesForType allows defining which OpenAPI `type`s will explicitly not use type aliases",
+ "items": {
+ "type": "string",
+ "enum": [
+ "array"
+ ]
+ }
+ },
+ "name-normalizer": {
+ "type": "string",
+ "description": "NameNormalizer is the method used to normalize Go names and types, for instance converting the text `MyApi` to `MyAPI`. Corresponds with the constants defined for `codegen.NameNormalizerFunction`",
+ "default": "ToCamelCase",
+ "enum": [
+ "ToCamelCase",
+ "ToCamelCaseWithDigits",
+ "ToCamelCaseWithInitialisms"
+ ]
+ }
+ }
+ },
+ "import-mapping": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string",
+ "description": "ImportMapping specifies the golang package path for each external reference"
+ }
+ },
+ "additional-imports": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "alias": {
+ "type": "string"
+ },
+ "package": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "package"
+ ]
+ },
+ "description": "AdditionalImports defines any additional Go imports to add to the generated code"
+ },
+ "output": {
+ "type": "string",
+ "description": "The filename to output"
+ }
+ },
+ "required": [
+ "package",
+ "output"
+ ]
+}
diff --git a/examples/Makefile b/examples/Makefile
new file mode 100644
index 000000000..93a6cdb16
--- /dev/null
+++ b/examples/Makefile
@@ -0,0 +1,17 @@
+lint:
+ $(GOBIN)/golangci-lint run ./...
+
+lint-ci:
+ $(GOBIN)/golangci-lint run ./... --out-format=colored-line-number --timeout=5m
+
+generate:
+ go generate ./...
+
+test:
+ go test -cover ./...
+
+tidy:
+ go mod tidy
+
+tidy-ci:
+ tidied -verbose
diff --git a/examples/anyof-allof-oneof/anyofallofoneof.gen.go b/examples/anyof-allof-oneof/anyofallofoneof.gen.go
new file mode 100644
index 000000000..99b861683
--- /dev/null
+++ b/examples/anyof-allof-oneof/anyofallofoneof.gen.go
@@ -0,0 +1,167 @@
+// Package anyofallofoneof provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package anyofallofoneof
+
+import (
+ "encoding/json"
+
+ "github.com/oapi-codegen/runtime"
+)
+
+// Client defines model for Client.
+type Client struct {
+ Name string `json:"name"`
+}
+
+// ClientAndMaybeIdentity defines model for ClientAndMaybeIdentity.
+type ClientAndMaybeIdentity struct {
+ union json.RawMessage
+}
+
+// ClientOrIdentity defines model for ClientOrIdentity.
+type ClientOrIdentity struct {
+ union json.RawMessage
+}
+
+// ClientWithId defines model for ClientWithId.
+type ClientWithId struct {
+ Id int `json:"id"`
+ Name string `json:"name"`
+}
+
+// Identity defines model for Identity.
+type Identity struct {
+ Issuer string `json:"issuer"`
+}
+
+// IdentityWithDuplicateField defines model for IdentityWithDuplicateField.
+type IdentityWithDuplicateField struct {
+ Issuer struct {
+ Name string `json:"name"`
+ } `json:"issuer"`
+}
+
+// AsClient returns the union data inside the ClientAndMaybeIdentity as a Client
+func (t ClientAndMaybeIdentity) AsClient() (Client, error) {
+ var body Client
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromClient overwrites any union data inside the ClientAndMaybeIdentity as the provided Client
+func (t *ClientAndMaybeIdentity) FromClient(v Client) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeClient performs a merge with any union data inside the ClientAndMaybeIdentity, using the provided Client
+func (t *ClientAndMaybeIdentity) MergeClient(v Client) error {
+ b, err := json.Marshal(v)
+ if err != nil {
+ return err
+ }
+
+ merged, err := runtime.JSONMerge(t.union, b)
+ t.union = merged
+ return err
+}
+
+// AsIdentity returns the union data inside the ClientAndMaybeIdentity as a Identity
+func (t ClientAndMaybeIdentity) AsIdentity() (Identity, error) {
+ var body Identity
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromIdentity overwrites any union data inside the ClientAndMaybeIdentity as the provided Identity
+func (t *ClientAndMaybeIdentity) FromIdentity(v Identity) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeIdentity performs a merge with any union data inside the ClientAndMaybeIdentity, using the provided Identity
+func (t *ClientAndMaybeIdentity) MergeIdentity(v Identity) 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 ClientAndMaybeIdentity) MarshalJSON() ([]byte, error) {
+ b, err := t.union.MarshalJSON()
+ return b, err
+}
+
+func (t *ClientAndMaybeIdentity) UnmarshalJSON(b []byte) error {
+ err := t.union.UnmarshalJSON(b)
+ return err
+}
+
+// AsClient returns the union data inside the ClientOrIdentity as a Client
+func (t ClientOrIdentity) AsClient() (Client, error) {
+ var body Client
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromClient overwrites any union data inside the ClientOrIdentity as the provided Client
+func (t *ClientOrIdentity) FromClient(v Client) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeClient performs a merge with any union data inside the ClientOrIdentity, using the provided Client
+func (t *ClientOrIdentity) MergeClient(v Client) error {
+ b, err := json.Marshal(v)
+ if err != nil {
+ return err
+ }
+
+ merged, err := runtime.JSONMerge(t.union, b)
+ t.union = merged
+ return err
+}
+
+// AsIdentity returns the union data inside the ClientOrIdentity as a Identity
+func (t ClientOrIdentity) AsIdentity() (Identity, error) {
+ var body Identity
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromIdentity overwrites any union data inside the ClientOrIdentity as the provided Identity
+func (t *ClientOrIdentity) FromIdentity(v Identity) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeIdentity performs a merge with any union data inside the ClientOrIdentity, using the provided Identity
+func (t *ClientOrIdentity) MergeIdentity(v Identity) 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 ClientOrIdentity) MarshalJSON() ([]byte, error) {
+ b, err := t.union.MarshalJSON()
+ return b, err
+}
+
+func (t *ClientOrIdentity) UnmarshalJSON(b []byte) error {
+ err := t.union.UnmarshalJSON(b)
+ return err
+}
diff --git a/examples/anyof-allof-oneof/api.yaml b/examples/anyof-allof-oneof/api.yaml
new file mode 100644
index 000000000..493d61b66
--- /dev/null
+++ b/examples/anyof-allof-oneof/api.yaml
@@ -0,0 +1,64 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Using complex schemas
+ description: An example of `anyOf`, `allOf` and `oneOf`
+components:
+ schemas:
+ # base types
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ Identity:
+ type: object
+ required:
+ - issuer
+ properties:
+ issuer:
+ type: string
+
+ # allOf performs a union of all types defined
+ ClientWithId:
+ allOf:
+ - $ref: '#/components/schemas/Client'
+ - properties:
+ id:
+ type: integer
+ required:
+ - id
+
+ # allOf performs a union of all types defined, but if there's a duplicate field defined, it'll be overwritten by the last schema
+ # https://github.com/deepmap/oapi-codegen/issues/1569
+ IdentityWithDuplicateField:
+ allOf:
+ # `issuer` will be ignored
+ - $ref: '#/components/schemas/Identity'
+ # `issuer` will be ignored
+ - properties:
+ issuer:
+ type: integer
+ # `issuer` will take precedence
+ - properties:
+ issuer:
+ type: object
+ properties:
+ name:
+ type: string
+ required:
+ - name
+
+ # anyOf results in a type that has an `AsClient`/`MergeClient`/`FromClient` and an `AsIdentity`/`MergeIdentity`/`FromIdentity` method so you can choose which of them you want to retrieve
+ ClientAndMaybeIdentity:
+ anyOf:
+ - $ref: '#/components/schemas/Client'
+ - $ref: '#/components/schemas/Identity'
+
+ # oneOf results in a type that has an `AsClient`/`MergeClient`/`FromClient` and an `AsIdentity`/`MergeIdentity`/`FromIdentity` method so you can choose which of them you want to retrieve
+ ClientOrIdentity:
+ oneOf:
+ - $ref: '#/components/schemas/Client'
+ - $ref: '#/components/schemas/Identity'
diff --git a/examples/anyof-allof-oneof/cfg.yaml b/examples/anyof-allof-oneof/cfg.yaml
new file mode 100644
index 000000000..6db786227
--- /dev/null
+++ b/examples/anyof-allof-oneof/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../configuration-schema.json
+package: anyofallofoneof
+output: anyofallofoneof.gen.go
+generate:
+ models: true
+output-options:
+ # NOTE that this is only required for the `Unreferenced` type
+ skip-prune: true
diff --git a/examples/anyof-allof-oneof/generate.go b/examples/anyof-allof-oneof/generate.go
new file mode 100644
index 000000000..9e993e2b9
--- /dev/null
+++ b/examples/anyof-allof-oneof/generate.go
@@ -0,0 +1,3 @@
+package anyofallofoneof
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/authenticated-api/echo/api/api.gen.go b/examples/authenticated-api/echo/api/api.gen.go
index bca4d644d..383ab5dc2 100644
--- a/examples/authenticated-api/echo/api/api.gen.go
+++ b/examples/authenticated-api/echo/api/api.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/examples/authenticated-api/echo/api/config.yaml b/examples/authenticated-api/echo/api/config.yaml
index 0b176ca61..0893383bc 100644
--- a/examples/authenticated-api/echo/api/config.yaml
+++ b/examples/authenticated-api/echo/api/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
echo-server: true
diff --git a/examples/authenticated-api/echo/api/doc.go b/examples/authenticated-api/echo/api/doc.go
index d49f3532e..e6d8f45d9 100644
--- a/examples/authenticated-api/echo/api/doc.go
+++ b/examples/authenticated-api/echo/api/doc.go
@@ -1,3 +1,3 @@
package api
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../../api.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../../api.yaml
diff --git a/examples/authenticated-api/echo/main.go b/examples/authenticated-api/echo/main.go
index 2d1ace8e2..905f8d8ae 100644
--- a/examples/authenticated-api/echo/main.go
+++ b/examples/authenticated-api/echo/main.go
@@ -5,10 +5,10 @@ import (
"log"
"net"
- "github.com/deepmap/oapi-codegen/v2/examples/authenticated-api/echo/api"
- "github.com/deepmap/oapi-codegen/v2/examples/authenticated-api/echo/server"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/authenticated-api/echo/api"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/authenticated-api/echo/server"
)
func main() {
diff --git a/examples/authenticated-api/echo/server/fake_jws.go b/examples/authenticated-api/echo/server/fake_jws.go
index 46532af66..6eb3067d8 100644
--- a/examples/authenticated-api/echo/server/fake_jws.go
+++ b/examples/authenticated-api/echo/server/fake_jws.go
@@ -4,16 +4,17 @@ import (
"crypto/ecdsa"
"fmt"
- "github.com/deepmap/oapi-codegen/v2/pkg/ecdsafile"
"github.com/lestrrat-go/jwx/jwa"
"github.com/lestrrat-go/jwx/jwk"
"github.com/lestrrat-go/jwx/jws"
"github.com/lestrrat-go/jwx/jwt"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/ecdsafile"
)
// PrivateKey is an ECDSA private key which was generated with the following
// command:
-// openssl ecparam -name prime256v1 -genkey -noout -out ecprivatekey.pem
+//
+// openssl ecparam -name prime256v1 -genkey -noout -out ecprivatekey.pem
//
// We are using a hard coded key here in this example, but in real applications,
// you would never do this. Your JWT signing key must never be in your application,
diff --git a/examples/authenticated-api/echo/server/server.go b/examples/authenticated-api/echo/server/server.go
index dedb2cb2c..5346b77e2 100644
--- a/examples/authenticated-api/echo/server/server.go
+++ b/examples/authenticated-api/echo/server/server.go
@@ -6,10 +6,10 @@ import (
"sort"
"sync"
- "github.com/deepmap/oapi-codegen/v2/examples/authenticated-api/echo/api"
"github.com/getkin/kin-openapi/openapi3filter"
"github.com/labstack/echo/v4"
middleware "github.com/oapi-codegen/echo-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/authenticated-api/echo/api"
)
type server struct {
diff --git a/examples/authenticated-api/echo/server/server_test.go b/examples/authenticated-api/echo/server/server_test.go
index 22ee03054..5891c7171 100644
--- a/examples/authenticated-api/echo/server/server_test.go
+++ b/examples/authenticated-api/echo/server/server_test.go
@@ -4,9 +4,9 @@ import (
"net/http"
"testing"
- "github.com/deepmap/oapi-codegen/v2/examples/authenticated-api/echo/api"
- "github.com/oapi-codegen/testutil"
"github.com/labstack/echo/v4"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/authenticated-api/echo/api"
+ "github.com/oapi-codegen/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
diff --git a/examples/authenticated-api/stdhttp/Makefile b/examples/authenticated-api/stdhttp/Makefile
new file mode 100644
index 000000000..dac22331f
--- /dev/null
+++ b/examples/authenticated-api/stdhttp/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 -f2 -d. <<< $(GOVER)")
+
+define execute-if-go-122
+@{ \
+if [[ 22 -le $(GOMINOR) ]]; then \
+ $1; \
+else \
+ echo -e "$(YELLOW)Skipping task as you're running Go v1.$(GOMINOR).x which is < Go 1.22, which this module requires$(RESET)"; \
+fi \
+}
+endef
+
+lint:
+ $(call execute-if-go-122,$(GOBIN)/golangci-lint run ./...)
+
+lint-ci:
+
+ $(call execute-if-go-122,$(GOBIN)/golangci-lint run ./... --out-format=github-actions --timeout=5m)
+
+generate:
+ $(call execute-if-go-122,go generate ./...)
+
+test:
+ $(call execute-if-go-122,go test -cover ./...)
+
+tidy:
+ $(call execute-if-go-122,go mod tidy)
+
+tidy-ci:
+ $(call execute-if-go-122,tidied -verbose)
diff --git a/examples/authenticated-api/stdhttp/api/api.gen.go b/examples/authenticated-api/stdhttp/api/api.gen.go
new file mode 100644
index 000000000..7b1fa2c48
--- /dev/null
+++ b/examples/authenticated-api/stdhttp/api/api.gen.go
@@ -0,0 +1,669 @@
+//go:build go1.22
+
+// Package api provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package api
+
+import (
+ "bytes"
+ "compress/gzip"
+ "context"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "path"
+ "strings"
+
+ "github.com/getkin/kin-openapi/openapi3"
+)
+
+const (
+ BearerAuthScopes = "BearerAuth.Scopes"
+)
+
+// Error defines model for Error.
+type Error struct {
+ // Code Error code
+ Code int32 `json:"code"`
+
+ // Message Error message
+ Message string `json:"message"`
+}
+
+// Thing defines model for Thing.
+type Thing struct {
+ Name string `json:"name"`
+}
+
+// ThingWithID defines model for ThingWithID.
+type ThingWithID struct {
+ Id int64 `json:"id"`
+ Name string `json:"name"`
+}
+
+// AddThingJSONRequestBody defines body for AddThing for application/json ContentType.
+type AddThingJSONRequestBody = Thing
+
+// 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 {
+ // ListThings request
+ ListThings(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ // AddThingWithBody request with any body
+ AddThingWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ AddThing(ctx context.Context, body AddThingJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+func (c *Client) ListThings(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewListThingsRequest(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)
+}
+
+func (c *Client) AddThingWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewAddThingRequestWithBody(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) AddThing(ctx context.Context, body AddThingJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewAddThingRequest(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)
+}
+
+// NewListThingsRequest generates requests for ListThings
+func NewListThingsRequest(server string) (*http.Request, error) {
+ var err error
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/things")
+ 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
+}
+
+// NewAddThingRequest calls the generic AddThing builder with application/json body
+func NewAddThingRequest(server string, body AddThingJSONRequestBody) (*http.Request, error) {
+ var bodyReader io.Reader
+ buf, err := json.Marshal(body)
+ if err != nil {
+ return nil, err
+ }
+ bodyReader = bytes.NewReader(buf)
+ return NewAddThingRequestWithBody(server, "application/json", bodyReader)
+}
+
+// NewAddThingRequestWithBody generates requests for AddThing with any type of body
+func NewAddThingRequestWithBody(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("/things")
+ 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
+}
+
+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 {
+ // ListThingsWithResponse request
+ ListThingsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*ListThingsResponse, error)
+
+ // AddThingWithBodyWithResponse request with any body
+ AddThingWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*AddThingResponse, error)
+
+ AddThingWithResponse(ctx context.Context, body AddThingJSONRequestBody, reqEditors ...RequestEditorFn) (*AddThingResponse, error)
+}
+
+type ListThingsResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *[]ThingWithID
+}
+
+// Status returns HTTPResponse.Status
+func (r ListThingsResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r ListThingsResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+type AddThingResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON201 *[]ThingWithID
+}
+
+// Status returns HTTPResponse.Status
+func (r AddThingResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r AddThingResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+// ListThingsWithResponse request returning *ListThingsResponse
+func (c *ClientWithResponses) ListThingsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*ListThingsResponse, error) {
+ rsp, err := c.ListThings(ctx, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParseListThingsResponse(rsp)
+}
+
+// AddThingWithBodyWithResponse request with arbitrary body returning *AddThingResponse
+func (c *ClientWithResponses) AddThingWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*AddThingResponse, error) {
+ rsp, err := c.AddThingWithBody(ctx, contentType, body, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParseAddThingResponse(rsp)
+}
+
+func (c *ClientWithResponses) AddThingWithResponse(ctx context.Context, body AddThingJSONRequestBody, reqEditors ...RequestEditorFn) (*AddThingResponse, error) {
+ rsp, err := c.AddThing(ctx, body, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParseAddThingResponse(rsp)
+}
+
+// ParseListThingsResponse parses an HTTP response from a ListThingsWithResponse call
+func ParseListThingsResponse(rsp *http.Response) (*ListThingsResponse, error) {
+ bodyBytes, err := io.ReadAll(rsp.Body)
+ defer func() { _ = rsp.Body.Close() }()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &ListThingsResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest []ThingWithID
+ if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+ return nil, err
+ }
+ response.JSON200 = &dest
+
+ }
+
+ return response, nil
+}
+
+// ParseAddThingResponse parses an HTTP response from a AddThingWithResponse call
+func ParseAddThingResponse(rsp *http.Response) (*AddThingResponse, error) {
+ bodyBytes, err := io.ReadAll(rsp.Body)
+ defer func() { _ = rsp.Body.Close() }()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &AddThingResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201:
+ var dest []ThingWithID
+ if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+ return nil, err
+ }
+ response.JSON201 = &dest
+
+ }
+
+ return response, nil
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /things)
+ ListThings(w http.ResponseWriter, r *http.Request)
+
+ // (POST /things)
+ AddThing(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
+
+// ListThings operation middleware
+func (siw *ServerInterfaceWrapper) ListThings(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ ctx = context.WithValue(ctx, BearerAuthScopes, []string{})
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.ListThings(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// AddThing operation middleware
+func (siw *ServerInterfaceWrapper) AddThing(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ ctx = context.WithValue(ctx, BearerAuthScopes, []string{"things:w"})
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.AddThing(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+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{})
+}
+
+type StdHTTPServerOptions struct {
+ BaseURL string
+ BaseRouter *http.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 *http.ServeMux) http.Handler {
+ return HandlerWithOptions(si, StdHTTPServerOptions{
+ BaseRouter: m,
+ })
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, m *http.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+"/things", wrapper.ListThings)
+ m.HandleFunc("POST "+options.BaseURL+"/things", wrapper.AddThing)
+
+ return m
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+ "H4sIAAAAAAAC/8RUwW7bOBD9lcHsAnsRbCdZ7EE3B8kCDgq0aA3kEAcII44ttjLJDEdxjUD/XpCUHDVO",
+ "0/bUiy2Swzfz3rzhE1Zu650lKwHLJwxVTVuVPi+ZHccPz84Ti6G0XTlN8V9TqNh4Mc5imYMhnRW4drxV",
+ "giUaK2enWKDsPeUlbYixK3BLIajND4GG48PVIGzsBruuQKaH1jBpLG+wTziE33YFLusYeFS2VduU7W28",
+ "FHVAuTZSLy7iLdU079dY3jzh30xrLPGv6bNu0160aU7dFS9zGx1/x6r89+8rqryoxWi87W7jbqCqZSP7",
+ "TzFPhjwnxcTzVuq4uk+r/4cEV9dLLHIrY4J8+pywFvHYRWBj1+64BXML9FVtfUMw/7CAXW2qGtpAATIS",
+ "iPtCFkLlPAVQVsPV9RJUrKVAMdLEJLE0smIqJaQTzmXGxAIfiUNOdTKZTWbRD86TVd5giWdpq0CvpE5U",
+ "pxJlTZ8bkuNyP5K0bAMoaEwQcGvIFyZwTpVqA8V1ALLaO2MFtKNg/xFwj8RsdDymld007l41MEhdgBHo",
+ "uxGhI8O148Syp2Wcnawspto5LRcaS3xngixzxbGfwTsbcs9OZ7M8QFbIJiLK+6aHmn4Okc0wgck2Qtt0",
+ "8aee643aHVqsmNU+9/h7sV6KlGO8C68IO9c6Uk+BIC7qdCTxcixtOGgaUnDWdGUHUSFbMllmpO1dBit3",
+ "d9lTYCw41slo4Inj4IBa2R0bodckn2udRy8PEAU5d3r/W1r/wlgfizl/1sbYQCwTGMwY6ec90n3UzkgN",
+ "ysLiAseDLtxSd+SUkz/ulOWYwXLEAFprHlqKPMaPU3odx8/SDQ59ze/Ym7Ex4lsAAAD//9UBNUSMBgAA",
+}
+
+// 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/examples/authenticated-api/stdhttp/api/config.yaml b/examples/authenticated-api/stdhttp/api/config.yaml
new file mode 100644
index 000000000..9cbde4b66
--- /dev/null
+++ b/examples/authenticated-api/stdhttp/api/config.yaml
@@ -0,0 +1,10 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: api
+generate:
+ std-http-server: true
+ client: true
+ models: true
+ embedded-spec: true
+output: api.gen.go
+output-options:
+ skip-prune: true
diff --git a/examples/authenticated-api/stdhttp/api/doc.go b/examples/authenticated-api/stdhttp/api/doc.go
new file mode 100644
index 000000000..e6d8f45d9
--- /dev/null
+++ b/examples/authenticated-api/stdhttp/api/doc.go
@@ -0,0 +1,3 @@
+package api
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../../api.yaml
diff --git a/examples/authenticated-api/stdhttp/go.mod b/examples/authenticated-api/stdhttp/go.mod
new file mode 100644
index 000000000..fb0f72572
--- /dev/null
+++ b/examples/authenticated-api/stdhttp/go.mod
@@ -0,0 +1,41 @@
+module github.com/oapi-codegen/oapi-codegen/v2/examples/authenticated-api/stdhttp
+
+go 1.22
+
+replace github.com/oapi-codegen/oapi-codegen/v2 => ../../../
+
+require (
+ github.com/getkin/kin-openapi v0.124.0
+ github.com/lestrrat-go/jwx v1.2.29
+ github.com/oapi-codegen/nethttp-middleware v1.0.2
+ github.com/oapi-codegen/oapi-codegen/v2 v2.0.0-00010101000000-000000000000
+ github.com/oapi-codegen/testutil v1.1.0
+ github.com/stretchr/testify v1.9.0
+)
+
+require (
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
+ github.com/go-openapi/jsonpointer v0.20.2 // indirect
+ github.com/go-openapi/swag v0.22.8 // indirect
+ github.com/goccy/go-json v0.10.2 // indirect
+ github.com/gorilla/mux v1.8.1 // indirect
+ github.com/invopop/yaml v0.2.0 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
+ github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
+ github.com/lestrrat-go/blackmagic v1.0.2 // indirect
+ github.com/lestrrat-go/httpcc v1.0.1 // indirect
+ github.com/lestrrat-go/iter v1.0.2 // indirect
+ github.com/lestrrat-go/option v1.0.1 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
+ 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
+ golang.org/x/crypto v0.22.0 // indirect
+ golang.org/x/mod v0.17.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/tools v0.21.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
new file mode 100644
index 000000000..fdbaa70c6
--- /dev/null
+++ b/examples/authenticated-api/stdhttp/go.sum
@@ -0,0 +1,128 @@
+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/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
+github.com/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M=
+github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
+github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
+github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
+github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
+github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
+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/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
+github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
+github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
+github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
+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/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A=
+github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
+github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
+github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
+github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
+github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
+github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
+github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
+github.com/lestrrat-go/jwx v1.2.29 h1:QT0utmUJ4/12rmsVQrJ3u55bycPkKqGYuGT4tyRhxSQ=
+github.com/lestrrat-go/jwx v1.2.29/go.mod h1:hU8k2l6WF0ncx20uQdOmik/Gjg6E3/wIRtXSNFeZuB8=
+github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
+github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
+github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+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/oapi-codegen/nethttp-middleware v1.0.2 h1:A5tfAcKJhWIbIPnlQH+l/DtfVE1i5TFgPlQAiW+l1vQ=
+github.com/oapi-codegen/nethttp-middleware v1.0.2/go.mod h1:DfDalonSO+eRQ3RTb8kYoWZByCCPFRxm9WKq1UbY0E4=
+github.com/oapi-codegen/testutil v1.1.0 h1:EufqpNg43acR3qzr3ObhXmWg3Sl2kwtRnUN5GYY4d5g=
+github.com/oapi-codegen/testutil v1.1.0/go.mod h1:ttCaYbHvJtHuiyeBF0tPIX+4uhEPTeizXKx28okijLw=
+github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
+github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
+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/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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+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/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
+golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
+golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
+golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
+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.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+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.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
+golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+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/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=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
+golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
+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.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.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+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.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.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
+golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+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-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0/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/authenticated-api/stdhttp/main.go b/examples/authenticated-api/stdhttp/main.go
new file mode 100644
index 000000000..73d330aac
--- /dev/null
+++ b/examples/authenticated-api/stdhttp/main.go
@@ -0,0 +1,57 @@
+package main
+
+import (
+ "flag"
+ "log"
+ "net/http"
+
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/authenticated-api/stdhttp/api"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/authenticated-api/stdhttp/server"
+)
+
+func main() {
+ port := flag.String("port", "8080", "port where to serve traffic")
+
+ r := http.NewServeMux()
+
+ // Create a fake authenticator. This allows us to issue tokens, and also
+ // implements a validator to check their validity.
+ fa, err := server.NewFakeAuthenticator()
+ if err != nil {
+ log.Fatalln("error creating authenticator:", err)
+ }
+
+ // Create middleware for validating tokens.
+ mw, err := server.CreateMiddleware(fa)
+ if err != nil {
+ log.Fatalln("error creating middleware:", err)
+ }
+
+ svr := server.NewServer()
+
+ h := api.HandlerFromMux(svr, r)
+ // wrap the existing handler with our global middleware
+ h = mw(h)
+
+ // We're going to print some useful things for interacting with this server.
+ // This token allows access to any API's with no specific claims.
+ readerJWS, err := fa.CreateJWSWithClaims([]string{})
+ if err != nil {
+ log.Fatalln("error creating reader JWS:", err)
+ }
+ // This token allows access to API's with no scopes, and with the "things:w" claim.
+ writerJWS, err := fa.CreateJWSWithClaims([]string{"things:w"})
+ if err != nil {
+ log.Fatalln("error creating writer JWS:", err)
+ }
+
+ log.Println("Reader token", string(readerJWS))
+ log.Println("Writer token", string(writerJWS))
+
+ s := &http.Server{
+ Handler: h,
+ Addr: "0.0.0.0:" + *port,
+ }
+
+ log.Fatal(s.ListenAndServe())
+}
diff --git a/examples/authenticated-api/stdhttp/server/fake_jws.go b/examples/authenticated-api/stdhttp/server/fake_jws.go
new file mode 100644
index 000000000..6eb3067d8
--- /dev/null
+++ b/examples/authenticated-api/stdhttp/server/fake_jws.go
@@ -0,0 +1,110 @@
+package server
+
+import (
+ "crypto/ecdsa"
+ "fmt"
+
+ "github.com/lestrrat-go/jwx/jwa"
+ "github.com/lestrrat-go/jwx/jwk"
+ "github.com/lestrrat-go/jwx/jws"
+ "github.com/lestrrat-go/jwx/jwt"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/ecdsafile"
+)
+
+// PrivateKey is an ECDSA private key which was generated with the following
+// command:
+//
+// openssl ecparam -name prime256v1 -genkey -noout -out ecprivatekey.pem
+//
+// We are using a hard coded key here in this example, but in real applications,
+// you would never do this. Your JWT signing key must never be in your application,
+// only the public key.
+const PrivateKey = `-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIN2dALnjdcZaIZg4QuA6Dw+kxiSW502kJfmBN3priIhPoAoGCCqGSM49
+AwEHoUQDQgAE4pPyvrB9ghqkT1Llk0A42lixkugFd/TBdOp6wf69O9Nndnp4+HcR
+s9SlG/8hjB2Hz42v4p3haKWv3uS1C6ahCQ==
+-----END EC PRIVATE KEY-----`
+
+const KeyID = `fake-key-id`
+const FakeIssuer = "fake-issuer"
+const FakeAudience = "example-users"
+const PermissionsClaim = "perm"
+
+type FakeAuthenticator struct {
+ PrivateKey *ecdsa.PrivateKey
+ KeySet jwk.Set
+}
+
+var _ JWSValidator = (*FakeAuthenticator)(nil)
+
+// NewFakeAuthenticator creates an authenticator example which uses a hard coded
+// ECDSA key to validate JWT's that it has signed itself.
+func NewFakeAuthenticator() (*FakeAuthenticator, error) {
+ privKey, err := ecdsafile.LoadEcdsaPrivateKey([]byte(PrivateKey))
+ if err != nil {
+ return nil, fmt.Errorf("loading PEM private key: %w", err)
+ }
+
+ set := jwk.NewSet()
+ pubKey := jwk.NewECDSAPublicKey()
+
+ err = pubKey.FromRaw(&privKey.PublicKey)
+ if err != nil {
+ return nil, fmt.Errorf("parsing jwk key: %w", err)
+ }
+
+ err = pubKey.Set(jwk.AlgorithmKey, jwa.ES256)
+ if err != nil {
+ return nil, fmt.Errorf("setting key algorithm: %w", err)
+ }
+
+ err = pubKey.Set(jwk.KeyIDKey, KeyID)
+ if err != nil {
+ return nil, fmt.Errorf("setting key ID: %w", err)
+ }
+
+ set.Add(pubKey)
+
+ return &FakeAuthenticator{PrivateKey: privKey, KeySet: set}, nil
+}
+
+// ValidateJWS ensures that the critical JWT claims needed to ensure that we
+// trust the JWT are present and with the correct values.
+func (f *FakeAuthenticator) ValidateJWS(jwsString string) (jwt.Token, error) {
+ return jwt.Parse([]byte(jwsString), jwt.WithKeySet(f.KeySet),
+ jwt.WithAudience(FakeAudience), jwt.WithIssuer(FakeIssuer))
+}
+
+// SignToken takes a JWT and signs it with our private key, returning a JWS.
+func (f *FakeAuthenticator) SignToken(t jwt.Token) ([]byte, error) {
+ hdr := jws.NewHeaders()
+ if err := hdr.Set(jws.AlgorithmKey, jwa.ES256); err != nil {
+ return nil, fmt.Errorf("setting algorithm: %w", err)
+ }
+ if err := hdr.Set(jws.TypeKey, "JWT"); err != nil {
+ return nil, fmt.Errorf("setting type: %w", err)
+ }
+ if err := hdr.Set(jws.KeyIDKey, KeyID); err != nil {
+ return nil, fmt.Errorf("setting Key ID: %w", err)
+ }
+ return jwt.Sign(t, jwa.ES256, f.PrivateKey, jwt.WithHeaders(hdr))
+}
+
+// CreateJWSWithClaims is a helper function to create JWT's with the specified
+// claims.
+func (f *FakeAuthenticator) CreateJWSWithClaims(claims []string) ([]byte, error) {
+ t := jwt.New()
+ err := t.Set(jwt.IssuerKey, FakeIssuer)
+ if err != nil {
+ return nil, fmt.Errorf("setting issuer: %w", err)
+ }
+ err = t.Set(jwt.AudienceKey, FakeAudience)
+ if err != nil {
+ return nil, fmt.Errorf("setting audience: %w", err)
+ }
+ err = t.Set(PermissionsClaim, claims)
+ if err != nil {
+ return nil, fmt.Errorf("setting permissions: %w", err)
+ }
+ return f.SignToken(t)
+}
diff --git a/examples/authenticated-api/stdhttp/server/jwt_authenticator.go b/examples/authenticated-api/stdhttp/server/jwt_authenticator.go
new file mode 100644
index 000000000..0cecccf04
--- /dev/null
+++ b/examples/authenticated-api/stdhttp/server/jwt_authenticator.go
@@ -0,0 +1,135 @@
+package server
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "net/http"
+ "strings"
+
+ "github.com/getkin/kin-openapi/openapi3filter"
+ "github.com/lestrrat-go/jwx/jwt"
+)
+
+// JWSValidator is used to validate JWS payloads and return a JWT if they're
+// valid
+type JWSValidator interface {
+ ValidateJWS(jws string) (jwt.Token, error)
+}
+
+const JWTClaimsContextKey = "jwt_claims"
+
+var (
+ ErrNoAuthHeader = errors.New("Authorization header is missing")
+ ErrInvalidAuthHeader = errors.New("Authorization header is malformed")
+ ErrClaimsInvalid = errors.New("Provided claims do not match expected scopes")
+)
+
+// GetJWSFromRequest extracts a JWS string from an Authorization: Bearer header
+func GetJWSFromRequest(req *http.Request) (string, error) {
+ authHdr := req.Header.Get("Authorization")
+ // Check for the Authorization header.
+ if authHdr == "" {
+ return "", ErrNoAuthHeader
+ }
+ // We expect a header value of the form "Bearer ", with 1 space after
+ // Bearer, per spec.
+ prefix := "Bearer "
+ if !strings.HasPrefix(authHdr, prefix) {
+ return "", ErrInvalidAuthHeader
+ }
+ return strings.TrimPrefix(authHdr, prefix), nil
+}
+
+func NewAuthenticator(v JWSValidator) openapi3filter.AuthenticationFunc {
+ return func(ctx context.Context, input *openapi3filter.AuthenticationInput) error {
+ return Authenticate(v, ctx, input)
+ }
+}
+
+// Authenticate uses the specified validator to ensure a JWT is valid, then makes
+// sure that the claims provided by the JWT match the scopes as required in the API.
+func Authenticate(v JWSValidator, ctx context.Context, input *openapi3filter.AuthenticationInput) error {
+ // Our security scheme is named BearerAuth, ensure this is the case
+ if input.SecuritySchemeName != "BearerAuth" {
+ return fmt.Errorf("security scheme %s != 'BearerAuth'", input.SecuritySchemeName)
+ }
+
+ // Now, we need to get the JWS from the request, to match the request expectations
+ // against request contents.
+ jws, err := GetJWSFromRequest(input.RequestValidationInput.Request)
+ if err != nil {
+ return fmt.Errorf("getting jws: %w", err)
+ }
+
+ // if the JWS is valid, we have a JWT, which will contain a bunch of claims.
+ token, err := v.ValidateJWS(jws)
+ if err != nil {
+ return fmt.Errorf("validating JWS: %w", err)
+ }
+
+ // We've got a valid token now, and we can look into its claims to see whether
+ // they match. Every single scope must be present in the claims.
+ err = CheckTokenClaims(input.Scopes, token)
+
+ if err != nil {
+ return fmt.Errorf("token claims don't match: %w", err)
+ }
+
+ // Set the property on the echo context so the handler is able to
+ // access the claims data we generate in here.
+ // TODO
+ // ctx.Set(JWTClaimsContextKey, token)
+
+ return nil
+}
+
+// GetClaimsFromToken returns a list of claims from the token. We store these
+// as a list under the "perms" claim, short for permissions, to keep the token
+// shorter.
+func GetClaimsFromToken(t jwt.Token) ([]string, error) {
+ rawPerms, found := t.Get(PermissionsClaim)
+ if !found {
+ // If the perms aren't found, it means that the token has none, but it has
+ // passed signature validation by now, so it's a valid token, so we return
+ // the empty list.
+ return make([]string, 0), nil
+ }
+
+ // rawPerms will be an untyped JSON list, so we need to convert it to
+ // a string list.
+ rawList, ok := rawPerms.([]interface{})
+ if !ok {
+ return nil, fmt.Errorf("'%s' claim is unexpected type'", PermissionsClaim)
+ }
+
+ claims := make([]string, len(rawList))
+
+ for i, rawClaim := range rawList {
+ var ok bool
+ claims[i], ok = rawClaim.(string)
+ if !ok {
+ return nil, fmt.Errorf("%s[%d] is not a string", PermissionsClaim, i)
+ }
+ }
+ return claims, nil
+}
+
+func CheckTokenClaims(expectedClaims []string, t jwt.Token) error {
+ claims, err := GetClaimsFromToken(t)
+ if err != nil {
+ return fmt.Errorf("getting claims from token: %w", err)
+ }
+ // Put the claims into a map, for quick access.
+ claimsMap := make(map[string]bool, len(claims))
+ for _, c := range claims {
+ claimsMap[c] = true
+ }
+
+ for _, e := range expectedClaims {
+ if !claimsMap[e] {
+ return ErrClaimsInvalid
+ }
+ }
+ return nil
+}
diff --git a/examples/authenticated-api/stdhttp/server/server.go b/examples/authenticated-api/stdhttp/server/server.go
new file mode 100644
index 000000000..ddcabaa73
--- /dev/null
+++ b/examples/authenticated-api/stdhttp/server/server.go
@@ -0,0 +1,122 @@
+package server
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "sort"
+ "sync"
+
+ "github.com/getkin/kin-openapi/openapi3filter"
+ middleware "github.com/oapi-codegen/nethttp-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/authenticated-api/stdhttp/api"
+)
+
+type server struct {
+ sync.RWMutex
+ lastID int64
+ things map[int64]api.Thing
+}
+
+func NewServer() *server {
+ return &server{
+ lastID: 0,
+ things: make(map[int64]api.Thing),
+ }
+}
+
+func CreateMiddleware(v JWSValidator) (func(next http.Handler) http.Handler, error) {
+ spec, err := api.GetSwagger()
+ if err != nil {
+ return nil, fmt.Errorf("loading spec: %w", err)
+ }
+
+ validator := middleware.OapiRequestValidatorWithOptions(spec,
+ &middleware.Options{
+ Options: openapi3filter.Options{
+ AuthenticationFunc: NewAuthenticator(v),
+ },
+ })
+
+ return validator, nil
+}
+
+// Ensure that we implement the server interface
+var _ api.ServerInterface = (*server)(nil)
+
+func (s *server) ListThings(w http.ResponseWriter, r *http.Request) {
+ // This handler will only be called when a valid JWT is presented for
+ // access.
+ s.RLock()
+
+ thingKeys := make([]int64, 0, len(s.things))
+ for key := range s.things {
+ thingKeys = append(thingKeys, key)
+ }
+ sort.Sort(int64s(thingKeys))
+
+ things := make([]api.ThingWithID, 0, len(s.things))
+
+ for _, key := range thingKeys {
+ thing := s.things[key]
+ things = append(things, api.ThingWithID{
+ Id: key,
+ Name: thing.Name,
+ })
+ }
+
+ s.RUnlock()
+
+ w.WriteHeader(http.StatusOK)
+ _ = json.NewEncoder(w).Encode(things)
+}
+
+type int64s []int64
+
+func (in int64s) Len() int {
+ return len(in)
+}
+
+func (in int64s) Less(i, j int) bool {
+ return in[i] < in[j]
+}
+
+func (in int64s) Swap(i, j int) {
+ in[i], in[j] = in[j], in[i]
+}
+
+var _ sort.Interface = (int64s)(nil)
+
+func (s *server) AddThing(w http.ResponseWriter, r *http.Request) {
+ // This handler will only be called when the JWT is valid and the JWT contains
+ // the scopes required.
+ bodyBytes, err := io.ReadAll(r.Body)
+ defer func() { _ = r.Body.Close() }()
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ _, _ = w.Write([]byte("could not bind request body"))
+ return
+ }
+
+ var thing api.Thing
+ err = json.Unmarshal(bodyBytes, &thing)
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ _, _ = w.Write([]byte("could not bind request body"))
+ return
+ }
+
+ s.Lock()
+ defer s.Unlock()
+
+ s.things[s.lastID] = thing
+ thingWithId := api.ThingWithID{
+ Name: thing.Name,
+ Id: s.lastID,
+ }
+ s.lastID++
+
+ w.WriteHeader(http.StatusCreated)
+ _ = json.NewEncoder(w).Encode(thingWithId)
+}
diff --git a/examples/authenticated-api/stdhttp/server/server_test.go b/examples/authenticated-api/stdhttp/server/server_test.go
new file mode 100644
index 000000000..cfada646d
--- /dev/null
+++ b/examples/authenticated-api/stdhttp/server/server_test.go
@@ -0,0 +1,63 @@
+package server
+
+import (
+ "net/http"
+ "testing"
+
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/authenticated-api/stdhttp/api"
+ "github.com/oapi-codegen/testutil"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestAPI(t *testing.T) {
+ r := http.NewServeMux()
+ s := NewServer()
+
+ fa, err := NewFakeAuthenticator()
+ require.NoError(t, err)
+
+ mw, err := CreateMiddleware(fa)
+ require.NoError(t, err)
+
+ h := api.HandlerFromMux(s, r)
+ // wrap the existing handler with our global middleware
+ h = mw(h)
+
+ // Let's create a JWT with no scopes, which allows access to listing things.
+ readerJWT, err := fa.CreateJWSWithClaims([]string{})
+ require.NoError(t, err)
+ t.Logf("reader jwt: %s", string(readerJWT))
+
+ // Now, create a JWT with write permission.
+ writerJWT, err := fa.CreateJWSWithClaims([]string{"things:w"})
+ require.NoError(t, err)
+ t.Logf("writer jwt: %s", string(writerJWT))
+
+ // ListPets should return 401 Unauthorized without credentials
+ response := testutil.NewRequest().Get("/things").GoWithHTTPHandler(t, h)
+ assert.Equal(t, http.StatusUnauthorized, response.Code())
+
+ // Using the writer JWT should allow us to insert a thing.
+ response = testutil.NewRequest().Post("/things").
+ WithJWSAuth(string(writerJWT)).
+ WithAcceptJson().
+ WithJsonBody(api.Thing{Name: "Thing 1"}).GoWithHTTPHandler(t, h)
+ require.Equal(t, http.StatusCreated, response.Code())
+
+ // Using the reader JWT should forbid inserting a thing.
+ response = testutil.NewRequest().Post("/things").
+ WithJWSAuth(string(readerJWT)).
+ WithAcceptJson().
+ WithJsonBody(api.Thing{Name: "Thing 2"}).GoWithHTTPHandler(t, h)
+ require.Equal(t, http.StatusUnauthorized, response.Code())
+
+ // Both JWT's should allow reading the list of things.
+ jwts := []string{string(readerJWT), string(writerJWT)}
+ for _, jwt := range jwts {
+ response := testutil.NewRequest().Get("/things").
+ WithJWSAuth(jwt).
+ WithAcceptJson().GoWithHTTPHandler(t, h)
+ assert.Equal(t, http.StatusOK, response.Code())
+ }
+}
diff --git a/examples/authenticated-api/stdhttp/tools/tools.go b/examples/authenticated-api/stdhttp/tools/tools.go
new file mode 100644
index 000000000..8615cb4c5
--- /dev/null
+++ b/examples/authenticated-api/stdhttp/tools/tools.go
@@ -0,0 +1,8 @@
+//go:build tools
+// +build tools
+
+package tools
+
+import (
+ _ "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen"
+)
diff --git a/examples/client/api.yaml b/examples/client/api.yaml
new file mode 100644
index 000000000..5945b63dd
--- /dev/null
+++ b/examples/client/api.yaml
@@ -0,0 +1,47 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Generate models
+paths:
+ /client:
+ get:
+ operationId: getClient
+ responses:
+ 200:
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ClientType"
+ put:
+ operationId: updateClient
+ responses:
+ 400:
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ code:
+ type: string
+ required:
+ - code
+components:
+ schemas:
+ ClientType:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ # NOTE that this is not generated by default because it's not referenced. If you want it, you need to use the following YAML configuration:
+ #
+ # output-options:
+ # skip-prune: true
+ Unreferenced:
+ type: object
+ required:
+ - id
+ properties:
+ id:
+ type: int
diff --git a/examples/client/cfg.yaml b/examples/client/cfg.yaml
new file mode 100644
index 000000000..d2103b056
--- /dev/null
+++ b/examples/client/cfg.yaml
@@ -0,0 +1,6 @@
+# yaml-language-server: $schema=../../configuration-schema.json
+package: client
+output: client.gen.go
+generate:
+ models: true
+ client: true
diff --git a/examples/client/client.gen.go b/examples/client/client.gen.go
new file mode 100644
index 000000000..8ef6b7856
--- /dev/null
+++ b/examples/client/client.gen.go
@@ -0,0 +1,345 @@
+// Package client provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package client
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+)
+
+// ClientType defines model for ClientType.
+type ClientType struct {
+ Name string `json:"name"`
+}
+
+// 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 {
+ // GetClient request
+ GetClient(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ // UpdateClient request
+ UpdateClient(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+func (c *Client) GetClient(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewGetClientRequest(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)
+}
+
+func (c *Client) UpdateClient(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewUpdateClientRequest(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)
+}
+
+// NewGetClientRequest generates requests for GetClient
+func NewGetClientRequest(server string) (*http.Request, error) {
+ var err error
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/client")
+ 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
+}
+
+// NewUpdateClientRequest generates requests for UpdateClient
+func NewUpdateClientRequest(server string) (*http.Request, error) {
+ var err error
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/client")
+ if operationPath[0] == '/' {
+ operationPath = "." + operationPath
+ }
+
+ queryURL, err := serverURL.Parse(operationPath)
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest("PUT", 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 {
+ // GetClientWithResponse request
+ GetClientWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetClientResponse, error)
+
+ // UpdateClientWithResponse request
+ UpdateClientWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*UpdateClientResponse, error)
+}
+
+type GetClientResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *ClientType
+}
+
+// Status returns HTTPResponse.Status
+func (r GetClientResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r GetClientResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+type UpdateClientResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON400 *struct {
+ Code string `json:"code"`
+ }
+}
+
+// Status returns HTTPResponse.Status
+func (r UpdateClientResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r UpdateClientResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+// GetClientWithResponse request returning *GetClientResponse
+func (c *ClientWithResponses) GetClientWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetClientResponse, error) {
+ rsp, err := c.GetClient(ctx, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParseGetClientResponse(rsp)
+}
+
+// UpdateClientWithResponse request returning *UpdateClientResponse
+func (c *ClientWithResponses) UpdateClientWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*UpdateClientResponse, error) {
+ rsp, err := c.UpdateClient(ctx, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParseUpdateClientResponse(rsp)
+}
+
+// ParseGetClientResponse parses an HTTP response from a GetClientWithResponse call
+func ParseGetClientResponse(rsp *http.Response) (*GetClientResponse, error) {
+ bodyBytes, err := io.ReadAll(rsp.Body)
+ defer func() { _ = rsp.Body.Close() }()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &GetClientResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest ClientType
+ if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+ return nil, err
+ }
+ response.JSON200 = &dest
+
+ }
+
+ return response, nil
+}
+
+// ParseUpdateClientResponse parses an HTTP response from a UpdateClientWithResponse call
+func ParseUpdateClientResponse(rsp *http.Response) (*UpdateClientResponse, error) {
+ bodyBytes, err := io.ReadAll(rsp.Body)
+ defer func() { _ = rsp.Body.Close() }()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &UpdateClientResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400:
+ var dest struct {
+ Code string `json:"code"`
+ }
+ if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+ return nil, err
+ }
+ response.JSON400 = &dest
+
+ }
+
+ return response, nil
+}
diff --git a/examples/client/generate.go b/examples/client/generate.go
new file mode 100644
index 000000000..e9c9a42f8
--- /dev/null
+++ b/examples/client/generate.go
@@ -0,0 +1,3 @@
+package client
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/custom-client-type/cfg.yaml b/examples/custom-client-type/cfg.yaml
index 6f52fb3db..7dcbbbc26 100644
--- a/examples/custom-client-type/cfg.yaml
+++ b/examples/custom-client-type/cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../configuration-schema.json
package: customclienttype
output: custom-client-type.gen.go
generate:
diff --git a/examples/custom-client-type/custom-client-type.gen.go b/examples/custom-client-type/custom-client-type.gen.go
index 79bab485e..6dd2ef019 100644
--- a/examples/custom-client-type/custom-client-type.gen.go
+++ b/examples/custom-client-type/custom-client-type.gen.go
@@ -1,6 +1,6 @@
// Package customclienttype provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package customclienttype
import (
diff --git a/examples/custom-client-type/doc.go b/examples/custom-client-type/doc.go
index 540715b92..778f8a210 100644
--- a/examples/custom-client-type/doc.go
+++ b/examples/custom-client-type/doc.go
@@ -3,4 +3,4 @@ package customclienttype
// This is an example of how to add a prefix to the name of the generated Client struct
// See https://github.com/deepmap/oapi-codegen/issues/785 for why this might be necessary
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/extensions/xdeprecatedreason/api.yaml b/examples/extensions/xdeprecatedreason/api.yaml
new file mode 100644
index 000000000..d1ca870f1
--- /dev/null
+++ b/examples/extensions/xdeprecatedreason/api.yaml
@@ -0,0 +1,28 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-deprecated-reason
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ deprecated: true
+ x-deprecated-reason: Don't use because reasons
+ id:
+ type: number
+ # NOTE that this doesn't generate, as no `deprecated: true` is set
+ x-deprecated-reason: NOTE you shouldn't see this, as you've not deprecated this field
diff --git a/examples/extensions/xdeprecatedreason/cfg.yaml b/examples/extensions/xdeprecatedreason/cfg.yaml
new file mode 100644
index 000000000..05ae8c244
--- /dev/null
+++ b/examples/extensions/xdeprecatedreason/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
+package: xdeprecatedreason
+output: gen.go
+generate:
+ models: true
+output-options:
+ # to make sure that all types are generated, even if they're unreferenced
+ skip-prune: true
diff --git a/examples/extensions/xdeprecatedreason/gen.go b/examples/extensions/xdeprecatedreason/gen.go
new file mode 100644
index 000000000..aa36e0387
--- /dev/null
+++ b/examples/extensions/xdeprecatedreason/gen.go
@@ -0,0 +1,17 @@
+// Package xdeprecatedreason provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package xdeprecatedreason
+
+// Client defines model for Client.
+type Client struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ Id *float32 `json:"id,omitempty"`
+ // Deprecated: Don't use because reasons
+ Name string `json:"name"`
+}
diff --git a/examples/extensions/xdeprecatedreason/generate.go b/examples/extensions/xdeprecatedreason/generate.go
new file mode 100644
index 000000000..97a610ff3
--- /dev/null
+++ b/examples/extensions/xdeprecatedreason/generate.go
@@ -0,0 +1,3 @@
+package xdeprecatedreason
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/extensions/xenumnames/api.yaml b/examples/extensions/xenumnames/api.yaml
new file mode 100644
index 000000000..b9c271582
--- /dev/null
+++ b/examples/extensions/xenumnames/api.yaml
@@ -0,0 +1,27 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-enumNames and x-enum-varnames
+components:
+ schemas:
+ ClientType:
+ type: string
+ enum:
+ - ACT
+ - EXP
+ ClientTypeWithNamesExtension:
+ type: string
+ enum:
+ - ACT
+ - EXP
+ x-enumNames:
+ - Active
+ - Expired
+ ClientTypeWithVarNamesExtension:
+ type: string
+ enum:
+ - ACT
+ - EXP
+ x-enum-varnames:
+ - Active
+ - Expired
diff --git a/examples/extensions/xenumnames/cfg.yaml b/examples/extensions/xenumnames/cfg.yaml
new file mode 100644
index 000000000..694e66732
--- /dev/null
+++ b/examples/extensions/xenumnames/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
+package: xenumnames
+output: gen.go
+generate:
+ models: true
+output-options:
+ # to make sure that all types are generated, even if they're unreferenced
+ skip-prune: true
diff --git a/examples/extensions/xenumnames/gen.go b/examples/extensions/xenumnames/gen.go
new file mode 100644
index 000000000..73ebfa656
--- /dev/null
+++ b/examples/extensions/xenumnames/gen.go
@@ -0,0 +1,31 @@
+// Package xenumnames provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package xenumnames
+
+// Defines values for ClientType.
+const (
+ ACT ClientType = "ACT"
+ EXP ClientType = "EXP"
+)
+
+// Defines values for ClientTypeWithNamesExtension.
+const (
+ ClientTypeWithNamesExtensionActive ClientTypeWithNamesExtension = "ACT"
+ ClientTypeWithNamesExtensionExpired ClientTypeWithNamesExtension = "EXP"
+)
+
+// Defines values for ClientTypeWithVarNamesExtension.
+const (
+ ClientTypeWithVarNamesExtensionActive ClientTypeWithVarNamesExtension = "ACT"
+ ClientTypeWithVarNamesExtensionExpired ClientTypeWithVarNamesExtension = "EXP"
+)
+
+// ClientType defines model for ClientType.
+type ClientType string
+
+// ClientTypeWithNamesExtension defines model for ClientTypeWithNamesExtension.
+type ClientTypeWithNamesExtension string
+
+// ClientTypeWithVarNamesExtension defines model for ClientTypeWithVarNamesExtension.
+type ClientTypeWithVarNamesExtension string
diff --git a/examples/extensions/xenumnames/generate.go b/examples/extensions/xenumnames/generate.go
new file mode 100644
index 000000000..599d6f3f9
--- /dev/null
+++ b/examples/extensions/xenumnames/generate.go
@@ -0,0 +1,3 @@
+package xenumnames
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/extensions/xgojsonignore/api.yaml b/examples/extensions/xgojsonignore/api.yaml
new file mode 100644
index 000000000..31af087f3
--- /dev/null
+++ b/examples/extensions/xgojsonignore/api.yaml
@@ -0,0 +1,37 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-go-json-ignore
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ complexField:
+ type: object
+ properties:
+ name:
+ type: string
+ accountName:
+ type: string
+ # ...
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ complexField:
+ type: object
+ properties:
+ name:
+ type: string
+ accountName:
+ type: string
+ # ...
+ x-go-json-ignore: true
diff --git a/examples/extensions/xgojsonignore/cfg.yaml b/examples/extensions/xgojsonignore/cfg.yaml
new file mode 100644
index 000000000..2e8300b09
--- /dev/null
+++ b/examples/extensions/xgojsonignore/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
+package: xgojsonignore
+output: gen.go
+generate:
+ models: true
+output-options:
+ # to make sure that all types are generated, even if they're unreferenced
+ skip-prune: true
diff --git a/examples/extensions/xgojsonignore/gen.go b/examples/extensions/xgojsonignore/gen.go
new file mode 100644
index 000000000..17c21373d
--- /dev/null
+++ b/examples/extensions/xgojsonignore/gen.go
@@ -0,0 +1,22 @@
+// Package xgojsonignore provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package xgojsonignore
+
+// Client defines model for Client.
+type Client struct {
+ ComplexField *struct {
+ AccountName *string `json:"accountName,omitempty"`
+ Name *string `json:"name,omitempty"`
+ } `json:"complexField,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ ComplexField *struct {
+ AccountName *string `json:"accountName,omitempty"`
+ Name *string `json:"name,omitempty"`
+ } `json:"-"`
+ Name string `json:"name"`
+}
diff --git a/examples/extensions/xgojsonignore/generate.go b/examples/extensions/xgojsonignore/generate.go
new file mode 100644
index 000000000..0d8488e43
--- /dev/null
+++ b/examples/extensions/xgojsonignore/generate.go
@@ -0,0 +1,3 @@
+package xgojsonignore
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/extensions/xgoname/api.yaml b/examples/extensions/xgoname/api.yaml
new file mode 100644
index 000000000..579412c91
--- /dev/null
+++ b/examples/extensions/xgoname/api.yaml
@@ -0,0 +1,27 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-go-name
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ x-go-name: ClientRenamedByExtension
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ # maybe we want to be intentionally verbose here?
+ x-go-name: AccountIdentifier
diff --git a/examples/extensions/xgoname/cfg.yaml b/examples/extensions/xgoname/cfg.yaml
new file mode 100644
index 000000000..7dc65386d
--- /dev/null
+++ b/examples/extensions/xgoname/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
+package: xgoname
+output: gen.go
+generate:
+ models: true
+output-options:
+ # to make sure that all types are generated, even if they're unreferenced
+ skip-prune: true
diff --git a/examples/extensions/xgoname/gen.go b/examples/extensions/xgoname/gen.go
new file mode 100644
index 000000000..c7831379a
--- /dev/null
+++ b/examples/extensions/xgoname/gen.go
@@ -0,0 +1,16 @@
+// Package xgoname provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package xgoname
+
+// Client defines model for Client.
+type Client struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientRenamedByExtension defines model for ClientWithExtension.
+type ClientRenamedByExtension struct {
+ AccountIdentifier *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
diff --git a/examples/extensions/xgoname/generate.go b/examples/extensions/xgoname/generate.go
new file mode 100644
index 000000000..546211419
--- /dev/null
+++ b/examples/extensions/xgoname/generate.go
@@ -0,0 +1,3 @@
+package xgoname
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/extensions/xgotype/api.yaml b/examples/extensions/xgotype/api.yaml
new file mode 100644
index 000000000..5efdb0272
--- /dev/null
+++ b/examples/extensions/xgotype/api.yaml
@@ -0,0 +1,36 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-go-type
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ # this is a bit of a contrived example, as you could instead use
+ # `format: uuid` but it explains how you'd do this when there may be
+ # a clash, for instance if you already had a `uuid` package that was
+ # being imported, or ...
+ x-go-type: googleuuid.UUID
+ x-go-type-import:
+ path: github.com/google/uuid
+ name: googleuuid
+ id:
+ type: number
+ # ... this is also a bit of a contrived example, as you could use
+ # `type: integer` but in the case that you know better than what
+ # oapi-codegen is generating, like so:
+ x-go-type: int64
diff --git a/examples/extensions/xgotype/cfg.yaml b/examples/extensions/xgotype/cfg.yaml
new file mode 100644
index 000000000..afc39fcd7
--- /dev/null
+++ b/examples/extensions/xgotype/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
+package: xgotype
+output: gen.go
+generate:
+ models: true
+output-options:
+ # to make sure that all types are generated, even if they're unreferenced
+ skip-prune: true
diff --git a/examples/extensions/xgotype/gen.go b/examples/extensions/xgotype/gen.go
new file mode 100644
index 000000000..376c1fdbf
--- /dev/null
+++ b/examples/extensions/xgotype/gen.go
@@ -0,0 +1,20 @@
+// Package xgotype provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package xgotype
+
+import (
+ googleuuid "github.com/google/uuid"
+)
+
+// Client defines model for Client.
+type Client struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ Id *int64 `json:"id,omitempty"`
+ Name googleuuid.UUID `json:"name"`
+}
diff --git a/examples/extensions/xgotype/generate.go b/examples/extensions/xgotype/generate.go
new file mode 100644
index 000000000..fc28c53de
--- /dev/null
+++ b/examples/extensions/xgotype/generate.go
@@ -0,0 +1,3 @@
+package xgotype
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/extensions/xgotypename/api.yaml b/examples/extensions/xgotypename/api.yaml
new file mode 100644
index 000000000..17b83cb0f
--- /dev/null
+++ b/examples/extensions/xgotypename/api.yaml
@@ -0,0 +1,27 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-go-type-name
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ x-go-type-name: ClientRenamedByExtension
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ # NOTE attempting a `x-go-type-name` here is a no-op, as we're not producing a _type_ only a _field_
+ x-go-type-name: ThisWillNotBeUsed
diff --git a/examples/extensions/xgotypename/cfg.yaml b/examples/extensions/xgotypename/cfg.yaml
new file mode 100644
index 000000000..3a903b657
--- /dev/null
+++ b/examples/extensions/xgotypename/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
+package: xgotypename
+output: gen.go
+generate:
+ models: true
+output-options:
+ # to make sure that all types are generated, even if they're unreferenced
+ skip-prune: true
diff --git a/examples/extensions/xgotypename/gen.go b/examples/extensions/xgotypename/gen.go
new file mode 100644
index 000000000..cc0c9c2bf
--- /dev/null
+++ b/examples/extensions/xgotypename/gen.go
@@ -0,0 +1,19 @@
+// Package xgotypename provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package xgotypename
+
+// Client defines model for Client.
+type Client struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension = ClientRenamedByExtension
+
+// ClientRenamedByExtension defines model for .
+type ClientRenamedByExtension struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
diff --git a/examples/extensions/xgotypename/generate.go b/examples/extensions/xgotypename/generate.go
new file mode 100644
index 000000000..787661180
--- /dev/null
+++ b/examples/extensions/xgotypename/generate.go
@@ -0,0 +1,3 @@
+package xgotypename
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/extensions/xgotypeskipoptionalpointer/api.yaml b/examples/extensions/xgotypeskipoptionalpointer/api.yaml
new file mode 100644
index 000000000..5dac5532b
--- /dev/null
+++ b/examples/extensions/xgotypeskipoptionalpointer/api.yaml
@@ -0,0 +1,25 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-go-type-skip-optional-pointer
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ x-go-type-skip-optional-pointer: true
diff --git a/examples/extensions/xgotypeskipoptionalpointer/cfg.yaml b/examples/extensions/xgotypeskipoptionalpointer/cfg.yaml
new file mode 100644
index 000000000..bb01706cf
--- /dev/null
+++ b/examples/extensions/xgotypeskipoptionalpointer/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
+package: xgotypeskipoptionalpointer
+output: gen.go
+generate:
+ models: true
+output-options:
+ # to make sure that all types are generated, even if they're unreferenced
+ skip-prune: true
diff --git a/examples/extensions/xgotypeskipoptionalpointer/gen.go b/examples/extensions/xgotypeskipoptionalpointer/gen.go
new file mode 100644
index 000000000..ddb1df843
--- /dev/null
+++ b/examples/extensions/xgotypeskipoptionalpointer/gen.go
@@ -0,0 +1,16 @@
+// Package xgotypeskipoptionalpointer provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package xgotypeskipoptionalpointer
+
+// Client defines model for Client.
+type Client struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ Id float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
diff --git a/examples/extensions/xgotypeskipoptionalpointer/generate.go b/examples/extensions/xgotypeskipoptionalpointer/generate.go
new file mode 100644
index 000000000..582ec97fd
--- /dev/null
+++ b/examples/extensions/xgotypeskipoptionalpointer/generate.go
@@ -0,0 +1,3 @@
+package xgotypeskipoptionalpointer
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/extensions/xoapicodegenextratags/api.yaml b/examples/extensions/xoapicodegenextratags/api.yaml
new file mode 100644
index 000000000..34771334a
--- /dev/null
+++ b/examples/extensions/xoapicodegenextratags/api.yaml
@@ -0,0 +1,30 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-oapi-codegen-extra-tags
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ - id
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ - id
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ x-oapi-codegen-extra-tags:
+ validate: "required,min=1,max=256"
+ safe-to-log: "true"
+ gorm: primarykey
diff --git a/examples/extensions/xoapicodegenextratags/cfg.yaml b/examples/extensions/xoapicodegenextratags/cfg.yaml
new file mode 100644
index 000000000..582d1932a
--- /dev/null
+++ b/examples/extensions/xoapicodegenextratags/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
+package: xoapicodegenextratags
+output: gen.go
+generate:
+ models: true
+output-options:
+ # to make sure that all types are generated, even if they're unreferenced
+ skip-prune: true
diff --git a/examples/extensions/xoapicodegenextratags/gen.go b/examples/extensions/xoapicodegenextratags/gen.go
new file mode 100644
index 000000000..25f950e3d
--- /dev/null
+++ b/examples/extensions/xoapicodegenextratags/gen.go
@@ -0,0 +1,16 @@
+// Package xoapicodegenextratags provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package xoapicodegenextratags
+
+// Client defines model for Client.
+type Client struct {
+ Id float32 `json:"id"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ Id float32 `gorm:"primarykey" json:"id" safe-to-log:"true" validate:"required,min=1,max=256"`
+ Name string `json:"name"`
+}
diff --git a/examples/extensions/xoapicodegenextratags/generate.go b/examples/extensions/xoapicodegenextratags/generate.go
new file mode 100644
index 000000000..6906128b0
--- /dev/null
+++ b/examples/extensions/xoapicodegenextratags/generate.go
@@ -0,0 +1,3 @@
+package xoapicodegenextratags
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/extensions/xomitempty/api.yaml b/examples/extensions/xomitempty/api.yaml
new file mode 100644
index 000000000..d01919942
--- /dev/null
+++ b/examples/extensions/xomitempty/api.yaml
@@ -0,0 +1,26 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-omitempty
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ # for some reason, you may want this behaviour, even though it's a required field
+ x-omitempty: true
+ id:
+ type: number
diff --git a/examples/extensions/xomitempty/cfg.yaml b/examples/extensions/xomitempty/cfg.yaml
new file mode 100644
index 000000000..fe8c98508
--- /dev/null
+++ b/examples/extensions/xomitempty/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
+package: xomitempty
+output: gen.go
+generate:
+ models: true
+output-options:
+ # to make sure that all types are generated, even if they're unreferenced
+ skip-prune: true
diff --git a/examples/extensions/xomitempty/gen.go b/examples/extensions/xomitempty/gen.go
new file mode 100644
index 000000000..a4a06f97e
--- /dev/null
+++ b/examples/extensions/xomitempty/gen.go
@@ -0,0 +1,16 @@
+// Package xomitempty provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package xomitempty
+
+// Client defines model for Client.
+type Client struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ Id *float32 `json:"id,omitempty"`
+ Name string `json:"name,omitempty"`
+}
diff --git a/examples/extensions/xomitempty/generate.go b/examples/extensions/xomitempty/generate.go
new file mode 100644
index 000000000..c6c48c4fe
--- /dev/null
+++ b/examples/extensions/xomitempty/generate.go
@@ -0,0 +1,3 @@
+package xomitempty
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/extensions/xorder/api.yaml b/examples/extensions/xorder/api.yaml
new file mode 100644
index 000000000..5171a0def
--- /dev/null
+++ b/examples/extensions/xorder/api.yaml
@@ -0,0 +1,26 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: x-order
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ a_name:
+ type: string
+ id:
+ type: number
+ ClientWithExtension:
+ type: object
+ required:
+ - name
+ properties:
+ a_name:
+ type: string
+ x-order: 2
+ id:
+ type: number
+ x-order: 1
diff --git a/examples/extensions/xorder/cfg.yaml b/examples/extensions/xorder/cfg.yaml
new file mode 100644
index 000000000..0d3851f47
--- /dev/null
+++ b/examples/extensions/xorder/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
+package: xorder
+output: gen.go
+generate:
+ models: true
+output-options:
+ # to make sure that all types are generated, even if they're unreferenced
+ skip-prune: true
diff --git a/examples/extensions/xorder/gen.go b/examples/extensions/xorder/gen.go
new file mode 100644
index 000000000..bb5841d56
--- /dev/null
+++ b/examples/extensions/xorder/gen.go
@@ -0,0 +1,16 @@
+// Package xorder provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package xorder
+
+// Client defines model for Client.
+type Client struct {
+ AName *string `json:"a_name,omitempty"`
+ Id *float32 `json:"id,omitempty"`
+}
+
+// ClientWithExtension defines model for ClientWithExtension.
+type ClientWithExtension struct {
+ Id *float32 `json:"id,omitempty"`
+ AName *string `json:"a_name,omitempty"`
+}
diff --git a/examples/extensions/xorder/generate.go b/examples/extensions/xorder/generate.go
new file mode 100644
index 000000000..9b9d46563
--- /dev/null
+++ b/examples/extensions/xorder/generate.go
@@ -0,0 +1,3 @@
+package xorder
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/go.mod b/examples/go.mod
index acb387490..077872f27 100644
--- a/examples/go.mod
+++ b/examples/go.mod
@@ -1,27 +1,28 @@
-module github.com/deepmap/oapi-codegen/v2/examples
+module github.com/oapi-codegen/oapi-codegen/v2/examples
go 1.20
-replace github.com/deepmap/oapi-codegen/v2 => ../
+replace github.com/oapi-codegen/oapi-codegen/v2 => ../
require (
- github.com/deepmap/oapi-codegen/v2 v2.0.0-00010101000000-000000000000
- github.com/getkin/kin-openapi v0.122.0
- github.com/gin-gonic/gin v1.9.1
+ github.com/getkin/kin-openapi v0.124.0
+ github.com/gin-gonic/gin v1.10.0
github.com/go-chi/chi/v5 v5.0.10
- github.com/gofiber/fiber/v2 v2.49.1
- github.com/gorilla/mux v1.8.0
+ github.com/gofiber/fiber/v2 v2.52.4
+ github.com/google/uuid v1.5.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.11.3
+ github.com/labstack/echo/v4 v4.12.0
github.com/lestrrat-go/jwx v1.2.26
- github.com/oapi-codegen/echo-middleware v1.0.1
- github.com/oapi-codegen/fiber-middleware v1.0.1
- github.com/oapi-codegen/gin-middleware v1.0.1
- github.com/oapi-codegen/iris-middleware v1.0.4
- github.com/oapi-codegen/nethttp-middleware v1.0.1
+ 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
+ github.com/oapi-codegen/oapi-codegen/v2 v2.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.8.4
+ github.com/stretchr/testify v1.9.0
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
)
@@ -34,25 +35,25 @@ require (
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
- github.com/bytedance/sonic v1.10.0-rc3 // indirect
- github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
- github.com/chenzhuoyu/iasm v0.9.0 // indirect
+ github.com/bytedance/sonic v1.11.6 // indirect
+ github.com/bytedance/sonic/loader v0.1.1 // indirect
+ github.com/cloudwego/base64x v0.1.4 // indirect
+ github.com/cloudwego/iasm v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/flosch/pongo2/v4 v4.0.2 // indirect
- github.com/gabriel-vasile/mimetype v1.4.2 // indirect
+ github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
- github.com/go-openapi/jsonpointer v0.20.0 // indirect
- github.com/go-openapi/swag v0.22.4 // indirect
+ github.com/go-openapi/jsonpointer v0.20.2 // indirect
+ github.com/go-openapi/swag v0.22.8 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
- github.com/go-playground/validator/v10 v10.14.1 // indirect
+ github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gomarkdown/markdown v0.0.0-20230716120725-531d2d74bc12 // indirect
- github.com/google/uuid v1.4.0 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/invopop/yaml v0.2.0 // indirect
github.com/iris-contrib/schema v0.0.6 // indirect
@@ -63,10 +64,10 @@ 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.16.7 // indirect
- github.com/klauspost/cpuid/v2 v2.2.5 // indirect
- github.com/labstack/gommon v0.4.0 // indirect
- github.com/leodido/go-urn v1.2.4 // indirect
+ github.com/klauspost/compress v1.17.0 // 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
github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
github.com/lestrrat-go/blackmagic v1.0.1 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
@@ -75,41 +76,40 @@ require (
github.com/mailgun/raymond/v2 v2.0.48 // 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.19 // 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
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
- github.com/pelletier/go-toml/v2 v2.0.9 // indirect
+ github.com/pelletier/go-toml/v2 v2.2.2 // indirect
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/rogpeppe/go-internal v1.11.0 // 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
github.com/tdewolff/minify/v2 v2.12.9 // indirect
github.com/tdewolff/parse/v2 v2.6.8 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
- github.com/ugorji/go/codec v1.2.11 // indirect
+ github.com/ugorji/go/codec v1.2.12 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/valyala/fasthttp v1.49.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/yosssi/ace v0.0.5 // indirect
- golang.org/x/arch v0.4.0 // indirect
- golang.org/x/crypto v0.14.0 // indirect
- golang.org/x/mod v0.12.0 // indirect
- golang.org/x/net v0.17.0 // indirect
- golang.org/x/sys v0.13.0 // indirect
- golang.org/x/text v0.14.0 // indirect
- golang.org/x/time v0.3.0 // indirect
- golang.org/x/tools v0.12.0 // indirect
- google.golang.org/protobuf v1.31.0 // indirect
+ golang.org/x/arch v0.8.0 // indirect
+ golang.org/x/crypto v0.23.0 // indirect
+ golang.org/x/mod v0.17.0 // indirect
+ golang.org/x/net v0.25.0 // indirect
+ golang.org/x/sys v0.20.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/time v0.5.0 // indirect
+ golang.org/x/tools v0.21.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
gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/examples/go.sum b/examples/go.sum
index 48c332c54..692f5ab55 100644
--- a/examples/go.sum
+++ b/examples/go.sum
@@ -19,16 +19,14 @@ github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
-github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
-github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
-github.com/bytedance/sonic v1.10.0-rc3 h1:uNSnscRapXTwUgTyOF0GVljYD08p9X/Lbr9MweSV3V0=
-github.com/bytedance/sonic v1.10.0-rc3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
-github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
-github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
-github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
-github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
-github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
-github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
+github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
+github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
+github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
+github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
+github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
+github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
+github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
+github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
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=
@@ -40,50 +38,48 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
-github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
-github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
-github.com/getkin/kin-openapi v0.122.0 h1:WB9Jbl0Hp/T79/JF9xlSW5Kl9uYdk/AWD0yAd9HOM10=
-github.com/getkin/kin-openapi v0.122.0/go.mod h1:PCWw/lfBrJY4HcdqE3jj+QFkaFK8ABoqo7PvqVhXXqw=
+github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
+github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
+github.com/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M=
+github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
-github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
+github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
+github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
-github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
-github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
-github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
-github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
+github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
+github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
+github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
-github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k=
-github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
+github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
+github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
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/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.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomarkdown/markdown v0.0.0-20230716120725-531d2d74bc12 h1:uK3X/2mt4tbSGoHvbLBHUny7CKiuwUip3MArtukol4E=
github.com/gomarkdown/markdown v0.0.0-20230716120725-531d2d74bc12/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
-github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
-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-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-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=
+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/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.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
-github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
+github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
@@ -108,22 +104,22 @@ 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.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
-github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
+github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
-github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
-github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+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=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
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/labstack/echo/v4 v4.11.3 h1:Upyu3olaqSHkCjs1EJJwQ3WId8b8b1hxbogyommKktM=
-github.com/labstack/echo/v4 v4.11.3/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws=
-github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
-github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
-github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
-github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
+github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
+github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
+github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
+github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
+github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
+github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A=
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
@@ -141,13 +137,11 @@ github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqA
github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
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.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
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.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
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-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=
@@ -161,22 +155,22 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/oapi-codegen/echo-middleware v1.0.1 h1:edYGScq1phCcuDoz9AqA9eHX+tEI1LNL5PL1lkkQh1k=
-github.com/oapi-codegen/echo-middleware v1.0.1/go.mod h1:DBQKRn+D/vfXOFbaX5GRwFttoJY64JH6yu+pdt7wU3o=
-github.com/oapi-codegen/fiber-middleware v1.0.1 h1:DZQA+tEsqEMox4pPmc6SJXvDriiWSxc3QiA4UuMwGq4=
-github.com/oapi-codegen/fiber-middleware v1.0.1/go.mod h1:UUVrHLPT4Zv7S2U2TCGLXpTx6mfMb613UI+Z6F8S5Vk=
-github.com/oapi-codegen/gin-middleware v1.0.1 h1:903hkcyMcM/h6ooHS7t/2ad973BY0xvsRNP0EN1B65g=
-github.com/oapi-codegen/gin-middleware v1.0.1/go.mod h1:JDMxGX/rErQs2VV0XAVo1sD6sA0EVUMvFSPhgOLt9mE=
-github.com/oapi-codegen/iris-middleware v1.0.4 h1:+Eoqqbc90qCeBz3Zlzf1xb5xn+wfwQihndHlvU/4Meo=
-github.com/oapi-codegen/iris-middleware v1.0.4/go.mod h1:D1IAqYMgm5QKbD9R+y0j8m+xUtiPLMG92iY+oos/NXc=
-github.com/oapi-codegen/nethttp-middleware v1.0.1 h1:ZWvwfnMU0eloHX1VEJmQscQm3741t0vCm0eSIie1NIo=
-github.com/oapi-codegen/nethttp-middleware v1.0.1/go.mod h1:P7xtAvpoqNB+5obR9qRCeefH7YlXWSK3KgPs/9WB8tE=
+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=
+github.com/oapi-codegen/iris-middleware v1.0.5/go.mod h1:/ysgvbjWyhfDAouIeUOjzIv+zsXfaIXlAQrsOU9/Kyo=
+github.com/oapi-codegen/nethttp-middleware v1.0.2 h1:A5tfAcKJhWIbIPnlQH+l/DtfVE1i5TFgPlQAiW+l1vQ=
+github.com/oapi-codegen/nethttp-middleware v1.0.2/go.mod h1:DfDalonSO+eRQ3RTb8kYoWZByCCPFRxm9WKq1UbY0E4=
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/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
-github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
+github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
+github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -186,8 +180,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
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.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
-github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
@@ -200,6 +193,7 @@ github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKk
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -207,9 +201,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tdewolff/minify/v2 v2.12.9 h1:dvn5MtmuQ/DFMwqf5j8QhEVpPX6fi3WGImhv8RUB4zA=
github.com/tdewolff/minify/v2 v2.12.9/go.mod h1:qOqdlDfL+7v0/fyymB+OP497nIxJYSvX4MQWA8OoiXU=
github.com/tdewolff/parse/v2 v2.6.8 h1:mhNZXYCx//xG7Yq2e/kVLNZw4YfYmeHbhx+Zc0OvFMA=
@@ -218,13 +212,12 @@ github.com/tdewolff/test v1.0.9 h1:SswqJCmeN4B+9gEAi/5uqT0qpi1y2/2O47V/1hhGZT0=
github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
-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/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
+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.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/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=
@@ -244,22 +237,22 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3Ifn
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
-golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc=
-golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
+golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
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-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.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
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=
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.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
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=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -268,31 +261,28 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx
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.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
+golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
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-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.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=
@@ -303,26 +293,23 @@ 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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-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/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+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=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
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.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
-golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
+golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
+golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
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=
-golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
-google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
+google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
@@ -331,7 +318,6 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
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-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/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/import-mapping/admin/api.yaml b/examples/import-mapping/admin/api.yaml
new file mode 100644
index 000000000..10dd0cdd4
--- /dev/null
+++ b/examples/import-mapping/admin/api.yaml
@@ -0,0 +1,36 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Admin API
+ description: The admin-only portion of the API, which has its own separate OpenAPI spec
+tags:
+ - name: admin
+ description: Admin API endpoints
+ - name: user
+ description: API endpoint that pertains to user data
+paths:
+ /admin/user/{id}:
+ get:
+ tags:
+ - admin
+ - user
+ summary: Get a user's details
+ operationId: getUserById
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ format: uuid
+ responses:
+ 200:
+ description: Success
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+components:
+ schemas:
+ User:
+ $ref: '../common/api.yaml#/components/schemas/User'
diff --git a/examples/import-mapping/admin/cfg.yaml b/examples/import-mapping/admin/cfg.yaml
new file mode 100644
index 000000000..a888e035a
--- /dev/null
+++ b/examples/import-mapping/admin/cfg.yaml
@@ -0,0 +1,11 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
+package: admin
+output: server.gen.go
+generate:
+ models: true
+ chi-server: true
+output-options:
+ # to make sure that all types are generated
+ skip-prune: true
+import-mapping:
+ ../common/api.yaml: github.com/oapi-codegen/oapi-codegen/v2/examples/import-mapping/common
diff --git a/examples/import-mapping/admin/generate.go b/examples/import-mapping/admin/generate.go
new file mode 100644
index 000000000..0cc4cece1
--- /dev/null
+++ b/examples/import-mapping/admin/generate.go
@@ -0,0 +1,3 @@
+package admin
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/import-mapping/admin/server.gen.go b/examples/import-mapping/admin/server.gen.go
new file mode 100644
index 000000000..66d84690c
--- /dev/null
+++ b/examples/import-mapping/admin/server.gen.go
@@ -0,0 +1,189 @@
+// Package admin provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package admin
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/go-chi/chi/v5"
+ externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/examples/import-mapping/common"
+ "github.com/oapi-codegen/runtime"
+ openapi_types "github.com/oapi-codegen/runtime/types"
+)
+
+// User defines model for User.
+type User = externalRef0.User
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+ // Get a user's details
+ // (GET /admin/user/{id})
+ GetUserById(w http.ResponseWriter, r *http.Request, id openapi_types.UUID)
+}
+
+// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint.
+
+type Unimplemented struct{}
+
+// Get a user's details
+// (GET /admin/user/{id})
+func (_ Unimplemented) GetUserById(w http.ResponseWriter, r *http.Request, id openapi_types.UUID) {
+ w.WriteHeader(http.StatusNotImplemented)
+}
+
+// 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
+
+// GetUserById operation middleware
+func (siw *ServerInterfaceWrapper) GetUserById(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ var err error
+
+ // ------------- Path parameter "id" -------------
+ var id openapi_types.UUID
+
+ err = runtime.BindStyledParameterWithOptions("simple", "id", chi.URLParam(r, "id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "id", Err: err})
+ return
+ }
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.GetUserById(w, r, id)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+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, ChiServerOptions{})
+}
+
+type ChiServerOptions struct {
+ BaseURL string
+ BaseRouter chi.Router
+ 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, r chi.Router) http.Handler {
+ return HandlerWithOptions(si, ChiServerOptions{
+ BaseRouter: r,
+ })
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, r chi.Router, baseURL string) http.Handler {
+ return HandlerWithOptions(si, ChiServerOptions{
+ BaseURL: baseURL,
+ BaseRouter: r,
+ })
+}
+
+// HandlerWithOptions creates http.Handler with additional options
+func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handler {
+ r := options.BaseRouter
+
+ if r == nil {
+ r = chi.NewRouter()
+ }
+ 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,
+ }
+
+ r.Group(func(r chi.Router) {
+ r.Get(options.BaseURL+"/admin/user/{id}", wrapper.GetUserById)
+ })
+
+ return r
+}
diff --git a/examples/import-mapping/common/api.yaml b/examples/import-mapping/common/api.yaml
new file mode 100644
index 000000000..08af65a13
--- /dev/null
+++ b/examples/import-mapping/common/api.yaml
@@ -0,0 +1,10 @@
+components:
+ schemas:
+ User:
+ type: object
+ additionalProperties: false
+ properties:
+ name:
+ type: string
+ required:
+ - name
diff --git a/examples/import-mapping/common/cfg.yaml b/examples/import-mapping/common/cfg.yaml
new file mode 100644
index 000000000..8c38a4454
--- /dev/null
+++ b/examples/import-mapping/common/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
+package: common
+output: types.gen.go
+generate:
+ models: true
+output-options:
+ # to make sure that all types are generated
+ skip-prune: true
diff --git a/examples/import-mapping/common/generate.go b/examples/import-mapping/common/generate.go
new file mode 100644
index 000000000..4e7fe60ec
--- /dev/null
+++ b/examples/import-mapping/common/generate.go
@@ -0,0 +1,3 @@
+package common
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/import-mapping/common/types.gen.go b/examples/import-mapping/common/types.gen.go
new file mode 100644
index 000000000..178106064
--- /dev/null
+++ b/examples/import-mapping/common/types.gen.go
@@ -0,0 +1,9 @@
+// Package common provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package common
+
+// User defines model for User.
+type User struct {
+ Name string `json:"name"`
+}
diff --git a/examples/minimal-server/api.yaml b/examples/minimal-server/api.yaml
new file mode 100644
index 000000000..ccf4cd590
--- /dev/null
+++ b/examples/minimal-server/api.yaml
@@ -0,0 +1,25 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Minimal ping API server
+paths:
+ /ping:
+ get:
+ responses:
+ '200':
+ description: pet response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pong'
+components:
+ schemas:
+ # base types
+ Pong:
+ type: object
+ required:
+ - ping
+ properties:
+ ping:
+ type: string
+ example: pong
diff --git a/examples/minimal-server/chi/api/cfg.yaml b/examples/minimal-server/chi/api/cfg.yaml
new file mode 100644
index 000000000..c5df9dd55
--- /dev/null
+++ b/examples/minimal-server/chi/api/cfg.yaml
@@ -0,0 +1,6 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: api
+output: ping.gen.go
+generate:
+ models: true
+ chi-server: true
diff --git a/examples/minimal-server/chi/api/generate.go b/examples/minimal-server/chi/api/generate.go
new file mode 100644
index 000000000..386f093dc
--- /dev/null
+++ b/examples/minimal-server/chi/api/generate.go
@@ -0,0 +1,3 @@
+package api
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml ../../api.yaml
diff --git a/examples/minimal-server/chi/api/impl.go b/examples/minimal-server/chi/api/impl.go
new file mode 100644
index 000000000..ddb3121e9
--- /dev/null
+++ b/examples/minimal-server/chi/api/impl.go
@@ -0,0 +1,25 @@
+package api
+
+import (
+ "encoding/json"
+ "net/http"
+)
+
+// ensure that we've conformed to the `ServerInterface` with a compile-time check
+var _ ServerInterface = (*Server)(nil)
+
+type Server struct{}
+
+func NewServer() Server {
+ return Server{}
+}
+
+// (GET /ping)
+func (Server) GetPing(w http.ResponseWriter, r *http.Request) {
+ resp := Pong{
+ Ping: "pong",
+ }
+
+ w.WriteHeader(http.StatusOK)
+ _ = json.NewEncoder(w).Encode(resp)
+}
diff --git a/examples/minimal-server/chi/api/ping.gen.go b/examples/minimal-server/chi/api/ping.gen.go
new file mode 100644
index 000000000..3f4b5ce29
--- /dev/null
+++ b/examples/minimal-server/chi/api/ping.gen.go
@@ -0,0 +1,176 @@
+// Package api provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package api
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/go-chi/chi/v5"
+)
+
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /ping)
+ GetPing(w http.ResponseWriter, r *http.Request)
+}
+
+// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint.
+
+type Unimplemented struct{}
+
+// (GET /ping)
+func (_ Unimplemented) GetPing(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusNotImplemented)
+}
+
+// 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
+
+// GetPing operation middleware
+func (siw *ServerInterfaceWrapper) GetPing(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.GetPing(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+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, ChiServerOptions{})
+}
+
+type ChiServerOptions struct {
+ BaseURL string
+ BaseRouter chi.Router
+ 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, r chi.Router) http.Handler {
+ return HandlerWithOptions(si, ChiServerOptions{
+ BaseRouter: r,
+ })
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, r chi.Router, baseURL string) http.Handler {
+ return HandlerWithOptions(si, ChiServerOptions{
+ BaseURL: baseURL,
+ BaseRouter: r,
+ })
+}
+
+// HandlerWithOptions creates http.Handler with additional options
+func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handler {
+ r := options.BaseRouter
+
+ if r == nil {
+ r = chi.NewRouter()
+ }
+ 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,
+ }
+
+ r.Group(func(r chi.Router) {
+ r.Get(options.BaseURL+"/ping", wrapper.GetPing)
+ })
+
+ return r
+}
diff --git a/examples/minimal-server/chi/main.go b/examples/minimal-server/chi/main.go
new file mode 100644
index 000000000..56e0a0515
--- /dev/null
+++ b/examples/minimal-server/chi/main.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ "log"
+ "net/http"
+
+ "github.com/go-chi/chi/v5"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/chi/api"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ r := chi.NewMux()
+
+ // get an `http.Handler` that we can use
+ h := api.HandlerFromMux(server, r)
+
+ s := &http.Server{
+ Handler: h,
+ Addr: "0.0.0.0:8080",
+ }
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(s.ListenAndServe())
+}
diff --git a/examples/minimal-server/echo/api/cfg.yaml b/examples/minimal-server/echo/api/cfg.yaml
new file mode 100644
index 000000000..06bb9233e
--- /dev/null
+++ b/examples/minimal-server/echo/api/cfg.yaml
@@ -0,0 +1,6 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: api
+output: ping.gen.go
+generate:
+ models: true
+ echo-server: true
diff --git a/examples/minimal-server/echo/api/generate.go b/examples/minimal-server/echo/api/generate.go
new file mode 100644
index 000000000..386f093dc
--- /dev/null
+++ b/examples/minimal-server/echo/api/generate.go
@@ -0,0 +1,3 @@
+package api
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml ../../api.yaml
diff --git a/examples/minimal-server/echo/api/impl.go b/examples/minimal-server/echo/api/impl.go
new file mode 100644
index 000000000..355c69bba
--- /dev/null
+++ b/examples/minimal-server/echo/api/impl.go
@@ -0,0 +1,25 @@
+package api
+
+import (
+ "net/http"
+
+ "github.com/labstack/echo/v4"
+)
+
+// ensure that we've conformed to the `ServerInterface` with a compile-time check
+var _ ServerInterface = (*Server)(nil)
+
+type Server struct{}
+
+func NewServer() Server {
+ return Server{}
+}
+
+// (GET /ping)
+func (Server) GetPing(ctx echo.Context) error {
+ resp := Pong{
+ Ping: "pong",
+ }
+
+ return ctx.JSON(http.StatusOK, resp)
+}
diff --git a/examples/minimal-server/echo/api/ping.gen.go b/examples/minimal-server/echo/api/ping.gen.go
new file mode 100644
index 000000000..bd78f8f2a
--- /dev/null
+++ b/examples/minimal-server/echo/api/ping.gen.go
@@ -0,0 +1,66 @@
+// Package api provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package api
+
+import (
+ "github.com/labstack/echo/v4"
+)
+
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /ping)
+ GetPing(ctx echo.Context) error
+}
+
+// ServerInterfaceWrapper converts echo contexts to parameters.
+type ServerInterfaceWrapper struct {
+ Handler ServerInterface
+}
+
+// GetPing converts echo context to params.
+func (w *ServerInterfaceWrapper) GetPing(ctx echo.Context) error {
+ var err error
+
+ // Invoke the callback with all the unmarshaled arguments
+ err = w.Handler.GetPing(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+"/ping", wrapper.GetPing)
+
+}
diff --git a/examples/minimal-server/echo/main.go b/examples/minimal-server/echo/main.go
new file mode 100644
index 000000000..ae53667f3
--- /dev/null
+++ b/examples/minimal-server/echo/main.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+ "log"
+
+ "github.com/labstack/echo/v4"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/echo/api"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ e := echo.New()
+
+ api.RegisterHandlers(e, server)
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(e.Start("0.0.0.0:8080"))
+}
diff --git a/examples/minimal-server/fiber/api/cfg.yaml b/examples/minimal-server/fiber/api/cfg.yaml
new file mode 100644
index 000000000..79b6e07ac
--- /dev/null
+++ b/examples/minimal-server/fiber/api/cfg.yaml
@@ -0,0 +1,6 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: api
+output: ping.gen.go
+generate:
+ models: true
+ fiber-server: true
diff --git a/examples/minimal-server/fiber/api/generate.go b/examples/minimal-server/fiber/api/generate.go
new file mode 100644
index 000000000..386f093dc
--- /dev/null
+++ b/examples/minimal-server/fiber/api/generate.go
@@ -0,0 +1,3 @@
+package api
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml ../../api.yaml
diff --git a/examples/minimal-server/fiber/api/impl.go b/examples/minimal-server/fiber/api/impl.go
new file mode 100644
index 000000000..20bcf8478
--- /dev/null
+++ b/examples/minimal-server/fiber/api/impl.go
@@ -0,0 +1,27 @@
+package api
+
+import (
+ "net/http"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+// ensure that we've conformed to the `ServerInterface` with a compile-time check
+var _ ServerInterface = (*Server)(nil)
+
+type Server struct{}
+
+func NewServer() Server {
+ return Server{}
+}
+
+// (GET /ping)
+func (Server) GetPing(ctx *fiber.Ctx) error {
+ resp := Pong{
+ Ping: "pong",
+ }
+
+ return ctx.
+ Status(http.StatusOK).
+ JSON(resp)
+}
diff --git a/examples/minimal-server/fiber/api/ping.gen.go b/examples/minimal-server/fiber/api/ping.gen.go
new file mode 100644
index 000000000..a21e6fa95
--- /dev/null
+++ b/examples/minimal-server/fiber/api/ping.gen.go
@@ -0,0 +1,58 @@
+// Package api provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package api
+
+import (
+ "github.com/gofiber/fiber/v2"
+)
+
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /ping)
+ GetPing(c *fiber.Ctx) error
+}
+
+// ServerInterfaceWrapper converts contexts to parameters.
+type ServerInterfaceWrapper struct {
+ Handler ServerInterface
+}
+
+type MiddlewareFunc fiber.Handler
+
+// GetPing operation middleware
+func (siw *ServerInterfaceWrapper) GetPing(c *fiber.Ctx) error {
+
+ return siw.Handler.GetPing(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+"/ping", wrapper.GetPing)
+
+}
diff --git a/examples/minimal-server/fiber/main.go b/examples/minimal-server/fiber/main.go
new file mode 100644
index 000000000..88504af7b
--- /dev/null
+++ b/examples/minimal-server/fiber/main.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+ "log"
+
+ "github.com/gofiber/fiber/v2"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/fiber/api"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ app := fiber.New()
+
+ api.RegisterHandlers(app, server)
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(app.Listen("0.0.0.0:8080"))
+}
diff --git a/examples/minimal-server/gin/api/cfg.yaml b/examples/minimal-server/gin/api/cfg.yaml
new file mode 100644
index 000000000..951cb3f6b
--- /dev/null
+++ b/examples/minimal-server/gin/api/cfg.yaml
@@ -0,0 +1,6 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: api
+output: ping.gen.go
+generate:
+ models: true
+ gin-server: true
diff --git a/examples/minimal-server/gin/api/generate.go b/examples/minimal-server/gin/api/generate.go
new file mode 100644
index 000000000..386f093dc
--- /dev/null
+++ b/examples/minimal-server/gin/api/generate.go
@@ -0,0 +1,3 @@
+package api
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml ../../api.yaml
diff --git a/examples/minimal-server/gin/api/impl.go b/examples/minimal-server/gin/api/impl.go
new file mode 100644
index 000000000..663105193
--- /dev/null
+++ b/examples/minimal-server/gin/api/impl.go
@@ -0,0 +1,25 @@
+package api
+
+import (
+ "net/http"
+
+ "github.com/gin-gonic/gin"
+)
+
+// ensure that we've conformed to the `ServerInterface` with a compile-time check
+var _ ServerInterface = (*Server)(nil)
+
+type Server struct{}
+
+func NewServer() Server {
+ return Server{}
+}
+
+// (GET /ping)
+func (Server) GetPing(ctx *gin.Context) {
+ resp := Pong{
+ Ping: "pong",
+ }
+
+ ctx.JSON(http.StatusOK, resp)
+}
diff --git a/examples/minimal-server/gin/api/ping.gen.go b/examples/minimal-server/gin/api/ping.gen.go
new file mode 100644
index 000000000..8e018d4e8
--- /dev/null
+++ b/examples/minimal-server/gin/api/ping.gen.go
@@ -0,0 +1,72 @@
+// Package api provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package api
+
+import (
+ "github.com/gin-gonic/gin"
+)
+
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /ping)
+ GetPing(c *gin.Context)
+}
+
+// ServerInterfaceWrapper converts contexts to parameters.
+type ServerInterfaceWrapper struct {
+ Handler ServerInterface
+ HandlerMiddlewares []MiddlewareFunc
+ ErrorHandler func(*gin.Context, error, int)
+}
+
+type MiddlewareFunc func(c *gin.Context)
+
+// GetPing operation middleware
+func (siw *ServerInterfaceWrapper) GetPing(c *gin.Context) {
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ middleware(c)
+ if c.IsAborted() {
+ return
+ }
+ }
+
+ siw.Handler.GetPing(c)
+}
+
+// GinServerOptions provides options for the Gin server.
+type GinServerOptions struct {
+ BaseURL string
+ Middlewares []MiddlewareFunc
+ ErrorHandler func(*gin.Context, error, int)
+}
+
+// RegisterHandlers creates http.Handler with routing matching OpenAPI spec.
+func RegisterHandlers(router gin.IRouter, si ServerInterface) {
+ RegisterHandlersWithOptions(router, si, GinServerOptions{})
+}
+
+// RegisterHandlersWithOptions creates http.Handler with additional options
+func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) {
+ errorHandler := options.ErrorHandler
+ if errorHandler == nil {
+ errorHandler = func(c *gin.Context, err error, statusCode int) {
+ c.JSON(statusCode, gin.H{"msg": err.Error()})
+ }
+ }
+
+ wrapper := ServerInterfaceWrapper{
+ Handler: si,
+ HandlerMiddlewares: options.Middlewares,
+ ErrorHandler: errorHandler,
+ }
+
+ router.GET(options.BaseURL+"/ping", wrapper.GetPing)
+}
diff --git a/examples/minimal-server/gin/gin b/examples/minimal-server/gin/gin
new file mode 100755
index 000000000..225e21ff8
Binary files /dev/null and b/examples/minimal-server/gin/gin differ
diff --git a/examples/minimal-server/gin/main.go b/examples/minimal-server/gin/main.go
new file mode 100644
index 000000000..365932e31
--- /dev/null
+++ b/examples/minimal-server/gin/main.go
@@ -0,0 +1,28 @@
+package main
+
+import (
+ "log"
+ "net/http"
+
+ "github.com/gin-gonic/gin"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/gin/api"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ r := gin.Default()
+
+ api.RegisterHandlers(r, server)
+
+ // And we serve HTTP until the world ends.
+
+ s := &http.Server{
+ Handler: r,
+ Addr: "0.0.0.0:8080",
+ }
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(s.ListenAndServe())
+}
diff --git a/examples/minimal-server/gorillamux/api/cfg.yaml b/examples/minimal-server/gorillamux/api/cfg.yaml
new file mode 100644
index 000000000..f68fe1c11
--- /dev/null
+++ b/examples/minimal-server/gorillamux/api/cfg.yaml
@@ -0,0 +1,6 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: api
+output: ping.gen.go
+generate:
+ models: true
+ gorilla-server: true
diff --git a/examples/minimal-server/gorillamux/api/generate.go b/examples/minimal-server/gorillamux/api/generate.go
new file mode 100644
index 000000000..386f093dc
--- /dev/null
+++ b/examples/minimal-server/gorillamux/api/generate.go
@@ -0,0 +1,3 @@
+package api
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml ../../api.yaml
diff --git a/examples/minimal-server/gorillamux/api/impl.go b/examples/minimal-server/gorillamux/api/impl.go
new file mode 100644
index 000000000..ddb3121e9
--- /dev/null
+++ b/examples/minimal-server/gorillamux/api/impl.go
@@ -0,0 +1,25 @@
+package api
+
+import (
+ "encoding/json"
+ "net/http"
+)
+
+// ensure that we've conformed to the `ServerInterface` with a compile-time check
+var _ ServerInterface = (*Server)(nil)
+
+type Server struct{}
+
+func NewServer() Server {
+ return Server{}
+}
+
+// (GET /ping)
+func (Server) GetPing(w http.ResponseWriter, r *http.Request) {
+ resp := Pong{
+ Ping: "pong",
+ }
+
+ w.WriteHeader(http.StatusOK)
+ _ = json.NewEncoder(w).Encode(resp)
+}
diff --git a/examples/minimal-server/gorillamux/api/ping.gen.go b/examples/minimal-server/gorillamux/api/ping.gen.go
new file mode 100644
index 000000000..f62e3c7f0
--- /dev/null
+++ b/examples/minimal-server/gorillamux/api/ping.gen.go
@@ -0,0 +1,165 @@
+// Package api provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package api
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/gorilla/mux"
+)
+
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /ping)
+ GetPing(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
+
+// GetPing operation middleware
+func (siw *ServerInterfaceWrapper) GetPing(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.GetPing(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+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, GorillaServerOptions{})
+}
+
+type GorillaServerOptions struct {
+ BaseURL string
+ BaseRouter *mux.Router
+ 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, r *mux.Router) http.Handler {
+ return HandlerWithOptions(si, GorillaServerOptions{
+ BaseRouter: r,
+ })
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, r *mux.Router, baseURL string) http.Handler {
+ return HandlerWithOptions(si, GorillaServerOptions{
+ BaseURL: baseURL,
+ BaseRouter: r,
+ })
+}
+
+// HandlerWithOptions creates http.Handler with additional options
+func HandlerWithOptions(si ServerInterface, options GorillaServerOptions) http.Handler {
+ r := options.BaseRouter
+
+ if r == nil {
+ r = mux.NewRouter()
+ }
+ 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,
+ }
+
+ r.HandleFunc(options.BaseURL+"/ping", wrapper.GetPing).Methods("GET")
+
+ return r
+}
diff --git a/examples/minimal-server/gorillamux/main.go b/examples/minimal-server/gorillamux/main.go
new file mode 100644
index 000000000..5d7dc87f7
--- /dev/null
+++ b/examples/minimal-server/gorillamux/main.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ "log"
+ "net/http"
+
+ "github.com/gorilla/mux"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/gorillamux/api"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ r := mux.NewRouter()
+
+ // get an `http.Handler` that we can use
+ h := api.HandlerFromMux(server, r)
+
+ s := &http.Server{
+ Handler: h,
+ Addr: "0.0.0.0:8080",
+ }
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(s.ListenAndServe())
+}
diff --git a/examples/minimal-server/iris/api/cfg.yaml b/examples/minimal-server/iris/api/cfg.yaml
new file mode 100644
index 000000000..1f83520f7
--- /dev/null
+++ b/examples/minimal-server/iris/api/cfg.yaml
@@ -0,0 +1,6 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: api
+output: ping.gen.go
+generate:
+ models: true
+ iris-server: true
diff --git a/examples/minimal-server/iris/api/generate.go b/examples/minimal-server/iris/api/generate.go
new file mode 100644
index 000000000..386f093dc
--- /dev/null
+++ b/examples/minimal-server/iris/api/generate.go
@@ -0,0 +1,3 @@
+package api
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml ../../api.yaml
diff --git a/examples/minimal-server/iris/api/impl.go b/examples/minimal-server/iris/api/impl.go
new file mode 100644
index 000000000..4adbd04b3
--- /dev/null
+++ b/examples/minimal-server/iris/api/impl.go
@@ -0,0 +1,26 @@
+package api
+
+import (
+ "net/http"
+
+ "github.com/kataras/iris/v12"
+)
+
+// ensure that we've conformed to the `ServerInterface` with a compile-time check
+var _ ServerInterface = (*Server)(nil)
+
+type Server struct{}
+
+func NewServer() Server {
+ return Server{}
+}
+
+// (GET /ping)
+func (Server) GetPing(ctx iris.Context) {
+ resp := Pong{
+ Ping: "pong",
+ }
+
+ ctx.StatusCode(http.StatusOK)
+ _ = ctx.JSON(resp)
+}
diff --git a/examples/minimal-server/iris/api/ping.gen.go b/examples/minimal-server/iris/api/ping.gen.go
new file mode 100644
index 000000000..144166eba
--- /dev/null
+++ b/examples/minimal-server/iris/api/ping.gen.go
@@ -0,0 +1,57 @@
+// Package api provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package api
+
+import (
+ "github.com/kataras/iris/v12"
+)
+
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /ping)
+ GetPing(ctx iris.Context)
+}
+
+// ServerInterfaceWrapper converts echo contexts to parameters.
+type ServerInterfaceWrapper struct {
+ Handler ServerInterface
+}
+
+type MiddlewareFunc iris.Handler
+
+// GetPing converts iris context to params.
+func (w *ServerInterfaceWrapper) GetPing(ctx iris.Context) {
+
+ // Invoke the callback with all the unmarshaled arguments
+ w.Handler.GetPing(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+"/ping", wrapper.GetPing)
+
+ router.Build()
+}
diff --git a/examples/minimal-server/iris/main.go b/examples/minimal-server/iris/main.go
new file mode 100644
index 000000000..a163d6f59
--- /dev/null
+++ b/examples/minimal-server/iris/main.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+ "log"
+
+ "github.com/kataras/iris/v12"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/iris/api"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ i := iris.Default()
+
+ api.RegisterHandlers(i, server)
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(i.Listen("0.0.0.0:8080"))
+}
diff --git a/examples/minimal-server/nethttp-compatible/main.go b/examples/minimal-server/nethttp-compatible/main.go
new file mode 100644
index 000000000..784b741cf
--- /dev/null
+++ b/examples/minimal-server/nethttp-compatible/main.go
@@ -0,0 +1,24 @@
+package main
+
+import (
+ "log"
+ "net/http"
+
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/gorillamux/api"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ // get an `http.Handler` that we can use, but notice that we don't need to specify the router (although under-the-hood it'll use the generated router)
+ h := api.Handler(server)
+
+ s := &http.Server{
+ Handler: h,
+ Addr: "0.0.0.0:8080",
+ }
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(s.ListenAndServe())
+}
diff --git a/examples/minimal-server/stdhttp/Makefile b/examples/minimal-server/stdhttp/Makefile
new file mode 100644
index 000000000..66f60e4a2
--- /dev/null
+++ b/examples/minimal-server/stdhttp/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 -f2 -d. <<< $(GOVER)")
+
+define execute-if-go-122
+@{ \
+if [[ 22 -le $(GOMINOR) ]]; then \
+ $1; \
+else \
+ echo -e "$(YELLOW)Skipping task as you're running Go v1.$(GOMINOR).x which is < Go 1.22, which this module requires$(RESET)"; \
+fi \
+}
+endef
+
+lint:
+ $(call execute-if-go-122,$(GOBIN)/golangci-lint run ./...)
+
+lint-ci:
+
+ $(call execute-if-go-122,$(GOBIN)/golangci-lint run ./... --out-format=colored-line-number --timeout=5m)
+
+generate:
+ $(call execute-if-go-122,go generate ./...)
+
+test:
+ $(call execute-if-go-122,go test -cover ./...)
+
+tidy:
+ $(call execute-if-go-122,go mod tidy)
+
+tidy-ci:
+ $(call execute-if-go-122,tidied -verbose)
diff --git a/examples/minimal-server/stdhttp/api/cfg.yaml b/examples/minimal-server/stdhttp/api/cfg.yaml
new file mode 100644
index 000000000..4369e342f
--- /dev/null
+++ b/examples/minimal-server/stdhttp/api/cfg.yaml
@@ -0,0 +1,6 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: api
+output: ping.gen.go
+generate:
+ models: true
+ std-http-server: true
diff --git a/examples/minimal-server/stdhttp/api/generate.go b/examples/minimal-server/stdhttp/api/generate.go
new file mode 100644
index 000000000..386f093dc
--- /dev/null
+++ b/examples/minimal-server/stdhttp/api/generate.go
@@ -0,0 +1,3 @@
+package api
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml ../../api.yaml
diff --git a/examples/minimal-server/stdhttp/api/impl.go b/examples/minimal-server/stdhttp/api/impl.go
new file mode 100644
index 000000000..ddb3121e9
--- /dev/null
+++ b/examples/minimal-server/stdhttp/api/impl.go
@@ -0,0 +1,25 @@
+package api
+
+import (
+ "encoding/json"
+ "net/http"
+)
+
+// ensure that we've conformed to the `ServerInterface` with a compile-time check
+var _ ServerInterface = (*Server)(nil)
+
+type Server struct{}
+
+func NewServer() Server {
+ return Server{}
+}
+
+// (GET /ping)
+func (Server) GetPing(w http.ResponseWriter, r *http.Request) {
+ resp := Pong{
+ Ping: "pong",
+ }
+
+ w.WriteHeader(http.StatusOK)
+ _ = json.NewEncoder(w).Encode(resp)
+}
diff --git a/examples/minimal-server/stdhttp/api/ping.gen.go b/examples/minimal-server/stdhttp/api/ping.gen.go
new file mode 100644
index 000000000..6d11afc6e
--- /dev/null
+++ b/examples/minimal-server/stdhttp/api/ping.gen.go
@@ -0,0 +1,166 @@
+//go:build go1.22
+
+// Package api provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package api
+
+import (
+ "fmt"
+ "net/http"
+)
+
+// Pong defines model for Pong.
+type Pong struct {
+ Ping string `json:"ping"`
+}
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (GET /ping)
+ GetPing(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
+
+// GetPing operation middleware
+func (siw *ServerInterfaceWrapper) GetPing(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.GetPing(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+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{})
+}
+
+type StdHTTPServerOptions struct {
+ BaseURL string
+ BaseRouter *http.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 *http.ServeMux) http.Handler {
+ return HandlerWithOptions(si, StdHTTPServerOptions{
+ BaseRouter: m,
+ })
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, m *http.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+"/ping", wrapper.GetPing)
+
+ return m
+}
diff --git a/examples/minimal-server/stdhttp/go.mod b/examples/minimal-server/stdhttp/go.mod
new file mode 100644
index 000000000..f2385d10f
--- /dev/null
+++ b/examples/minimal-server/stdhttp/go.mod
@@ -0,0 +1,23 @@
+module github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/stdhttp
+
+go 1.22
+
+replace github.com/oapi-codegen/oapi-codegen/v2 => ../../../
+
+require github.com/oapi-codegen/oapi-codegen/v2 v2.0.0-00010101000000-000000000000
+
+require (
+ github.com/getkin/kin-openapi v0.124.0 // indirect
+ github.com/go-openapi/jsonpointer v0.20.2 // indirect
+ github.com/go-openapi/swag v0.22.8 // indirect
+ github.com/invopop/yaml v0.2.0 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
+ github.com/perimeterx/marshmallow v1.1.5 // indirect
+ golang.org/x/mod v0.17.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/tools v0.21.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
new file mode 100644
index 000000000..1271a908d
--- /dev/null
+++ b/examples/minimal-server/stdhttp/go.sum
@@ -0,0 +1,48 @@
+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/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M=
+github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
+github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
+github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
+github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
+github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
+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/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
+github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
+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/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+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/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/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/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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
+github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
+golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
+golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/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/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/main.go b/examples/minimal-server/stdhttp/main.go
new file mode 100644
index 000000000..8ee94ec49
--- /dev/null
+++ b/examples/minimal-server/stdhttp/main.go
@@ -0,0 +1,26 @@
+package main
+
+import (
+ "log"
+ "net/http"
+
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/minimal-server/stdhttp/api"
+)
+
+func main() {
+ // create a type that satisfies the `api.ServerInterface`, which contains an implementation of every operation from the generated code
+ server := api.NewServer()
+
+ r := http.NewServeMux()
+
+ // get an `http.Handler` that we can use
+ h := api.HandlerFromMux(server, r)
+
+ s := &http.Server{
+ Handler: h,
+ Addr: "0.0.0.0:8080",
+ }
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(s.ListenAndServe())
+}
diff --git a/examples/minimal-server/stdhttp/tools/tools.go b/examples/minimal-server/stdhttp/tools/tools.go
new file mode 100644
index 000000000..8615cb4c5
--- /dev/null
+++ b/examples/minimal-server/stdhttp/tools/tools.go
@@ -0,0 +1,8 @@
+//go:build tools
+// +build tools
+
+package tools
+
+import (
+ _ "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen"
+)
diff --git a/examples/no-vcs-version-override/echo/api/api.gen.go b/examples/no-vcs-version-override/echo/api/api.gen.go
index 6ce0064e5..e95391fd1 100644
--- a/examples/no-vcs-version-override/echo/api/api.gen.go
+++ b/examples/no-vcs-version-override/echo/api/api.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v123.456.789 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v123.456.789 DO NOT EDIT.
package api
import (
diff --git a/examples/no-vcs-version-override/echo/api/config.yaml b/examples/no-vcs-version-override/echo/api/config.yaml
index 00bb9c1a2..1f6140c6e 100644
--- a/examples/no-vcs-version-override/echo/api/config.yaml
+++ b/examples/no-vcs-version-override/echo/api/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
echo-server: true
diff --git a/examples/no-vcs-version-override/echo/api/doc.go b/examples/no-vcs-version-override/echo/api/doc.go
index 82d3898ce..03f5a0318 100644
--- a/examples/no-vcs-version-override/echo/api/doc.go
+++ b/examples/no-vcs-version-override/echo/api/doc.go
@@ -1,3 +1,3 @@
package api
-//go:generate go run -ldflags "-X main.noVCSVersionOverride=v123.456.789" github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../../api.yaml
+//go:generate go run -ldflags "-X main.noVCSVersionOverride=v123.456.789" github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../../api.yaml
diff --git a/examples/only-models/api.yaml b/examples/only-models/api.yaml
new file mode 100644
index 000000000..4e3d82066
--- /dev/null
+++ b/examples/only-models/api.yaml
@@ -0,0 +1,50 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Generate models
+paths:
+ /client:
+ get:
+ operationId: getClient
+ responses:
+ 200:
+ content:
+ application/json:
+ schema:
+ # NOTE that Client is generated here, because it's within #/components/schemas
+ $ref: "#/components/schemas/Client"
+ put:
+ operationId: updateClient
+ responses:
+ 400:
+ content:
+ application/json:
+ # NOTE that this anonymous object is /not/ generated because it's an anonymous, but would be generated if using `generate: client`
+ # See https://github.com/deepmap/oapi-codegen/issues/1512
+ schema:
+ type: object
+ properties:
+ code:
+ type: string
+ required:
+ - code
+components:
+ schemas:
+ Client:
+ type: object
+ required:
+ - name
+ properties:
+ name:
+ type: string
+ # NOTE that this is not generated by default because it's not referenced. If you want it, you need to use the following YAML configuration:
+ #
+ # output-options:
+ # skip-prune: true
+ Unreferenced:
+ type: object
+ required:
+ - id
+ properties:
+ id:
+ type: integer
diff --git a/examples/only-models/cfg.yaml b/examples/only-models/cfg.yaml
new file mode 100644
index 000000000..01f4745bb
--- /dev/null
+++ b/examples/only-models/cfg.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../configuration-schema.json
+package: onlymodels
+output: only-models.gen.go
+generate:
+ models: true
+output-options:
+ # NOTE that this is only required for the `Unreferenced` type
+ skip-prune: true
diff --git a/examples/only-models/generate.go b/examples/only-models/generate.go
new file mode 100644
index 000000000..91b495725
--- /dev/null
+++ b/examples/only-models/generate.go
@@ -0,0 +1,3 @@
+package onlymodels
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config cfg.yaml api.yaml
diff --git a/examples/only-models/only-models.gen.go b/examples/only-models/only-models.gen.go
new file mode 100644
index 000000000..c8f33c9c8
--- /dev/null
+++ b/examples/only-models/only-models.gen.go
@@ -0,0 +1,14 @@
+// Package onlymodels provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package onlymodels
+
+// Client defines model for Client.
+type Client struct {
+ Name string `json:"name"`
+}
+
+// Unreferenced defines model for Unreferenced.
+type Unreferenced struct {
+ Id int `json:"id"`
+}
diff --git a/examples/petstore-expanded/chi/api/cfg.yaml b/examples/petstore-expanded/chi/api/cfg.yaml
index d1a29f337..4191a3047 100644
--- a/examples/petstore-expanded/chi/api/cfg.yaml
+++ b/examples/petstore-expanded/chi/api/cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
chi-server: true
diff --git a/examples/petstore-expanded/chi/api/petstore.gen.go b/examples/petstore-expanded/chi/api/petstore.gen.go
index 5f69e4bfa..89777eba0 100644
--- a/examples/petstore-expanded/chi/api/petstore.gen.go
+++ b/examples/petstore-expanded/chi/api/petstore.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/examples/petstore-expanded/chi/api/petstore.go b/examples/petstore-expanded/chi/api/petstore.go
index 888d16f13..6ede559ec 100644
--- a/examples/petstore-expanded/chi/api/petstore.go
+++ b/examples/petstore-expanded/chi/api/petstore.go
@@ -1,4 +1,4 @@
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=cfg.yaml ../../petstore-expanded.yaml
package api
diff --git a/examples/petstore-expanded/chi/petstore.go b/examples/petstore-expanded/chi/petstore.go
index 20b1f5ce8..b525fa576 100644
--- a/examples/petstore-expanded/chi/petstore.go
+++ b/examples/petstore-expanded/chi/petstore.go
@@ -12,9 +12,9 @@ import (
"net/http"
"os"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/chi/api"
- middleware "github.com/oapi-codegen/nethttp-middleware"
"github.com/go-chi/chi/v5"
+ middleware "github.com/oapi-codegen/nethttp-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/chi/api"
)
func main() {
diff --git a/examples/petstore-expanded/chi/petstore_test.go b/examples/petstore-expanded/chi/petstore_test.go
index aa2380e60..e9d7662b4 100644
--- a/examples/petstore-expanded/chi/petstore_test.go
+++ b/examples/petstore-expanded/chi/petstore_test.go
@@ -7,10 +7,10 @@ import (
"net/http/httptest"
"testing"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/chi/api"
+ "github.com/go-chi/chi/v5"
middleware "github.com/oapi-codegen/nethttp-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/chi/api"
"github.com/oapi-codegen/testutil"
- "github.com/go-chi/chi/v5"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
diff --git a/examples/petstore-expanded/echo/api/models.cfg.yaml b/examples/petstore-expanded/echo/api/models.cfg.yaml
index c1b80a89d..46b5e629c 100644
--- a/examples/petstore-expanded/echo/api/models.cfg.yaml
+++ b/examples/petstore-expanded/echo/api/models.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: models
generate:
models: true
diff --git a/examples/petstore-expanded/echo/api/models/models.gen.go b/examples/petstore-expanded/echo/api/models/models.gen.go
index 61880b8d6..0945e02ab 100644
--- a/examples/petstore-expanded/echo/api/models/models.gen.go
+++ b/examples/petstore-expanded/echo/api/models/models.gen.go
@@ -1,6 +1,6 @@
// Package models provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package models
// Error defines model for Error.
diff --git a/examples/petstore-expanded/echo/api/petstore-server.gen.go b/examples/petstore-expanded/echo/api/petstore-server.gen.go
index e92c4a0cc..8767c17a1 100644
--- a/examples/petstore-expanded/echo/api/petstore-server.gen.go
+++ b/examples/petstore-expanded/echo/api/petstore-server.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
@@ -13,9 +13,9 @@ import (
"path"
"strings"
- . "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/echo/api/models"
"github.com/getkin/kin-openapi/openapi3"
"github.com/labstack/echo/v4"
+ . "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/echo/api/models"
"github.com/oapi-codegen/runtime"
)
diff --git a/examples/petstore-expanded/echo/api/petstore.go b/examples/petstore-expanded/echo/api/petstore.go
index 4c3f412fb..9934fa992 100644
--- a/examples/petstore-expanded/echo/api/petstore.go
+++ b/examples/petstore-expanded/echo/api/petstore.go
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=models.cfg.yaml ../../petstore-expanded.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=models.cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../../petstore-expanded.yaml
package api
@@ -22,8 +22,8 @@ import (
"net/http"
"sync"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/echo/api/models"
"github.com/labstack/echo/v4"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/echo/api/models"
)
type PetStore struct {
diff --git a/examples/petstore-expanded/echo/api/server.cfg.yaml b/examples/petstore-expanded/echo/api/server.cfg.yaml
index 813270fa9..534f4d8f5 100644
--- a/examples/petstore-expanded/echo/api/server.cfg.yaml
+++ b/examples/petstore-expanded/echo/api/server.cfg.yaml
@@ -1,7 +1,8 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
output: petstore-server.gen.go
additional-imports:
- - package: github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/echo/api/models
+ - package: github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/echo/api/models
alias: .
generate:
echo-server: true
diff --git a/examples/petstore-expanded/echo/petstore.go b/examples/petstore-expanded/echo/petstore.go
index ea13d7192..5ea025050 100644
--- a/examples/petstore-expanded/echo/petstore.go
+++ b/examples/petstore-expanded/echo/petstore.go
@@ -11,10 +11,10 @@ import (
"net"
"os"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/echo/api"
"github.com/labstack/echo/v4"
echomiddleware "github.com/labstack/echo/v4/middleware"
middleware "github.com/oapi-codegen/echo-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/echo/api"
)
func main() {
diff --git a/examples/petstore-expanded/echo/petstore_test.go b/examples/petstore-expanded/echo/petstore_test.go
index 062812559..5fc058da9 100644
--- a/examples/petstore-expanded/echo/petstore_test.go
+++ b/examples/petstore-expanded/echo/petstore_test.go
@@ -19,12 +19,12 @@ import (
"net/http"
"testing"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/echo/api"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/echo/api/models"
- "github.com/oapi-codegen/testutil"
"github.com/labstack/echo/v4"
echoMiddleware "github.com/labstack/echo/v4/middleware"
middleware "github.com/oapi-codegen/echo-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/echo/api"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/echo/api/models"
+ "github.com/oapi-codegen/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
diff --git a/examples/petstore-expanded/echo/pkg_codegen_petstore_test.go b/examples/petstore-expanded/echo/pkg_codegen_petstore_test.go
index a6696c296..de651ec54 100644
--- a/examples/petstore-expanded/echo/pkg_codegen_petstore_test.go
+++ b/examples/petstore-expanded/echo/pkg_codegen_petstore_test.go
@@ -9,9 +9,9 @@ import (
"net/http/httptest"
"testing"
- examplePetstoreClient "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded"
- examplePetstore "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/echo/api"
- "github.com/deepmap/oapi-codegen/v2/pkg/codegen"
+ examplePetstoreClient "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded"
+ examplePetstore "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/echo/api"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen"
"github.com/stretchr/testify/assert"
"golang.org/x/lint"
)
diff --git a/examples/petstore-expanded/fiber/api/petstore-server.gen.go b/examples/petstore-expanded/fiber/api/petstore-server.gen.go
index bb8538efd..5b01b84a0 100644
--- a/examples/petstore-expanded/fiber/api/petstore-server.gen.go
+++ b/examples/petstore-expanded/fiber/api/petstore-server.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
@@ -127,7 +127,7 @@ func RegisterHandlersWithOptions(router fiber.Router, si ServerInterface, option
}
for _, m := range options.Middlewares {
- router.Use(m)
+ router.Use(fiber.Handler(m))
}
router.Get(options.BaseURL+"/pets", wrapper.FindPets)
diff --git a/examples/petstore-expanded/fiber/api/petstore-types.gen.go b/examples/petstore-expanded/fiber/api/petstore-types.gen.go
index 3d8ce1134..0e4954f34 100644
--- a/examples/petstore-expanded/fiber/api/petstore-types.gen.go
+++ b/examples/petstore-expanded/fiber/api/petstore-types.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
// Error defines model for Error.
diff --git a/examples/petstore-expanded/fiber/api/petstore.go b/examples/petstore-expanded/fiber/api/petstore.go
index df03e511e..38eec12d6 100644
--- a/examples/petstore-expanded/fiber/api/petstore.go
+++ b/examples/petstore-expanded/fiber/api/petstore.go
@@ -1,5 +1,5 @@
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../../petstore-expanded.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../../petstore-expanded.yaml
package api
diff --git a/examples/petstore-expanded/fiber/api/server.cfg.yaml b/examples/petstore-expanded/fiber/api/server.cfg.yaml
index 91ef1331d..638408629 100644
--- a/examples/petstore-expanded/fiber/api/server.cfg.yaml
+++ b/examples/petstore-expanded/fiber/api/server.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
fiber-server: true
diff --git a/examples/petstore-expanded/fiber/api/types.cfg.yaml b/examples/petstore-expanded/fiber/api/types.cfg.yaml
index 9ac30e11e..cf5128b72 100644
--- a/examples/petstore-expanded/fiber/api/types.cfg.yaml
+++ b/examples/petstore-expanded/fiber/api/types.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
models: true
diff --git a/examples/petstore-expanded/fiber/petstore.go b/examples/petstore-expanded/fiber/petstore.go
index 7ea71edce..6332ff886 100644
--- a/examples/petstore-expanded/fiber/petstore.go
+++ b/examples/petstore-expanded/fiber/petstore.go
@@ -13,8 +13,8 @@ import (
"github.com/gofiber/fiber/v2"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/fiber/api"
middleware "github.com/oapi-codegen/fiber-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/fiber/api"
)
func main() {
diff --git a/examples/petstore-expanded/fiber/petstore_test.go b/examples/petstore-expanded/fiber/petstore_test.go
index 4de37519c..dac1d58bf 100644
--- a/examples/petstore-expanded/fiber/petstore_test.go
+++ b/examples/petstore-expanded/fiber/petstore_test.go
@@ -12,7 +12,7 @@ import (
"github.com/gofiber/fiber/v2"
"github.com/stretchr/testify/assert"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/fiber/api"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/fiber/api"
)
func doGet(t *testing.T, app *fiber.App, rawURL string) (*http.Response, error) {
diff --git a/examples/petstore-expanded/gin/api/petstore-server.gen.go b/examples/petstore-expanded/gin/api/petstore-server.gen.go
index f048e0066..02499fcc1 100644
--- a/examples/petstore-expanded/gin/api/petstore-server.gen.go
+++ b/examples/petstore-expanded/gin/api/petstore-server.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/examples/petstore-expanded/gin/api/petstore-types.gen.go b/examples/petstore-expanded/gin/api/petstore-types.gen.go
index 3d8ce1134..0e4954f34 100644
--- a/examples/petstore-expanded/gin/api/petstore-types.gen.go
+++ b/examples/petstore-expanded/gin/api/petstore-types.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
// Error defines model for Error.
diff --git a/examples/petstore-expanded/gin/api/petstore.go b/examples/petstore-expanded/gin/api/petstore.go
index 09c37dba4..094b4ef9e 100644
--- a/examples/petstore-expanded/gin/api/petstore.go
+++ b/examples/petstore-expanded/gin/api/petstore.go
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../../petstore-expanded.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../../petstore-expanded.yaml
package api
diff --git a/examples/petstore-expanded/gin/api/server.cfg.yaml b/examples/petstore-expanded/gin/api/server.cfg.yaml
index 61944bcef..fe54882eb 100644
--- a/examples/petstore-expanded/gin/api/server.cfg.yaml
+++ b/examples/petstore-expanded/gin/api/server.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
gin-server: true
diff --git a/examples/petstore-expanded/gin/api/types.cfg.yaml b/examples/petstore-expanded/gin/api/types.cfg.yaml
index 9ac30e11e..cf5128b72 100644
--- a/examples/petstore-expanded/gin/api/types.cfg.yaml
+++ b/examples/petstore-expanded/gin/api/types.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
models: true
diff --git a/examples/petstore-expanded/gin/petstore.go b/examples/petstore-expanded/gin/petstore.go
index 04031e67d..8b0717a4c 100644
--- a/examples/petstore-expanded/gin/petstore.go
+++ b/examples/petstore-expanded/gin/petstore.go
@@ -14,8 +14,8 @@ import (
"github.com/gin-gonic/gin"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/gin/api"
middleware "github.com/oapi-codegen/gin-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/gin/api"
)
func NewGinPetServer(petStore *api.PetStore, port string) *http.Server {
diff --git a/examples/petstore-expanded/gin/petstore_test.go b/examples/petstore-expanded/gin/petstore_test.go
index ad9515443..d7a557d1c 100644
--- a/examples/petstore-expanded/gin/petstore_test.go
+++ b/examples/petstore-expanded/gin/petstore_test.go
@@ -7,7 +7,7 @@ import (
"net/http/httptest"
"testing"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/gin/api"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/gin/api"
"github.com/oapi-codegen/testutil"
"github.com/stretchr/testify/assert"
)
diff --git a/examples/petstore-expanded/gorilla/api/cfg.yaml b/examples/petstore-expanded/gorilla/api/cfg.yaml
index 8ead7a60d..003486995 100644
--- a/examples/petstore-expanded/gorilla/api/cfg.yaml
+++ b/examples/petstore-expanded/gorilla/api/cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
gorilla-server: true
diff --git a/examples/petstore-expanded/gorilla/api/petstore.gen.go b/examples/petstore-expanded/gorilla/api/petstore.gen.go
index 2f65ea25b..78d2178ea 100644
--- a/examples/petstore-expanded/gorilla/api/petstore.gen.go
+++ b/examples/petstore-expanded/gorilla/api/petstore.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/examples/petstore-expanded/gorilla/api/petstore.go b/examples/petstore-expanded/gorilla/api/petstore.go
index 888d16f13..6ede559ec 100644
--- a/examples/petstore-expanded/gorilla/api/petstore.go
+++ b/examples/petstore-expanded/gorilla/api/petstore.go
@@ -1,4 +1,4 @@
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=cfg.yaml ../../petstore-expanded.yaml
package api
diff --git a/examples/petstore-expanded/gorilla/petstore.go b/examples/petstore-expanded/gorilla/petstore.go
index d974efdaa..d1675f1ae 100644
--- a/examples/petstore-expanded/gorilla/petstore.go
+++ b/examples/petstore-expanded/gorilla/petstore.go
@@ -12,9 +12,9 @@ import (
"net/http"
"os"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/gorilla/api"
- middleware "github.com/oapi-codegen/nethttp-middleware"
"github.com/gorilla/mux"
+ middleware "github.com/oapi-codegen/nethttp-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/gorilla/api"
)
func main() {
diff --git a/examples/petstore-expanded/gorilla/petstore_test.go b/examples/petstore-expanded/gorilla/petstore_test.go
index a63dd536a..a6cfedecd 100644
--- a/examples/petstore-expanded/gorilla/petstore_test.go
+++ b/examples/petstore-expanded/gorilla/petstore_test.go
@@ -7,10 +7,10 @@ import (
"net/http/httptest"
"testing"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/gorilla/api"
+ "github.com/gorilla/mux"
middleware "github.com/oapi-codegen/nethttp-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/gorilla/api"
"github.com/oapi-codegen/testutil"
- "github.com/gorilla/mux"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
diff --git a/examples/petstore-expanded/internal/config.yaml b/examples/petstore-expanded/internal/config.yaml
index 067828054..33b649fd8 100644
--- a/examples/petstore-expanded/internal/config.yaml
+++ b/examples/petstore-expanded/internal/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
package: petstore
generate:
client: true
diff --git a/examples/petstore-expanded/internal/doc.go b/examples/petstore-expanded/internal/doc.go
index bfd040503..b04cac3f8 100644
--- a/examples/petstore-expanded/internal/doc.go
+++ b/examples/petstore-expanded/internal/doc.go
@@ -17,4 +17,4 @@ package internal
// server. The file petstore.gen.go is automatically generated from the schema
// Run oapi-codegen to regenerate the petstore boilerplate
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../petstore-expanded.yaml
diff --git a/examples/petstore-expanded/iris/api/petstore-server.gen.go b/examples/petstore-expanded/iris/api/petstore-server.gen.go
index 3abf1dac4..a559c238d 100644
--- a/examples/petstore-expanded/iris/api/petstore-server.gen.go
+++ b/examples/petstore-expanded/iris/api/petstore-server.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/examples/petstore-expanded/iris/api/petstore-types.gen.go b/examples/petstore-expanded/iris/api/petstore-types.gen.go
index 3d8ce1134..0e4954f34 100644
--- a/examples/petstore-expanded/iris/api/petstore-types.gen.go
+++ b/examples/petstore-expanded/iris/api/petstore-types.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
// Error defines model for Error.
diff --git a/examples/petstore-expanded/iris/api/petstore.go b/examples/petstore-expanded/iris/api/petstore.go
index ab6491d3d..d1e801801 100644
--- a/examples/petstore-expanded/iris/api/petstore.go
+++ b/examples/petstore-expanded/iris/api/petstore.go
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../../petstore-expanded.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../../petstore-expanded.yaml
package api
diff --git a/examples/petstore-expanded/iris/api/server.cfg.yaml b/examples/petstore-expanded/iris/api/server.cfg.yaml
index cb44eb33f..f8bb40c5b 100644
--- a/examples/petstore-expanded/iris/api/server.cfg.yaml
+++ b/examples/petstore-expanded/iris/api/server.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
iris-server: true
diff --git a/examples/petstore-expanded/iris/api/types.cfg.yaml b/examples/petstore-expanded/iris/api/types.cfg.yaml
index 9ac30e11e..cf5128b72 100644
--- a/examples/petstore-expanded/iris/api/types.cfg.yaml
+++ b/examples/petstore-expanded/iris/api/types.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
models: true
diff --git a/examples/petstore-expanded/iris/petstore.go b/examples/petstore-expanded/iris/petstore.go
index feebfcc40..2b2dea37f 100644
--- a/examples/petstore-expanded/iris/petstore.go
+++ b/examples/petstore-expanded/iris/petstore.go
@@ -11,9 +11,9 @@ import (
"log"
"os"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/iris/api"
- middleware "github.com/oapi-codegen/iris-middleware"
"github.com/kataras/iris/v12"
+ middleware "github.com/oapi-codegen/iris-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/iris/api"
)
func NewIrisPetServer(petStore *api.PetStore, port int) *iris.Application {
diff --git a/examples/petstore-expanded/iris/petstore_test.go b/examples/petstore-expanded/iris/petstore_test.go
index facb9f222..837a53369 100644
--- a/examples/petstore-expanded/iris/petstore_test.go
+++ b/examples/petstore-expanded/iris/petstore_test.go
@@ -21,7 +21,7 @@ import (
"net/http/httptest"
"testing"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/iris/api"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/iris/api"
"github.com/oapi-codegen/testutil"
"github.com/stretchr/testify/assert"
)
diff --git a/examples/petstore-expanded/petstore-client.gen.go b/examples/petstore-expanded/petstore-client.gen.go
index e97ccf6cd..9bd928f49 100644
--- a/examples/petstore-expanded/petstore-client.gen.go
+++ b/examples/petstore-expanded/petstore-client.gen.go
@@ -1,6 +1,6 @@
// Package petstore provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package petstore
import (
diff --git a/examples/petstore-expanded/stdhttp/Makefile b/examples/petstore-expanded/stdhttp/Makefile
new file mode 100644
index 000000000..66f60e4a2
--- /dev/null
+++ b/examples/petstore-expanded/stdhttp/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 -f2 -d. <<< $(GOVER)")
+
+define execute-if-go-122
+@{ \
+if [[ 22 -le $(GOMINOR) ]]; then \
+ $1; \
+else \
+ echo -e "$(YELLOW)Skipping task as you're running Go v1.$(GOMINOR).x which is < Go 1.22, which this module requires$(RESET)"; \
+fi \
+}
+endef
+
+lint:
+ $(call execute-if-go-122,$(GOBIN)/golangci-lint run ./...)
+
+lint-ci:
+
+ $(call execute-if-go-122,$(GOBIN)/golangci-lint run ./... --out-format=colored-line-number --timeout=5m)
+
+generate:
+ $(call execute-if-go-122,go generate ./...)
+
+test:
+ $(call execute-if-go-122,go test -cover ./...)
+
+tidy:
+ $(call execute-if-go-122,go mod tidy)
+
+tidy-ci:
+ $(call execute-if-go-122,tidied -verbose)
diff --git a/examples/petstore-expanded/stdhttp/api/cfg.yaml b/examples/petstore-expanded/stdhttp/api/cfg.yaml
new file mode 100644
index 000000000..12339c51f
--- /dev/null
+++ b/examples/petstore-expanded/stdhttp/api/cfg.yaml
@@ -0,0 +1,7 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: api
+generate:
+ std-http-server: true
+ embedded-spec: true
+ models: true
+output: petstore.gen.go
diff --git a/examples/petstore-expanded/stdhttp/api/petstore.gen.go b/examples/petstore-expanded/stdhttp/api/petstore.gen.go
new file mode 100644
index 000000000..23dd9d463
--- /dev/null
+++ b/examples/petstore-expanded/stdhttp/api/petstore.gen.go
@@ -0,0 +1,417 @@
+//go:build go1.22
+
+// Package api provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package api
+
+import (
+ "bytes"
+ "compress/gzip"
+ "encoding/base64"
+ "fmt"
+ "net/http"
+ "net/url"
+ "path"
+ "strings"
+
+ "github.com/getkin/kin-openapi/openapi3"
+ "github.com/oapi-codegen/runtime"
+)
+
+// Error defines model for Error.
+type Error struct {
+ // Code Error code
+ Code int32 `json:"code"`
+
+ // Message Error message
+ Message string `json:"message"`
+}
+
+// NewPet defines model for NewPet.
+type NewPet struct {
+ // Name Name of the pet
+ Name string `json:"name"`
+
+ // Tag Type of the pet
+ Tag *string `json:"tag,omitempty"`
+}
+
+// Pet defines model for Pet.
+type Pet struct {
+ // Id Unique id of the pet
+ Id int64 `json:"id"`
+
+ // Name Name of the pet
+ Name string `json:"name"`
+
+ // Tag Type of the pet
+ Tag *string `json:"tag,omitempty"`
+}
+
+// FindPetsParams defines parameters for FindPets.
+type FindPetsParams struct {
+ // Tags tags to filter by
+ Tags *[]string `form:"tags,omitempty" json:"tags,omitempty"`
+
+ // Limit maximum number of results to return
+ Limit *int32 `form:"limit,omitempty" json:"limit,omitempty"`
+}
+
+// AddPetJSONRequestBody defines body for AddPet for application/json ContentType.
+type AddPetJSONRequestBody = NewPet
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+ // Returns all pets
+ // (GET /pets)
+ FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams)
+ // Creates a new pet
+ // (POST /pets)
+ AddPet(w http.ResponseWriter, r *http.Request)
+ // Deletes a pet by ID
+ // (DELETE /pets/{id})
+ DeletePet(w http.ResponseWriter, r *http.Request, id int64)
+ // Returns a pet by ID
+ // (GET /pets/{id})
+ FindPetByID(w http.ResponseWriter, r *http.Request, id int64)
+}
+
+// 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
+
+// FindPets operation middleware
+func (siw *ServerInterfaceWrapper) FindPets(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ var err error
+
+ // Parameter object where we will unmarshal all parameters from the context
+ var params FindPetsParams
+
+ // ------------- Optional query parameter "tags" -------------
+
+ err = runtime.BindQueryParameter("form", true, false, "tags", r.URL.Query(), ¶ms.Tags)
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "tags", 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.FindPets(w, r, params)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// AddPet operation middleware
+func (siw *ServerInterfaceWrapper) AddPet(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.AddPet(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// DeletePet operation middleware
+func (siw *ServerInterfaceWrapper) DeletePet(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ var err error
+
+ // ------------- Path parameter "id" -------------
+ var id int64
+
+ err = runtime.BindStyledParameterWithOptions("simple", "id", r.PathValue("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "id", Err: err})
+ return
+ }
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.DeletePet(w, r, id)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// FindPetByID operation middleware
+func (siw *ServerInterfaceWrapper) FindPetByID(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ var err error
+
+ // ------------- Path parameter "id" -------------
+ var id int64
+
+ err = runtime.BindStyledParameterWithOptions("simple", "id", r.PathValue("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "id", Err: err})
+ return
+ }
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.FindPetByID(w, r, id)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+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{})
+}
+
+type StdHTTPServerOptions struct {
+ BaseURL string
+ BaseRouter *http.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 *http.ServeMux) http.Handler {
+ return HandlerWithOptions(si, StdHTTPServerOptions{
+ BaseRouter: m,
+ })
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, m *http.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+"/pets", wrapper.FindPets)
+ m.HandleFunc("POST "+options.BaseURL+"/pets", wrapper.AddPet)
+ m.HandleFunc("DELETE "+options.BaseURL+"/pets/{id}", wrapper.DeletePet)
+ m.HandleFunc("GET "+options.BaseURL+"/pets/{id}", wrapper.FindPetByID)
+
+ return m
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+ "H4sIAAAAAAAC/+RXW48budH9KwV+32OnNbEXedBTvB4vICBrT+LdvKznoYZdkmrBSw9Z1FgY6L8HRbZu",
+ "I3k2QYIgQV506WY1T51zqlj9bGz0YwwUJJv5s8l2TR7rzw8pxaQ/xhRHSsJUL9s4kH4PlG3iUTgGM2+L",
+ "od7rzDImj2LmhoO8fWM6I9uR2l9aUTK7znjKGVfffND+9iE0S+KwMrtdZxI9Fk40mPkvZtpwv/x+15mP",
+ "9HRHcok7oL+y3Uf0BHEJsiYYSS437Izg6jLup+34etwLoHV3hTdhQ+c+Lc38l2fz/4mWZm7+b3YUYjap",
+ "MJty2XUvk+HhEtLPgR8LAQ/nuE7F+MN3V8R4gZQHc7+73+llDsvYJA+CtuImj+zM3ODIQuj/mJ9wtaLU",
+ "czTdRLH53K7Bu7sF/EToTWdK0qC1yJjns9lJ0K57kcU7yOhHRzVa1ihQMmVAzSZLTASYAQPQ17ZMIgzk",
+ "Y8iSUAiWhFISZeBQOfg0UtAnve1vII9keckW61adcWwpZDqaw7wb0a4J3vQ3F5ifnp56rLf7mFazKTbP",
+ "/rR4/+Hj5w+/e9Pf9GvxrjqGks+flp8pbdjS1cRndc1M5WBxp6zdTXmazmwo5cbK7/ub/kYfHUcKOLKZ",
+ "m7f1UmdGlHX1xEwZ0h+rZrFzXv9CUlLIgM5VKmGZoq8U5W0W8o1r/V8yJVgry9ZSziDxS/iIHjINYGMY",
+ "2FOQ4oGy9PAjkqWAGYT8GBNkXLEIZ8g4MoUOAllI6xhsyZDJnyxgAfQkPbyjQBgABVYJNzwgYFkV6gAt",
+ "MNriuIb28L4kfGApCeLAEVxM5DuIKWAioBUJkKMJXSDbgS0pl6wl4chKyT3cFs7gGaSkkXMHY3EbDph0",
+ "L0pRk+5AOFgeShDYYOKS4deSJfawCLBGC2sFgTkTjA6FEAa2UrzSsWhFpbngwCNny2EFGESzOebueFUc",
+ "HjIf15hIEu5J1PXgo6MsTMB+pDSwMvVX3qBvCaHjx4IeBkZlJmGGR81tQ44FQgwgMUlMSgkvKQyH3Xu4",
+ "S0iZgihMCuyPAEoKCJvoiowosKFAARVwI1c/PJakz1iE45OXlCbWl2jZcT7bpO6gH91RXws5DuhIhR06",
+ "5dFSQtHE9LuHzyWPFAZWlh2qeYboYurUgZmsqJtrltUqmnUHG1qzLQ5BW1saigfHD5RiDz/G9MBAhbOP",
+ "w6kMersa26HlwNh/CV/CZxqqEiXDktR8Lj7EVAMoHh2TiqTie9Da8FgfOJHP2XVA5axamuTgivpQ3dnD",
+ "3RozOdcKY6Q0hVeaq7wksMRi+aE0wnG/j647jd+Qm6TjDaWE3fnWWifAQ3coxMAP6x5+FhjJOQpCWU+O",
+ "MeZCWkn7IupBqcB9FWjR7bncP2mfVmWyq0AOtgglWJDEWerBtGFB6uGHki0BSe0GQ+FDFWinyJYcJa5w",
+ "mn/3AV7dUrCaxxafMYDHlaZMblKrhz+XFuqjU92aelSad45QukPzASxWi6StnOzZ0p7MMTWZQzWqWVRg",
+ "4NAdoUyFGzjzHnBWDJalDKxQc0YosvfZJGTb6Yy0ul8Pd6fCVOYmjGMi4eJPOlczTelO/K2tt/+iZ5wO",
+ "DfW8Wwxmbn7gMOj5Uo+NpARQynUKOT8sBFfa92HJTijBw9boMGDm5rFQ2h5Pel1numlorHOJkK9n0OUU",
+ "1S5gSrjV/1m29djT8aQOOOcIPH5lr228+AdKOtEkysVJhZXqWfYNTI49yxmo3xxHd/c6AuVRW0tF/+bm",
+ "Zj/3UGjz2ji6aXKY/ZoV4vO1tF8b5tok94KI3cUANJLAHkwbj5ZYnPxDeF6D0cb6KxuXQF9Hba3ag9ua",
+ "zuTiPabtlQFCsY0xXxk13idCqTNboCddux/G6lyjZ3DDrkt0nnMuPtFwYdZ3g3rVtOmUsnwfh+2/jIX9",
+ "ZH1Jwx2JegyHQb8OsM3plCyp0O6f9MxvWuW/xxoXgtf7dR6dPfOwaxZxJFdewNp1jc0cVq6+tcADapuN",
+ "zTWLW8hFc7rikdsa3Wzyakdb3GoPGZu2E5apf+gAfWwfPFwo/a1ecv1t6rKXfHeZtQJpKIb/JCFvD2JU",
+ "FbawuFV4r79QnCt20HFx+63j5/ttvff367Ukset/m1z/s2X8QtGmfl1CabOX6fyteP9S3p+82err6e5+",
+ "97cAAAD//ykDnxlaEgAA",
+}
+
+// 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/examples/petstore-expanded/stdhttp/api/petstore.go b/examples/petstore-expanded/stdhttp/api/petstore.go
new file mode 100644
index 000000000..5b9d8606f
--- /dev/null
+++ b/examples/petstore-expanded/stdhttp/api/petstore.go
@@ -0,0 +1,130 @@
+//go:build go1.22
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=cfg.yaml ../../petstore-expanded.yaml
+
+package api
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "sync"
+)
+
+type PetStore struct {
+ Pets map[int64]Pet
+ NextId int64
+ Lock sync.Mutex
+}
+
+// Make sure we conform to ServerInterface
+
+var _ ServerInterface = (*PetStore)(nil)
+
+func NewPetStore() *PetStore {
+ return &PetStore{
+ Pets: make(map[int64]Pet),
+ NextId: 1000,
+ }
+}
+
+// sendPetStoreError wraps sending of an error in the Error format, and
+// handling the failure to marshal that.
+func sendPetStoreError(w http.ResponseWriter, code int, message string) {
+ petErr := Error{
+ Code: int32(code),
+ Message: message,
+ }
+ w.WriteHeader(code)
+ _ = json.NewEncoder(w).Encode(petErr)
+}
+
+// FindPets implements all the handlers in the ServerInterface
+func (p *PetStore) FindPets(w http.ResponseWriter, r *http.Request, params FindPetsParams) {
+ p.Lock.Lock()
+ defer p.Lock.Unlock()
+
+ var result []Pet
+
+ for _, pet := range p.Pets {
+ if params.Tags != nil {
+ // If we have tags, filter pets by tag
+ for _, t := range *params.Tags {
+ if pet.Tag != nil && (*pet.Tag == t) {
+ result = append(result, pet)
+ }
+ }
+ } else {
+ // Add all pets if we're not filtering
+ result = append(result, pet)
+ }
+
+ if params.Limit != nil {
+ l := int(*params.Limit)
+ if len(result) >= l {
+ // We're at the limit
+ break
+ }
+ }
+ }
+
+ w.WriteHeader(http.StatusOK)
+ _ = json.NewEncoder(w).Encode(result)
+}
+
+func (p *PetStore) AddPet(w http.ResponseWriter, r *http.Request) {
+ // We expect a NewPet object in the request body.
+ var newPet NewPet
+ if err := json.NewDecoder(r.Body).Decode(&newPet); err != nil {
+ sendPetStoreError(w, http.StatusBadRequest, "Invalid format for NewPet")
+ return
+ }
+
+ // We now have a pet, let's add it to our "database".
+
+ // We're always asynchronous, so lock unsafe operations below
+ p.Lock.Lock()
+ defer p.Lock.Unlock()
+
+ // We handle pets, not NewPets, which have an additional ID field
+ var pet Pet
+ pet.Name = newPet.Name
+ pet.Tag = newPet.Tag
+ pet.Id = p.NextId
+ p.NextId++
+
+ // Insert into map
+ p.Pets[pet.Id] = pet
+
+ // Now, we have to return the NewPet
+ w.WriteHeader(http.StatusCreated)
+ _ = json.NewEncoder(w).Encode(pet)
+}
+
+func (p *PetStore) FindPetByID(w http.ResponseWriter, r *http.Request, id int64) {
+ p.Lock.Lock()
+ defer p.Lock.Unlock()
+
+ pet, found := p.Pets[id]
+ if !found {
+ sendPetStoreError(w, http.StatusNotFound, fmt.Sprintf("Could not find pet with ID %d", id))
+ return
+ }
+
+ w.WriteHeader(http.StatusOK)
+ _ = json.NewEncoder(w).Encode(pet)
+}
+
+func (p *PetStore) DeletePet(w http.ResponseWriter, r *http.Request, id int64) {
+ p.Lock.Lock()
+ defer p.Lock.Unlock()
+
+ _, found := p.Pets[id]
+ if !found {
+ sendPetStoreError(w, http.StatusNotFound, fmt.Sprintf("Could not find pet with ID %d", id))
+ return
+ }
+ delete(p.Pets, id)
+
+ w.WriteHeader(http.StatusNoContent)
+}
diff --git a/examples/petstore-expanded/stdhttp/go.mod b/examples/petstore-expanded/stdhttp/go.mod
new file mode 100644
index 000000000..a0ff28b6a
--- /dev/null
+++ b/examples/petstore-expanded/stdhttp/go.mod
@@ -0,0 +1,34 @@
+module github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/stdhttp
+
+go 1.22
+
+replace github.com/oapi-codegen/oapi-codegen/v2 => ../../../
+
+require (
+ github.com/getkin/kin-openapi v0.124.0
+ github.com/oapi-codegen/nethttp-middleware v1.0.2
+ github.com/oapi-codegen/oapi-codegen/v2 v2.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.9.0
+)
+
+require (
+ github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/go-openapi/jsonpointer v0.20.2 // indirect
+ github.com/go-openapi/swag v0.22.8 // indirect
+ github.com/google/uuid v1.4.0 // indirect
+ github.com/gorilla/mux v1.8.1 // indirect
+ github.com/invopop/yaml v0.2.0 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
+ github.com/perimeterx/marshmallow v1.1.5 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ golang.org/x/mod v0.17.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/tools v0.21.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
new file mode 100644
index 000000000..c5e5169f4
--- /dev/null
+++ b/examples/petstore-expanded/stdhttp/go.sum
@@ -0,0 +1,67 @@
+github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
+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/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/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M=
+github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
+github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
+github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
+github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
+github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
+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/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
+github.com/google/uuid v1.4.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/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
+github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
+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/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+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/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/oapi-codegen/nethttp-middleware v1.0.2 h1:A5tfAcKJhWIbIPnlQH+l/DtfVE1i5TFgPlQAiW+l1vQ=
+github.com/oapi-codegen/nethttp-middleware v1.0.2/go.mod h1:DfDalonSO+eRQ3RTb8kYoWZByCCPFRxm9WKq1UbY0E4=
+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/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/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/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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
+github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
+golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
+golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/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/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/petstore.go b/examples/petstore-expanded/stdhttp/petstore.go
new file mode 100644
index 000000000..68e45cc1d
--- /dev/null
+++ b/examples/petstore-expanded/stdhttp/petstore.go
@@ -0,0 +1,54 @@
+//go:build go1.22
+
+// This is an example of implementing the Pet Store from the OpenAPI documentation
+// found at:
+// https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/petstore.yaml
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "net"
+ "net/http"
+ "os"
+
+ middleware "github.com/oapi-codegen/nethttp-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/stdhttp/api"
+)
+
+func main() {
+ port := flag.String("port", "8080", "Port for test HTTP server")
+ flag.Parse()
+
+ swagger, err := api.GetSwagger()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
+ os.Exit(1)
+ }
+
+ // Clear out the servers array in the swagger spec, that skips validating
+ // that server names match. We don't know how this thing will be run.
+ swagger.Servers = nil
+
+ // Create an instance of our handler which satisfies the generated interface
+ petStore := api.NewPetStore()
+
+ r := http.NewServeMux()
+
+ // We now register our petStore above as the handler for the interface
+ api.HandlerFromMux(petStore, r)
+
+ // Use our validation middleware to check all requests against the
+ // OpenAPI schema.
+ h := middleware.OapiRequestValidator(swagger)(r)
+
+ s := &http.Server{
+ Handler: h,
+ Addr: net.JoinHostPort("0.0.0.0", *port),
+ }
+
+ // And we serve HTTP until the world ends.
+ log.Fatal(s.ListenAndServe())
+}
diff --git a/examples/petstore-expanded/stdhttp/petstore_test.go b/examples/petstore-expanded/stdhttp/petstore_test.go
new file mode 100644
index 000000000..bf3df022d
--- /dev/null
+++ b/examples/petstore-expanded/stdhttp/petstore_test.go
@@ -0,0 +1,173 @@
+//go:build go1.22
+
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ middleware "github.com/oapi-codegen/nethttp-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/stdhttp/api"
+ "github.com/oapi-codegen/testutil"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func doGet(t *testing.T, mux *http.ServeMux, url string) *httptest.ResponseRecorder {
+ response := testutil.NewRequest().Get(url).WithAcceptJson().GoWithHTTPHandler(t, mux)
+ return response.Recorder
+}
+
+func TestPetStore(t *testing.T) {
+ var err error
+
+ // Get the swagger description of our API
+ swagger, err := api.GetSwagger()
+ require.NoError(t, err)
+
+ // Clear out the servers array in the swagger spec, that skips validating
+ // that server names match. We don't know how this thing will be run.
+ swagger.Servers = nil
+
+ // Create a new ServeMux for testing.
+ m := http.NewServeMux()
+
+ // Use our validation middleware to check all requests against the
+ // OpenAPI schema.
+ opts := api.StdHTTPServerOptions{
+ BaseRouter: m,
+ Middlewares: []api.MiddlewareFunc{
+ middleware.OapiRequestValidator(swagger),
+ },
+ }
+
+ store := api.NewPetStore()
+ api.HandlerWithOptions(store, opts)
+
+ t.Run("Add pet", func(t *testing.T) {
+ tag := "TagOfSpot"
+ newPet := api.NewPet{
+ Name: "Spot",
+ Tag: &tag,
+ }
+
+ rr := testutil.NewRequest().Post("/pets").WithJsonBody(newPet).GoWithHTTPHandler(t, m).Recorder
+ assert.Equal(t, http.StatusCreated, rr.Code)
+
+ var resultPet api.Pet
+ err = json.NewDecoder(rr.Body).Decode(&resultPet)
+ assert.NoError(t, err, "error unmarshaling response")
+ assert.Equal(t, newPet.Name, resultPet.Name)
+ assert.Equal(t, *newPet.Tag, *resultPet.Tag)
+ })
+
+ t.Run("Find pet by ID", func(t *testing.T) {
+ pet := api.Pet{
+ Id: 100,
+ }
+
+ store.Pets[pet.Id] = pet
+ rr := doGet(t, m, fmt.Sprintf("/pets/%d", pet.Id))
+
+ var resultPet api.Pet
+ err = json.NewDecoder(rr.Body).Decode(&resultPet)
+ assert.NoError(t, err, "error getting pet")
+ assert.Equal(t, pet, resultPet)
+ })
+
+ t.Run("Pet not found", func(t *testing.T) {
+ rr := doGet(t, m, "/pets/27179095781")
+ assert.Equal(t, http.StatusNotFound, rr.Code)
+
+ var petError api.Error
+ err = json.NewDecoder(rr.Body).Decode(&petError)
+ assert.NoError(t, err, "error getting response", err)
+ assert.Equal(t, int32(http.StatusNotFound), petError.Code)
+ })
+
+ t.Run("List all pets", func(t *testing.T) {
+ store.Pets = map[int64]api.Pet{
+ 1: {},
+ 2: {},
+ }
+
+ // Now, list all pets, we should have two
+ rr := doGet(t, m, "/pets")
+ assert.Equal(t, http.StatusOK, rr.Code)
+
+ var petList []api.Pet
+ err = json.NewDecoder(rr.Body).Decode(&petList)
+ assert.NoError(t, err, "error getting response", err)
+ assert.Equal(t, 2, len(petList))
+ })
+
+ t.Run("Filter pets by tag", func(t *testing.T) {
+ tag := "TagOfFido"
+
+ store.Pets = map[int64]api.Pet{
+ 1: {
+ Tag: &tag,
+ },
+ 2: {},
+ }
+
+ // Filter pets by tag, we should have 1
+ rr := doGet(t, m, "/pets?tags=TagOfFido")
+ assert.Equal(t, http.StatusOK, rr.Code)
+
+ var petList []api.Pet
+ err = json.NewDecoder(rr.Body).Decode(&petList)
+ assert.NoError(t, err, "error getting response", err)
+ assert.Equal(t, 1, len(petList))
+ })
+
+ t.Run("Filter pets by tag", func(t *testing.T) {
+ store.Pets = map[int64]api.Pet{
+ 1: {},
+ 2: {},
+ }
+
+ // Filter pets by non-existent tag, we should have 0
+ rr := doGet(t, m, "/pets?tags=NotExists")
+ assert.Equal(t, http.StatusOK, rr.Code)
+
+ var petList []api.Pet
+ err = json.NewDecoder(rr.Body).Decode(&petList)
+ assert.NoError(t, err, "error getting response", err)
+ assert.Equal(t, 0, len(petList))
+ })
+
+ t.Run("Delete pets", func(t *testing.T) {
+ store.Pets = map[int64]api.Pet{
+ 1: {},
+ 2: {},
+ }
+
+ // Let's delete non-existent pet
+ rr := testutil.NewRequest().Delete("/pets/7").GoWithHTTPHandler(t, m).Recorder
+ assert.Equal(t, http.StatusNotFound, rr.Code)
+
+ var petError api.Error
+ err = json.NewDecoder(rr.Body).Decode(&petError)
+ assert.NoError(t, err, "error unmarshaling PetError")
+ assert.Equal(t, int32(http.StatusNotFound), petError.Code)
+
+ // Now, delete both real pets
+ rr = testutil.NewRequest().Delete("/pets/1").GoWithHTTPHandler(t, m).Recorder
+ assert.Equal(t, http.StatusNoContent, rr.Code)
+
+ rr = testutil.NewRequest().Delete("/pets/2").GoWithHTTPHandler(t, m).Recorder
+ assert.Equal(t, http.StatusNoContent, rr.Code)
+
+ // Should have no pets left.
+ var petList []api.Pet
+ rr = doGet(t, m, "/pets")
+ assert.Equal(t, http.StatusOK, rr.Code)
+ err = json.NewDecoder(rr.Body).Decode(&petList)
+ assert.NoError(t, err, "error getting response", err)
+ assert.Equal(t, 0, len(petList))
+ })
+}
diff --git a/examples/petstore-expanded/stdhttp/tools/tools.go b/examples/petstore-expanded/stdhttp/tools/tools.go
new file mode 100644
index 000000000..8615cb4c5
--- /dev/null
+++ b/examples/petstore-expanded/stdhttp/tools/tools.go
@@ -0,0 +1,8 @@
+//go:build tools
+// +build tools
+
+package tools
+
+import (
+ _ "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen"
+)
diff --git a/examples/petstore-expanded/strict/api/petstore-server.gen.go b/examples/petstore-expanded/strict/api/petstore-server.gen.go
index 34b58e69f..656f40d90 100644
--- a/examples/petstore-expanded/strict/api/petstore-server.gen.go
+++ b/examples/petstore-expanded/strict/api/petstore-server.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/examples/petstore-expanded/strict/api/petstore-types.gen.go b/examples/petstore-expanded/strict/api/petstore-types.gen.go
index 3d8ce1134..0e4954f34 100644
--- a/examples/petstore-expanded/strict/api/petstore-types.gen.go
+++ b/examples/petstore-expanded/strict/api/petstore-types.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
// Error defines model for Error.
diff --git a/examples/petstore-expanded/strict/api/petstore.go b/examples/petstore-expanded/strict/api/petstore.go
index 96ecc6a03..fc5c9fda2 100644
--- a/examples/petstore-expanded/strict/api/petstore.go
+++ b/examples/petstore-expanded/strict/api/petstore.go
@@ -1,5 +1,5 @@
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../../petstore-expanded.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../../petstore-expanded.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../../petstore-expanded.yaml
package api
diff --git a/examples/petstore-expanded/strict/api/server.cfg.yaml b/examples/petstore-expanded/strict/api/server.cfg.yaml
index f3c71c63f..48d2bf90b 100644
--- a/examples/petstore-expanded/strict/api/server.cfg.yaml
+++ b/examples/petstore-expanded/strict/api/server.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
chi-server: true
diff --git a/examples/petstore-expanded/strict/api/types.cfg.yaml b/examples/petstore-expanded/strict/api/types.cfg.yaml
index 9ac30e11e..cf5128b72 100644
--- a/examples/petstore-expanded/strict/api/types.cfg.yaml
+++ b/examples/petstore-expanded/strict/api/types.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
models: true
diff --git a/examples/petstore-expanded/strict/petstore.go b/examples/petstore-expanded/strict/petstore.go
index f0acac4bf..363caf7e1 100644
--- a/examples/petstore-expanded/strict/petstore.go
+++ b/examples/petstore-expanded/strict/petstore.go
@@ -12,9 +12,9 @@ import (
"net/http"
"os"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/strict/api"
- middleware "github.com/oapi-codegen/nethttp-middleware"
"github.com/go-chi/chi/v5"
+ middleware "github.com/oapi-codegen/nethttp-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/strict/api"
)
func main() {
diff --git a/examples/petstore-expanded/strict/petstore_test.go b/examples/petstore-expanded/strict/petstore_test.go
index 848c32e62..208b65ea3 100644
--- a/examples/petstore-expanded/strict/petstore_test.go
+++ b/examples/petstore-expanded/strict/petstore_test.go
@@ -7,10 +7,10 @@ import (
"net/http/httptest"
"testing"
- "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded/strict/api"
+ "github.com/go-chi/chi/v5"
middleware "github.com/oapi-codegen/nethttp-middleware"
+ "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded/strict/api"
"github.com/oapi-codegen/testutil"
- "github.com/go-chi/chi/v5"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
diff --git a/examples/tools.go b/examples/tools.go
index 67a500f26..8615cb4c5 100644
--- a/examples/tools.go
+++ b/examples/tools.go
@@ -4,5 +4,5 @@
package tools
import (
- _ "github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen"
+ _ "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen"
)
diff --git a/go.mod b/go.mod
index 6791410b4..83705d225 100644
--- a/go.mod
+++ b/go.mod
@@ -1,39 +1,37 @@
-module github.com/deepmap/oapi-codegen/v2
+module github.com/oapi-codegen/oapi-codegen/v2
go 1.21
require (
- github.com/Masterminds/sprig/v3 v3.2.3
- github.com/getkin/kin-openapi v0.122.0
- github.com/stretchr/testify v1.8.4
- golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
- golang.org/x/text v0.14.0
- golang.org/x/tools v0.12.0
+ github.com/Masterminds/sprig/v3 v3.3.0
+ github.com/getkin/kin-openapi v0.124.0
+ github.com/stretchr/testify v1.9.0
+ golang.org/x/text v0.17.0
+ golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d
gopkg.in/yaml.v2 v2.4.0
)
require (
+ dario.cat/mergo v1.0.1 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
- github.com/Masterminds/semver/v3 v3.2.0 // indirect
+ github.com/Masterminds/semver/v3 v3.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
- github.com/go-openapi/jsonpointer v0.19.6 // indirect
- github.com/go-openapi/swag v0.22.4 // indirect
- github.com/google/uuid v1.1.1 // indirect
- github.com/huandu/xstrings v1.3.3 // indirect
- github.com/imdario/mergo v0.3.11 // indirect
+ github.com/go-openapi/jsonpointer v0.20.2 // indirect
+ github.com/go-openapi/swag v0.22.8 // indirect
+ github.com/google/uuid v1.6.0 // indirect
+ github.com/huandu/xstrings v1.5.0 // indirect
github.com/invopop/yaml v0.2.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
- github.com/mitchellh/copystructure v1.0.0 // indirect
- github.com/mitchellh/reflectwalk v1.0.0 // indirect
+ github.com/mitchellh/copystructure v1.2.0 // indirect
+ github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/shopspring/decimal v1.2.0 // indirect
- github.com/spf13/cast v1.3.1 // indirect
+ github.com/shopspring/decimal v1.4.0 // indirect
+ github.com/spf13/cast v1.7.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
- golang.org/x/crypto v0.3.0 // indirect
- golang.org/x/mod v0.12.0 // indirect
- golang.org/x/sys v0.12.0 // indirect
+ golang.org/x/crypto v0.26.0 // indirect
+ golang.org/x/mod v0.17.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index 10d684f20..6cee5e821 100644
--- a/go.sum
+++ b/go.sum
@@ -1,121 +1,74 @@
+dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
+dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
-github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
-github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
-github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
-github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
+github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
+github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
+github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
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/getkin/kin-openapi v0.122.0 h1:WB9Jbl0Hp/T79/JF9xlSW5Kl9uYdk/AWD0yAd9HOM10=
-github.com/getkin/kin-openapi v0.122.0/go.mod h1:PCWw/lfBrJY4HcdqE3jj+QFkaFK8ABoqo7PvqVhXXqw=
-github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
-github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
-github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
-github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
-github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
+github.com/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M=
+github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
+github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
+github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
+github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
+github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
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/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
-github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
-github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
-github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
-github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
+github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
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/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-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/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
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/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
-github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
-github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
-github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
+github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
+github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
+github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
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/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/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
-github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
-github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
-github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
-github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+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/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
+github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
+github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
+github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
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/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
-golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
-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=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/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.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-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-20201119102817-f84b799fce68/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
-golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
-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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-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-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
-golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
-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/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
+golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
+golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
+golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
+golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/yaml.v2 v2.2.2/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-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/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/Makefile b/internal/test/Makefile
new file mode 100644
index 000000000..93a6cdb16
--- /dev/null
+++ b/internal/test/Makefile
@@ -0,0 +1,17 @@
+lint:
+ $(GOBIN)/golangci-lint run ./...
+
+lint-ci:
+ $(GOBIN)/golangci-lint run ./... --out-format=colored-line-number --timeout=5m
+
+generate:
+ go generate ./...
+
+test:
+ go test -cover ./...
+
+tidy:
+ go mod tidy
+
+tidy-ci:
+ tidied -verbose
diff --git a/internal/test/all_of/config1.yaml b/internal/test/all_of/config1.yaml
index 5e023c1f4..1cc8fe87c 100644
--- a/internal/test/all_of/config1.yaml
+++ b/internal/test/all_of/config1.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
package: v1
generate:
models: true
diff --git a/internal/test/all_of/config2.yaml b/internal/test/all_of/config2.yaml
index bd93f3c39..b5b9d64be 100644
--- a/internal/test/all_of/config2.yaml
+++ b/internal/test/all_of/config2.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
package: v2
generate:
models: true
diff --git a/internal/test/all_of/doc.go b/internal/test/all_of/doc.go
index a3284a6c1..b154cb224 100644
--- a/internal/test/all_of/doc.go
+++ b/internal/test/all_of/doc.go
@@ -1,4 +1,4 @@
package allof
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config1.yaml openapi.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config2.yaml openapi.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config1.yaml openapi.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config2.yaml openapi.yaml
diff --git a/internal/test/all_of/v1/openapi.gen.go b/internal/test/all_of/v1/openapi.gen.go
index 0b65e403f..db5fd302c 100644
--- a/internal/test/all_of/v1/openapi.gen.go
+++ b/internal/test/all_of/v1/openapi.gen.go
@@ -1,6 +1,6 @@
// Package v1 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package v1
import (
diff --git a/internal/test/all_of/v2/openapi.gen.go b/internal/test/all_of/v2/openapi.gen.go
index f00a14f89..ab430340d 100644
--- a/internal/test/all_of/v2/openapi.gen.go
+++ b/internal/test/all_of/v2/openapi.gen.go
@@ -1,6 +1,6 @@
// Package v2 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package v2
import (
diff --git a/internal/test/any_of/param/config.yaml b/internal/test/any_of/param/config.yaml
index 7b2827042..1e35ec88b 100644
--- a/internal/test/any_of/param/config.yaml
+++ b/internal/test/any_of/param/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: param
generate:
models: true
diff --git a/internal/test/any_of/param/doc.go b/internal/test/any_of/param/doc.go
index 71113bd57..657385e03 100644
--- a/internal/test/any_of/param/doc.go
+++ b/internal/test/any_of/param/doc.go
@@ -1,3 +1,3 @@
package param
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/any_of/param/param.gen.go b/internal/test/any_of/param/param.gen.go
index 1d6b42212..3378ae3da 100644
--- a/internal/test/any_of/param/param.gen.go
+++ b/internal/test/any_of/param/param.gen.go
@@ -1,6 +1,6 @@
// Package param provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package param
import (
diff --git a/internal/test/any_of/param/param_test.go b/internal/test/any_of/param/param_test.go
index 9ae6edd13..94641b365 100644
--- a/internal/test/any_of/param/param_test.go
+++ b/internal/test/any_of/param/param_test.go
@@ -3,7 +3,7 @@ package param_test
import (
"testing"
- "github.com/deepmap/oapi-codegen/v2/internal/test/any_of/param"
+ "github.com/oapi-codegen/oapi-codegen/v2/internal/test/any_of/param"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
diff --git a/internal/test/client/client.gen.go b/internal/test/client/client.gen.go
index 64c0ca227..275c72cf0 100644
--- a/internal/test/client/client.gen.go
+++ b/internal/test/client/client.gen.go
@@ -1,6 +1,6 @@
// Package client provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package client
import (
diff --git a/internal/test/client/client_test.go b/internal/test/client/client_test.go
index dd08ae2fb..ef7c5df16 100644
--- a/internal/test/client/client_test.go
+++ b/internal/test/client/client_test.go
@@ -3,7 +3,7 @@ package client
import (
"testing"
- "github.com/deepmap/oapi-codegen/v2/pkg/securityprovider"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/securityprovider"
"github.com/stretchr/testify/assert"
)
diff --git a/internal/test/client/doc.go b/internal/test/client/doc.go
index a97d93a6b..930039dad 100644
--- a/internal/test/client/doc.go
+++ b/internal/test/client/doc.go
@@ -1,3 +1,3 @@
package client
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --package=client --generate=client,types -o client.gen.go client.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --package=client --generate=client,types -o client.gen.go client.yaml
diff --git a/internal/test/components/components.gen.go b/internal/test/components/components.gen.go
index be856de10..95257707b 100644
--- a/internal/test/components/components.gen.go
+++ b/internal/test/components/components.gen.go
@@ -1,6 +1,6 @@
// Package components provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package components
import (
@@ -329,7 +329,7 @@ type OneOfVariant6 struct {
// ReferenceToRenameMe When a Schema is renamed, $ref should refer to the new name
type ReferenceToRenameMe struct {
- // ToNewName This schema should be renamed via x-go-name when generating
+ // NewName This schema should be renamed via x-go-name when generating
NewName NewName `json:"ToNewName"`
}
diff --git a/internal/test/components/config.yaml b/internal/test/components/config.yaml
index 1250e0f66..185203a50 100644
--- a/internal/test/components/config.yaml
+++ b/internal/test/components/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
package: components
generate:
models: true
diff --git a/internal/test/components/doc.go b/internal/test/components/doc.go
index 7d5021bcc..64f995a9c 100644
--- a/internal/test/components/doc.go
+++ b/internal/test/components/doc.go
@@ -1,3 +1,3 @@
package components
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml components.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml components.yaml
diff --git a/internal/test/extensions/x-order/config.yaml b/internal/test/extensions/x-order/config.yaml
index d5db754a1..357489f37 100644
--- a/internal/test/extensions/x-order/config.yaml
+++ b/internal/test/extensions/x-order/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: xorder
generate:
models: true
diff --git a/internal/test/extensions/x-order/generate.go b/internal/test/extensions/x-order/generate.go
index d49bb7970..8970f968a 100644
--- a/internal/test/extensions/x-order/generate.go
+++ b/internal/test/extensions/x-order/generate.go
@@ -1,3 +1,3 @@
package xorder
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/extensions/x-order/issue.gen.go b/internal/test/extensions/x-order/issue.gen.go
index 6934cea8f..9dda2d072 100644
--- a/internal/test/extensions/x-order/issue.gen.go
+++ b/internal/test/extensions/x-order/issue.gen.go
@@ -1,6 +1,6 @@
// Package xorder provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package xorder
import (
diff --git a/internal/test/externalref/doc.go b/internal/test/externalref/doc.go
index 805be737a..c5aeaa522 100644
--- a/internal/test/externalref/doc.go
+++ b/internal/test/externalref/doc.go
@@ -1,3 +1,3 @@
package externalref
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=externalref.cfg.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=externalref.cfg.yaml spec.yaml
diff --git a/internal/test/externalref/externalref.cfg.yaml b/internal/test/externalref/externalref.cfg.yaml
index d19e6dd13..22a76c3ff 100644
--- a/internal/test/externalref/externalref.cfg.yaml
+++ b/internal/test/externalref/externalref.cfg.yaml
@@ -1,11 +1,12 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
package: externalref
generate:
models: true
embedded-spec: true
import-mapping:
- ./packageA/spec.yaml: github.com/deepmap/oapi-codegen/v2/internal/test/externalref/packageA
- ./packageB/spec.yaml: github.com/deepmap/oapi-codegen/v2/internal/test/externalref/packageB
- https://petstore3.swagger.io/api/v3/openapi.json: github.com/deepmap/oapi-codegen/v2/internal/test/externalref/petstore
+ ./packageA/spec.yaml: github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/packageA
+ ./packageB/spec.yaml: github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/packageB
+ https://petstore3.swagger.io/api/v3/openapi.json: github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/petstore
output: externalref.gen.go
output-options:
skip-prune: true
diff --git a/internal/test/externalref/externalref.gen.go b/internal/test/externalref/externalref.gen.go
index 3f132b055..d21bb6813 100644
--- a/internal/test/externalref/externalref.gen.go
+++ b/internal/test/externalref/externalref.gen.go
@@ -1,6 +1,6 @@
// Package externalref provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package externalref
import (
@@ -12,10 +12,10 @@ import (
"path"
"strings"
- externalRef0 "github.com/deepmap/oapi-codegen/v2/internal/test/externalref/packageA"
- externalRef1 "github.com/deepmap/oapi-codegen/v2/internal/test/externalref/packageB"
- externalRef2 "github.com/deepmap/oapi-codegen/v2/internal/test/externalref/petstore"
"github.com/getkin/kin-openapi/openapi3"
+ externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/packageA"
+ externalRef1 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/packageB"
+ externalRef2 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/petstore"
)
// Container defines model for Container.
diff --git a/internal/test/externalref/imports_test.go b/internal/test/externalref/imports_test.go
index c491edc25..34fd0ec11 100644
--- a/internal/test/externalref/imports_test.go
+++ b/internal/test/externalref/imports_test.go
@@ -3,9 +3,9 @@ package externalref
import (
"testing"
- packageA "github.com/deepmap/oapi-codegen/v2/internal/test/externalref/packageA"
- packageB "github.com/deepmap/oapi-codegen/v2/internal/test/externalref/packageB"
- petstore "github.com/deepmap/oapi-codegen/v2/internal/test/externalref/petstore"
+ packageA "github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/packageA"
+ packageB "github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/packageB"
+ petstore "github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/petstore"
"github.com/stretchr/testify/require"
)
diff --git a/internal/test/externalref/packageA/config.yaml b/internal/test/externalref/packageA/config.yaml
index fbff1a676..6ee1a1369 100644
--- a/internal/test/externalref/packageA/config.yaml
+++ b/internal/test/externalref/packageA/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: packagea
generate:
models: true
@@ -5,5 +6,5 @@ generate:
output-options:
skip-prune: true
import-mapping:
- ../packageB/spec.yaml: github.com/deepmap/oapi-codegen/v2/internal/test/externalref/packageB
+ ../packageB/spec.yaml: github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/packageB
output: externalref.gen.go
diff --git a/internal/test/externalref/packageA/doc.go b/internal/test/externalref/packageA/doc.go
index 6d11f4bcf..f05471ffb 100644
--- a/internal/test/externalref/packageA/doc.go
+++ b/internal/test/externalref/packageA/doc.go
@@ -1,3 +1,3 @@
package packagea
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/externalref/packageA/externalref.gen.go b/internal/test/externalref/packageA/externalref.gen.go
index 6f569bfa2..d925df21e 100644
--- a/internal/test/externalref/packageA/externalref.gen.go
+++ b/internal/test/externalref/packageA/externalref.gen.go
@@ -1,6 +1,6 @@
// Package packagea provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package packagea
import (
@@ -12,8 +12,8 @@ import (
"path"
"strings"
- externalRef0 "github.com/deepmap/oapi-codegen/v2/internal/test/externalref/packageB"
"github.com/getkin/kin-openapi/openapi3"
+ externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/packageB"
)
// ObjectA defines model for ObjectA.
diff --git a/internal/test/externalref/packageB/config.yaml b/internal/test/externalref/packageB/config.yaml
index 748a18858..3dc9b7ce7 100644
--- a/internal/test/externalref/packageB/config.yaml
+++ b/internal/test/externalref/packageB/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: packageb
generate:
models: true
diff --git a/internal/test/externalref/packageB/doc.go b/internal/test/externalref/packageB/doc.go
index 2aba2cdfb..0dc18f825 100644
--- a/internal/test/externalref/packageB/doc.go
+++ b/internal/test/externalref/packageB/doc.go
@@ -1,3 +1,3 @@
package packageb
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/externalref/packageB/externalref.gen.go b/internal/test/externalref/packageB/externalref.gen.go
index e81242edc..c3f879cfd 100644
--- a/internal/test/externalref/packageB/externalref.gen.go
+++ b/internal/test/externalref/packageB/externalref.gen.go
@@ -1,6 +1,6 @@
// Package packageb provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package packageb
import (
diff --git a/internal/test/externalref/petstore/config.yaml b/internal/test/externalref/petstore/config.yaml
index fbff1a676..6ee1a1369 100644
--- a/internal/test/externalref/petstore/config.yaml
+++ b/internal/test/externalref/petstore/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: packagea
generate:
models: true
@@ -5,5 +6,5 @@ generate:
output-options:
skip-prune: true
import-mapping:
- ../packageB/spec.yaml: github.com/deepmap/oapi-codegen/v2/internal/test/externalref/packageB
+ ../packageB/spec.yaml: github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/packageB
output: externalref.gen.go
diff --git a/internal/test/externalref/petstore/doc.go b/internal/test/externalref/petstore/doc.go
index 6d11f4bcf..f05471ffb 100644
--- a/internal/test/externalref/petstore/doc.go
+++ b/internal/test/externalref/petstore/doc.go
@@ -1,3 +1,3 @@
package packagea
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/externalref/petstore/externalref.gen.go b/internal/test/externalref/petstore/externalref.gen.go
index 24b2cedb3..c1d5d3e10 100644
--- a/internal/test/externalref/petstore/externalref.gen.go
+++ b/internal/test/externalref/petstore/externalref.gen.go
@@ -1,6 +1,6 @@
// Package packagea provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package packagea
import (
@@ -13,8 +13,8 @@ import (
"strings"
"time"
- externalRef0 "github.com/deepmap/oapi-codegen/v2/internal/test/externalref/packageB"
"github.com/getkin/kin-openapi/openapi3"
+ externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/externalref/packageB"
)
const (
diff --git a/internal/test/filter/doc.go b/internal/test/filter/doc.go
index 9b33988d8..a9051b101 100644
--- a/internal/test/filter/doc.go
+++ b/internal/test/filter/doc.go
@@ -1,4 +1,4 @@
package client
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --package=filtertags --generate=server -o tags/server.gen.go -include-tags included-tag1,included-tag2 server.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --package=filteroperations --generate=server -o operations/server.gen.go -include-operation-ids included-operation1,included-operation2 server.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --package=filtertags --generate=server -o tags/server.gen.go -include-tags included-tag1,included-tag2 server.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --package=filteroperations --generate=server -o operations/server.gen.go -include-operation-ids included-operation1,included-operation2 server.yaml
diff --git a/internal/test/filter/operations/server.gen.go b/internal/test/filter/operations/server.gen.go
index a4db89e6d..49fc69b5e 100644
--- a/internal/test/filter/operations/server.gen.go
+++ b/internal/test/filter/operations/server.gen.go
@@ -1,6 +1,6 @@
// Package filteroperations provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package filteroperations
import (
diff --git a/internal/test/filter/tags/server.gen.go b/internal/test/filter/tags/server.gen.go
index f7c993aaf..8137c0f39 100644
--- a/internal/test/filter/tags/server.gen.go
+++ b/internal/test/filter/tags/server.gen.go
@@ -1,6 +1,6 @@
// Package filtertags provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package filtertags
import (
diff --git a/internal/test/go.mod b/internal/test/go.mod
index 5f6928e48..f6a61a742 100644
--- a/internal/test/go.mod
+++ b/internal/test/go.mod
@@ -1,22 +1,22 @@
-module github.com/deepmap/oapi-codegen/v2/internal/test
+module github.com/oapi-codegen/oapi-codegen/v2/internal/test
go 1.20
-replace github.com/deepmap/oapi-codegen/v2 => ../../
+replace github.com/oapi-codegen/oapi-codegen/v2 => ../../
require (
- github.com/deepmap/oapi-codegen/v2 v2.0.0-00010101000000-000000000000
- github.com/getkin/kin-openapi v0.122.0
+ github.com/getkin/kin-openapi v0.124.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/gorilla/mux v1.8.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.11.3
github.com/oapi-codegen/nullable v1.0.1
+ github.com/oapi-codegen/oapi-codegen/v2 v2.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.8.4
+ github.com/stretchr/testify v1.9.0
gopkg.in/yaml.v2 v2.4.0
)
@@ -37,8 +37,8 @@ require (
github.com/flosch/pongo2/v4 v4.0.2 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
- github.com/go-openapi/jsonpointer v0.20.0 // indirect
- github.com/go-openapi/swag v0.22.4 // indirect
+ github.com/go-openapi/jsonpointer v0.20.2 // indirect
+ github.com/go-openapi/swag v0.22.8 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.1 // indirect
@@ -74,11 +74,10 @@ require (
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/rogpeppe/go-internal v1.11.0 // 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
- github.com/stretchr/objx v0.5.0 // indirect
+ github.com/stretchr/objx v0.5.2 // indirect
github.com/tdewolff/minify/v2 v2.12.9 // indirect
github.com/tdewolff/parse/v2 v2.6.8 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
@@ -91,13 +90,13 @@ require (
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/yosssi/ace v0.0.5 // indirect
golang.org/x/arch v0.4.0 // indirect
- golang.org/x/crypto v0.14.0 // indirect
- golang.org/x/mod v0.12.0 // indirect
- golang.org/x/net v0.17.0 // indirect
- golang.org/x/sys v0.13.0 // indirect
- golang.org/x/text v0.14.0 // indirect
+ golang.org/x/crypto v0.23.0 // indirect
+ golang.org/x/mod v0.17.0 // indirect
+ golang.org/x/net v0.25.0 // indirect
+ golang.org/x/sys v0.20.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
golang.org/x/time v0.3.0 // indirect
- golang.org/x/tools v0.12.0 // indirect
+ golang.org/x/tools v0.21.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 382b67a04..26a8d593c 100644
--- a/internal/test/go.sum
+++ b/internal/test/go.sum
@@ -39,18 +39,18 @@ github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0H
github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
-github.com/getkin/kin-openapi v0.122.0 h1:WB9Jbl0Hp/T79/JF9xlSW5Kl9uYdk/AWD0yAd9HOM10=
-github.com/getkin/kin-openapi v0.122.0/go.mod h1:PCWw/lfBrJY4HcdqE3jj+QFkaFK8ABoqo7PvqVhXXqw=
+github.com/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M=
+github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
-github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
-github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
-github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
-github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
+github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
+github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
+github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
@@ -71,16 +71,16 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomarkdown/markdown v0.0.0-20230716120725-531d2d74bc12 h1:uK3X/2mt4tbSGoHvbLBHUny7CKiuwUip3MArtukol4E=
github.com/gomarkdown/markdown v0.0.0-20230716120725-531d2d74bc12/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
-github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
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-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
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=
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.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
-github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
+github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
@@ -160,8 +160,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
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.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
-github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
@@ -173,8 +172,9 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -183,8 +183,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tdewolff/minify/v2 v2.12.9 h1:dvn5MtmuQ/DFMwqf5j8QhEVpPX6fi3WGImhv8RUB4zA=
github.com/tdewolff/minify/v2 v2.12.9/go.mod h1:qOqdlDfL+7v0/fyymB+OP497nIxJYSvX4MQWA8OoiXU=
github.com/tdewolff/parse/v2 v2.6.8 h1:mhNZXYCx//xG7Yq2e/kVLNZw4YfYmeHbhx+Zc0OvFMA=
@@ -222,20 +223,20 @@ golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc=
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.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
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=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
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-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -248,26 +249,25 @@ golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/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.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
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.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
-golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
-golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
+golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
+golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
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=
-golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
diff --git a/internal/test/issues/issue-1039/client-config.yaml b/internal/test/issues/issue-1039/client-config.yaml
index b2039a310..a117c7c74 100644
--- a/internal/test/issues/issue-1039/client-config.yaml
+++ b/internal/test/issues/issue-1039/client-config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue1039
generate:
client: true
diff --git a/internal/test/issues/issue-1039/client.gen.go b/internal/test/issues/issue-1039/client.gen.go
index cf576c717..3114f2986 100644
--- a/internal/test/issues/issue-1039/client.gen.go
+++ b/internal/test/issues/issue-1039/client.gen.go
@@ -1,6 +1,6 @@
// Package issue1039 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue1039
import (
diff --git a/internal/test/issues/issue-1039/defaultbehaviour/types.gen.go b/internal/test/issues/issue-1039/defaultbehaviour/types.gen.go
index e16b43613..b148f3783 100644
--- a/internal/test/issues/issue-1039/defaultbehaviour/types.gen.go
+++ b/internal/test/issues/issue-1039/defaultbehaviour/types.gen.go
@@ -1,6 +1,6 @@
// Package defaultbehaviour provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package defaultbehaviour
// PatchRequest A request to patch an existing user object.
diff --git a/internal/test/issues/issue-1039/doc.go b/internal/test/issues/issue-1039/doc.go
index 4cb14c3fa..2997380aa 100644
--- a/internal/test/issues/issue-1039/doc.go
+++ b/internal/test/issues/issue-1039/doc.go
@@ -1,6 +1,6 @@
package issue1039
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=types-config.yaml spec.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=type-config-defaultbehaviour.yaml spec.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=client-config.yaml spec.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server-config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=types-config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=type-config-defaultbehaviour.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=client-config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server-config.yaml spec.yaml
diff --git a/internal/test/issues/issue-1039/server-config.yaml b/internal/test/issues/issue-1039/server-config.yaml
index ce837b254..e1e787993 100644
--- a/internal/test/issues/issue-1039/server-config.yaml
+++ b/internal/test/issues/issue-1039/server-config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue1039
generate:
chi-server: true
diff --git a/internal/test/issues/issue-1039/server.gen.go b/internal/test/issues/issue-1039/server.gen.go
index 578c353fe..ac0e22b78 100644
--- a/internal/test/issues/issue-1039/server.gen.go
+++ b/internal/test/issues/issue-1039/server.gen.go
@@ -1,6 +1,6 @@
// Package issue1039 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue1039
import (
diff --git a/internal/test/issues/issue-1039/type-config-defaultbehaviour.yaml b/internal/test/issues/issue-1039/type-config-defaultbehaviour.yaml
index 6b84312fd..2b0767908 100644
--- a/internal/test/issues/issue-1039/type-config-defaultbehaviour.yaml
+++ b/internal/test/issues/issue-1039/type-config-defaultbehaviour.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: defaultbehaviour
generate:
models: true
diff --git a/internal/test/issues/issue-1039/types-config.yaml b/internal/test/issues/issue-1039/types-config.yaml
index 556fc40cf..9f97d8bc6 100644
--- a/internal/test/issues/issue-1039/types-config.yaml
+++ b/internal/test/issues/issue-1039/types-config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue1039
generate:
models: true
diff --git a/internal/test/issues/issue-1039/types.gen.go b/internal/test/issues/issue-1039/types.gen.go
index e7665c4cf..9c1191534 100644
--- a/internal/test/issues/issue-1039/types.gen.go
+++ b/internal/test/issues/issue-1039/types.gen.go
@@ -1,9 +1,11 @@
// Package issue1039 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue1039
-import "github.com/oapi-codegen/nullable"
+import (
+ "github.com/oapi-codegen/nullable"
+)
// PatchRequest A request to patch an existing user object.
type PatchRequest struct {
diff --git a/internal/test/issues/issue-1087/api.gen.go b/internal/test/issues/issue-1087/api.gen.go
index 78810652f..99d00fd32 100644
--- a/internal/test/issues/issue-1087/api.gen.go
+++ b/internal/test/issues/issue-1087/api.gen.go
@@ -1,6 +1,6 @@
// Package issue1087 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue1087
import (
@@ -12,8 +12,8 @@ import (
"net/url"
"strings"
- externalRef0 "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1087/deps"
"github.com/go-chi/chi/v5"
+ externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1087/deps"
)
// Thing defines model for Thing.
diff --git a/internal/test/issues/issue-1087/deps/config.yaml b/internal/test/issues/issue-1087/deps/config.yaml
index 01ee1951a..95c23f63e 100644
--- a/internal/test/issues/issue-1087/deps/config.yaml
+++ b/internal/test/issues/issue-1087/deps/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../../configuration-schema.json
package: deps
output:
deps.gen.go
@@ -5,4 +6,4 @@ output-options:
skip-prune: true
generate:
models: true
- embedded-spec: true
\ No newline at end of file
+ embedded-spec: true
diff --git a/internal/test/issues/issue-1087/deps/deps.gen.go b/internal/test/issues/issue-1087/deps/deps.gen.go
index 91289e99a..8066ab2b5 100644
--- a/internal/test/issues/issue-1087/deps/deps.gen.go
+++ b/internal/test/issues/issue-1087/deps/deps.gen.go
@@ -1,6 +1,6 @@
// Package deps provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package deps
import (
diff --git a/internal/test/issues/issue-1087/deps/doc.go b/internal/test/issues/issue-1087/deps/doc.go
index e03a36546..0684d56ca 100644
--- a/internal/test/issues/issue-1087/deps/doc.go
+++ b/internal/test/issues/issue-1087/deps/doc.go
@@ -1,3 +1,3 @@
package deps
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml my-deps.json
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml my-deps.json
diff --git a/internal/test/issues/issue-1087/doc.go b/internal/test/issues/issue-1087/doc.go
index 324ca0971..2ad8db520 100644
--- a/internal/test/issues/issue-1087/doc.go
+++ b/internal/test/issues/issue-1087/doc.go
@@ -1,3 +1,3 @@
package issue1087
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.config.yaml spec.yaml
diff --git a/internal/test/issues/issue-1087/server.config.yaml b/internal/test/issues/issue-1087/server.config.yaml
index cfab0d7e7..6d795c05d 100644
--- a/internal/test/issues/issue-1087/server.config.yaml
+++ b/internal/test/issues/issue-1087/server.config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue1087
output:
api.gen.go
@@ -7,4 +8,4 @@ generate:
embedded-spec: false
client: true
import-mapping:
- ./deps/my-deps.json: github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1087/deps
+ ./deps/my-deps.json: github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1087/deps
diff --git a/internal/test/issues/issue-1093/api/child/child.gen.go b/internal/test/issues/issue-1093/api/child/child.gen.go
index 5de595a8a..a18d256df 100644
--- a/internal/test/issues/issue-1093/api/child/child.gen.go
+++ b/internal/test/issues/issue-1093/api/child/child.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
@@ -15,9 +15,9 @@ import (
"path"
"strings"
- externalRef0 "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1093/api/parent"
"github.com/getkin/kin-openapi/openapi3"
"github.com/gin-gonic/gin"
+ externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1093/api/parent"
strictgin "github.com/oapi-codegen/runtime/strictmiddleware/gin"
)
diff --git a/internal/test/issues/issue-1093/api/parent/parent.gen.go b/internal/test/issues/issue-1093/api/parent/parent.gen.go
index e59030372..916772b07 100644
--- a/internal/test/issues/issue-1093/api/parent/parent.gen.go
+++ b/internal/test/issues/issue-1093/api/parent/parent.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/internal/test/issues/issue-1093/child.cfg.yaml b/internal/test/issues/issue-1093/child.cfg.yaml
index 8c28d430e..4efb750c1 100644
--- a/internal/test/issues/issue-1093/child.cfg.yaml
+++ b/internal/test/issues/issue-1093/child.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
# child.yaml
package: api
generate:
@@ -6,5 +7,5 @@ generate:
strict-server: true
models: true
import-mapping:
- parent.api.yaml: github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1093/api/parent
-output: api/child/child.gen.go
\ No newline at end of file
+ parent.api.yaml: github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1093/api/parent
+output: api/child/child.gen.go
diff --git a/internal/test/issues/issue-1093/doc.go b/internal/test/issues/issue-1093/doc.go
index 0487fc8d3..7916b330b 100644
--- a/internal/test/issues/issue-1093/doc.go
+++ b/internal/test/issues/issue-1093/doc.go
@@ -2,5 +2,5 @@
// See https://github.com/deepmap/oapi-codegen/issues/1093
package issue1093
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config parent.cfg.yaml parent.api.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config child.cfg.yaml child.api.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config parent.cfg.yaml parent.api.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config child.cfg.yaml child.api.yaml
diff --git a/internal/test/issues/issue-1093/issue_test.go b/internal/test/issues/issue-1093/issue_test.go
index db7234477..990de8538 100644
--- a/internal/test/issues/issue-1093/issue_test.go
+++ b/internal/test/issues/issue-1093/issue_test.go
@@ -7,7 +7,7 @@ import (
"github.com/getkin/kin-openapi/openapi3"
"github.com/stretchr/testify/require"
- "github.com/deepmap/oapi-codegen/v2/pkg/codegen"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen"
)
//go:embed child.api.yaml
@@ -29,7 +29,7 @@ func TestIssue(t *testing.T) {
EmbeddedSpec: true,
},
ImportMapping: map[string]string{
- "parent.api.yaml": "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1093/api/parent",
+ "parent.api.yaml": "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1093/api/parent",
},
}
diff --git a/internal/test/issues/issue-1093/parent.cfg.yaml b/internal/test/issues/issue-1093/parent.cfg.yaml
index 306f456cc..ef00a99d6 100644
--- a/internal/test/issues/issue-1093/parent.cfg.yaml
+++ b/internal/test/issues/issue-1093/parent.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
gin-server: true
@@ -6,4 +7,4 @@ generate:
models: true
output: api/parent/parent.gen.go
output-options:
- skip-prune: true
\ No newline at end of file
+ skip-prune: true
diff --git a/internal/test/issues/issue-1127/api.gen.go b/internal/test/issues/issue-1127/api.gen.go
index 02e87ebc3..d3fa8e429 100644
--- a/internal/test/issues/issue-1127/api.gen.go
+++ b/internal/test/issues/issue-1127/api.gen.go
@@ -1,6 +1,6 @@
// Package issue1127 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue1127
// Whatever defines model for Whatever.
diff --git a/internal/test/issues/issue-1127/doc.go b/internal/test/issues/issue-1127/doc.go
index 9f60b28de..d591e52f8 100644
--- a/internal/test/issues/issue-1127/doc.go
+++ b/internal/test/issues/issue-1127/doc.go
@@ -1,3 +1,3 @@
package issue1127
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.config.yaml spec.yaml
diff --git a/internal/test/issues/issue-1127/server.config.yaml b/internal/test/issues/issue-1127/server.config.yaml
index 86e0e1e42..fd6b9de19 100644
--- a/internal/test/issues/issue-1127/server.config.yaml
+++ b/internal/test/issues/issue-1127/server.config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue1127
output:
api.gen.go
diff --git a/internal/test/issues/issue-1168/api.gen.go b/internal/test/issues/issue-1168/api.gen.go
index 1f44dc4b3..d681fbd81 100644
--- a/internal/test/issues/issue-1168/api.gen.go
+++ b/internal/test/issues/issue-1168/api.gen.go
@@ -1,6 +1,6 @@
// Package issue1168 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue1168
import (
diff --git a/internal/test/issues/issue-1168/doc.go b/internal/test/issues/issue-1168/doc.go
index 3d2039729..2541e721d 100644
--- a/internal/test/issues/issue-1168/doc.go
+++ b/internal/test/issues/issue-1168/doc.go
@@ -1,3 +1,3 @@
package issue1168
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.config.yaml spec.yaml
diff --git a/internal/test/issues/issue-1168/server.config.yaml b/internal/test/issues/issue-1168/server.config.yaml
index 7d70ed842..ff204a7c2 100644
--- a/internal/test/issues/issue-1168/server.config.yaml
+++ b/internal/test/issues/issue-1168/server.config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue1168
output:
api.gen.go
diff --git a/internal/test/issues/issue-1180/config.yaml b/internal/test/issues/issue-1180/config.yaml
index 307b8e33b..f8f01372f 100644
--- a/internal/test/issues/issue-1180/config.yaml
+++ b/internal/test/issues/issue-1180/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue1180
generate:
echo-server: true
diff --git a/internal/test/issues/issue-1180/doc.go b/internal/test/issues/issue-1180/doc.go
index 5b4cdf7de..5fcca2b96 100644
--- a/internal/test/issues/issue-1180/doc.go
+++ b/internal/test/issues/issue-1180/doc.go
@@ -1,3 +1,3 @@
package issue1180
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml issue.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml issue.yaml
diff --git a/internal/test/issues/issue-1180/issue.gen.go b/internal/test/issues/issue-1180/issue.gen.go
index 1b3399abf..cc675b96d 100644
--- a/internal/test/issues/issue-1180/issue.gen.go
+++ b/internal/test/issues/issue-1180/issue.gen.go
@@ -1,6 +1,6 @@
// Package issue1180 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue1180
import (
diff --git a/internal/test/issues/issue-1182/pkg1/config.yaml b/internal/test/issues/issue-1182/pkg1/config.yaml
index a1e9af4fe..a300242fb 100644
--- a/internal/test/issues/issue-1182/pkg1/config.yaml
+++ b/internal/test/issues/issue-1182/pkg1/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../../configuration-schema.json
package: pkg1
generate:
echo-server: true
@@ -7,4 +8,4 @@ generate:
strict-server: true
output: pkg1.gen.go
import-mapping:
- pkg2.yaml: github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1182/pkg2
+ pkg2.yaml: github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1182/pkg2
diff --git a/internal/test/issues/issue-1182/pkg1/doc.go b/internal/test/issues/issue-1182/pkg1/doc.go
index 060f76260..8b57f0836 100644
--- a/internal/test/issues/issue-1182/pkg1/doc.go
+++ b/internal/test/issues/issue-1182/pkg1/doc.go
@@ -1,3 +1,3 @@
package pkg1
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../pkg1.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../pkg1.yaml
diff --git a/internal/test/issues/issue-1182/pkg1/pkg1.gen.go b/internal/test/issues/issue-1182/pkg1/pkg1.gen.go
index ce8632bd7..1f278d359 100644
--- a/internal/test/issues/issue-1182/pkg1/pkg1.gen.go
+++ b/internal/test/issues/issue-1182/pkg1/pkg1.gen.go
@@ -1,6 +1,6 @@
// Package pkg1 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package pkg1
import (
@@ -15,9 +15,9 @@ import (
"path"
"strings"
- externalRef0 "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1182/pkg2"
"github.com/getkin/kin-openapi/openapi3"
"github.com/labstack/echo/v4"
+ externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1182/pkg2"
strictecho "github.com/oapi-codegen/runtime/strictmiddleware/echo"
)
diff --git a/internal/test/issues/issue-1182/pkg2/config.yaml b/internal/test/issues/issue-1182/pkg2/config.yaml
index e4845843a..e61fd4844 100644
--- a/internal/test/issues/issue-1182/pkg2/config.yaml
+++ b/internal/test/issues/issue-1182/pkg2/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../../configuration-schema.json
package: pkg2
generate:
echo-server: true
diff --git a/internal/test/issues/issue-1182/pkg2/doc.go b/internal/test/issues/issue-1182/pkg2/doc.go
index fcb267c5c..68cb0b78a 100644
--- a/internal/test/issues/issue-1182/pkg2/doc.go
+++ b/internal/test/issues/issue-1182/pkg2/doc.go
@@ -1,3 +1,3 @@
package pkg2
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../pkg2.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../pkg2.yaml
diff --git a/internal/test/issues/issue-1182/pkg2/pkg2.gen.go b/internal/test/issues/issue-1182/pkg2/pkg2.gen.go
index 682bec3c0..51eece40a 100644
--- a/internal/test/issues/issue-1182/pkg2/pkg2.gen.go
+++ b/internal/test/issues/issue-1182/pkg2/pkg2.gen.go
@@ -1,6 +1,6 @@
// Package pkg2 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package pkg2
import (
diff --git a/internal/test/issues/issue-1189/config.yaml b/internal/test/issues/issue-1189/config.yaml
index 921e76c16..ddc507656 100644
--- a/internal/test/issues/issue-1189/config.yaml
+++ b/internal/test/issues/issue-1189/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: param
generate:
echo-server: true
diff --git a/internal/test/issues/issue-1189/doc.go b/internal/test/issues/issue-1189/doc.go
index c5c647f00..e64506f48 100644
--- a/internal/test/issues/issue-1189/doc.go
+++ b/internal/test/issues/issue-1189/doc.go
@@ -1,3 +1,3 @@
package param
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml issue1189.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml issue1189.yaml
diff --git a/internal/test/issues/issue-1189/issue1189.gen.go b/internal/test/issues/issue-1189/issue1189.gen.go
index 16ebff95a..c1a869ad9 100644
--- a/internal/test/issues/issue-1189/issue1189.gen.go
+++ b/internal/test/issues/issue-1189/issue1189.gen.go
@@ -1,6 +1,6 @@
// Package param provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package param
import (
diff --git a/internal/test/issues/issue-1208-1209/config.yaml b/internal/test/issues/issue-1208-1209/config.yaml
index 9ce73ab03..52a520aa3 100644
--- a/internal/test/issues/issue-1208-1209/config.yaml
+++ b/internal/test/issues/issue-1208-1209/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: multijson
generate:
client: true
diff --git a/internal/test/issues/issue-1208-1209/doc.go b/internal/test/issues/issue-1208-1209/doc.go
index bd18f8322..7384a2ab9 100644
--- a/internal/test/issues/issue-1208-1209/doc.go
+++ b/internal/test/issues/issue-1208-1209/doc.go
@@ -1,3 +1,3 @@
package multijson
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml issue-multi-json.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml issue-multi-json.yaml
diff --git a/internal/test/issues/issue-1208-1209/issue-multi-json.gen.go b/internal/test/issues/issue-1208-1209/issue-multi-json.gen.go
index dc43f33b6..780d45e6a 100644
--- a/internal/test/issues/issue-1208-1209/issue-multi-json.gen.go
+++ b/internal/test/issues/issue-1208-1209/issue-multi-json.gen.go
@@ -1,6 +1,6 @@
// Package multijson provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package multijson
import (
diff --git a/internal/test/issues/issue-1208-1209/issue-multi-json_test.go b/internal/test/issues/issue-1208-1209/issue-multi-json_test.go
index 825a9909e..2c379909e 100644
--- a/internal/test/issues/issue-1208-1209/issue-multi-json_test.go
+++ b/internal/test/issues/issue-1208-1209/issue-multi-json_test.go
@@ -6,7 +6,7 @@ import (
"net/http"
"testing"
- multijson "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1208-1209"
+ multijson "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1208-1209"
"github.com/stretchr/testify/assert"
)
diff --git a/internal/test/issues/issue-1212/pkg1/config.yaml b/internal/test/issues/issue-1212/pkg1/config.yaml
index 9a0498e09..040b8223b 100644
--- a/internal/test/issues/issue-1212/pkg1/config.yaml
+++ b/internal/test/issues/issue-1212/pkg1/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../../configuration-schema.json
package: pkg1
generate:
client: true
@@ -7,4 +8,4 @@ generate:
strict-server: true
output: pkg1.gen.go
import-mapping:
- pkg2.yaml: github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1212/pkg2
+ pkg2.yaml: github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1212/pkg2
diff --git a/internal/test/issues/issue-1212/pkg1/doc.go b/internal/test/issues/issue-1212/pkg1/doc.go
index 060f76260..8b57f0836 100644
--- a/internal/test/issues/issue-1212/pkg1/doc.go
+++ b/internal/test/issues/issue-1212/pkg1/doc.go
@@ -1,3 +1,3 @@
package pkg1
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../pkg1.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../pkg1.yaml
diff --git a/internal/test/issues/issue-1212/pkg1/pkg1.gen.go b/internal/test/issues/issue-1212/pkg1/pkg1.gen.go
index 4f0e619c3..bada274bc 100644
--- a/internal/test/issues/issue-1212/pkg1/pkg1.gen.go
+++ b/internal/test/issues/issue-1212/pkg1/pkg1.gen.go
@@ -1,6 +1,6 @@
// Package pkg1 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package pkg1
import (
@@ -17,9 +17,9 @@ import (
"path"
"strings"
- externalRef0 "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1212/pkg2"
"github.com/getkin/kin-openapi/openapi3"
"github.com/gin-gonic/gin"
+ externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1212/pkg2"
strictgin "github.com/oapi-codegen/runtime/strictmiddleware/gin"
)
diff --git a/internal/test/issues/issue-1212/pkg2/config.yaml b/internal/test/issues/issue-1212/pkg2/config.yaml
index 9ea6f2ce6..d3a63e5d4 100644
--- a/internal/test/issues/issue-1212/pkg2/config.yaml
+++ b/internal/test/issues/issue-1212/pkg2/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../../configuration-schema.json
package: pkg2
generate:
client: true
diff --git a/internal/test/issues/issue-1212/pkg2/doc.go b/internal/test/issues/issue-1212/pkg2/doc.go
index fcb267c5c..68cb0b78a 100644
--- a/internal/test/issues/issue-1212/pkg2/doc.go
+++ b/internal/test/issues/issue-1212/pkg2/doc.go
@@ -1,3 +1,3 @@
package pkg2
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../pkg2.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../pkg2.yaml
diff --git a/internal/test/issues/issue-1212/pkg2/pkg2.gen.go b/internal/test/issues/issue-1212/pkg2/pkg2.gen.go
index fa8d50fde..5a994ed06 100644
--- a/internal/test/issues/issue-1212/pkg2/pkg2.gen.go
+++ b/internal/test/issues/issue-1212/pkg2/pkg2.gen.go
@@ -1,6 +1,6 @@
// Package pkg2 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package pkg2
import (
diff --git a/internal/test/issues/issue-1219/config.yaml b/internal/test/issues/issue-1219/config.yaml
index 0260889cd..91e041af5 100644
--- a/internal/test/issues/issue-1219/config.yaml
+++ b/internal/test/issues/issue-1219/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue1219
generate:
models: true
diff --git a/internal/test/issues/issue-1219/doc.go b/internal/test/issues/issue-1219/doc.go
index 6976b420b..7e1118e5c 100644
--- a/internal/test/issues/issue-1219/doc.go
+++ b/internal/test/issues/issue-1219/doc.go
@@ -1,3 +1,3 @@
package issue1219
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml issue.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml issue.yaml
diff --git a/internal/test/issues/issue-1219/issue.gen.go b/internal/test/issues/issue-1219/issue.gen.go
index e8df58f14..2beeedc59 100644
--- a/internal/test/issues/issue-1219/issue.gen.go
+++ b/internal/test/issues/issue-1219/issue.gen.go
@@ -1,6 +1,6 @@
// Package issue1219 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue1219
import (
diff --git a/internal/test/issues/issue-1219/issue_test.go b/internal/test/issues/issue-1219/issue_test.go
index 489675922..aebd0d1af 100644
--- a/internal/test/issues/issue-1219/issue_test.go
+++ b/internal/test/issues/issue-1219/issue_test.go
@@ -4,7 +4,7 @@ import (
"reflect"
"testing"
- issue1219 "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1219"
+ issue1219 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1219"
"github.com/stretchr/testify/assert"
)
diff --git a/internal/test/issues/issue-1298/config.yaml b/internal/test/issues/issue-1298/config.yaml
index a966f3ea4..76ef6715e 100644
--- a/internal/test/issues/issue-1298/config.yaml
+++ b/internal/test/issues/issue-1298/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue1298
generate:
models: true
diff --git a/internal/test/issues/issue-1298/doc.go b/internal/test/issues/issue-1298/doc.go
index dbae518f0..b5e5ee95c 100644
--- a/internal/test/issues/issue-1298/doc.go
+++ b/internal/test/issues/issue-1298/doc.go
@@ -1,3 +1,3 @@
package issue1298
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml issue1298.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml issue1298.yaml
diff --git a/internal/test/issues/issue-1298/issue1298.gen.go b/internal/test/issues/issue-1298/issue1298.gen.go
index 03f8eb392..94734a577 100644
--- a/internal/test/issues/issue-1298/issue1298.gen.go
+++ b/internal/test/issues/issue-1298/issue1298.gen.go
@@ -1,6 +1,6 @@
// Package issue1298 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue1298
import (
diff --git a/internal/test/issues/issue-1298/issue1298_test.go b/internal/test/issues/issue-1298/issue1298_test.go
index 62bc46884..0d627f10f 100644
--- a/internal/test/issues/issue-1298/issue1298_test.go
+++ b/internal/test/issues/issue-1298/issue1298_test.go
@@ -6,8 +6,8 @@ import (
"net/http/httptest"
"testing"
- issue1298 "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1298"
"github.com/gin-gonic/gin"
+ issue1298 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1298"
"github.com/stretchr/testify/assert"
)
diff --git a/internal/test/issues/issue-1378/bionicle/bionicle.gen.go b/internal/test/issues/issue-1378/bionicle/bionicle.gen.go
index 4b41f81d0..ec4c1f3b7 100644
--- a/internal/test/issues/issue-1378/bionicle/bionicle.gen.go
+++ b/internal/test/issues/issue-1378/bionicle/bionicle.gen.go
@@ -1,6 +1,6 @@
// Package bionicle provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package bionicle
import (
@@ -15,9 +15,9 @@ import (
"path"
"strings"
- externalRef0 "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1378/common"
"github.com/getkin/kin-openapi/openapi3"
"github.com/gorilla/mux"
+ externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1378/common"
"github.com/oapi-codegen/runtime"
strictnethttp "github.com/oapi-codegen/runtime/strictmiddleware/nethttp"
)
diff --git a/internal/test/issues/issue-1378/bionicle/config.yaml b/internal/test/issues/issue-1378/bionicle/config.yaml
index 21cdcd41e..4f81605dc 100644
--- a/internal/test/issues/issue-1378/bionicle/config.yaml
+++ b/internal/test/issues/issue-1378/bionicle/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../../configuration-schema.json
package: bionicle
generate:
gorilla-server: true
@@ -5,5 +6,5 @@ generate:
strict-server: true
models: true
import-mapping:
- common.yaml: github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1378/common
+ common.yaml: github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1378/common
output: bionicle.gen.go
diff --git a/internal/test/issues/issue-1378/bionicle/generate.go b/internal/test/issues/issue-1378/bionicle/generate.go
index 86c5c1ab0..26b366169 100644
--- a/internal/test/issues/issue-1378/bionicle/generate.go
+++ b/internal/test/issues/issue-1378/bionicle/generate.go
@@ -1,3 +1,3 @@
package bionicle
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../bionicle.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../bionicle.yaml
diff --git a/internal/test/issues/issue-1378/common/common.gen.go b/internal/test/issues/issue-1378/common/common.gen.go
index ce5ae4acf..d1747783e 100644
--- a/internal/test/issues/issue-1378/common/common.gen.go
+++ b/internal/test/issues/issue-1378/common/common.gen.go
@@ -1,6 +1,6 @@
// Package common provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package common
import (
diff --git a/internal/test/issues/issue-1378/common/config.yaml b/internal/test/issues/issue-1378/common/config.yaml
index 82fd8a275..2d2960cdc 100644
--- a/internal/test/issues/issue-1378/common/config.yaml
+++ b/internal/test/issues/issue-1378/common/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../../configuration-schema.json
package: common
generate:
gorilla-server: true
diff --git a/internal/test/issues/issue-1378/common/generate.go b/internal/test/issues/issue-1378/common/generate.go
index b54279ec4..dbb23b05d 100644
--- a/internal/test/issues/issue-1378/common/generate.go
+++ b/internal/test/issues/issue-1378/common/generate.go
@@ -1,3 +1,3 @@
package common
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../common.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../common.yaml
diff --git a/internal/test/issues/issue-1378/fooservice/config.yaml b/internal/test/issues/issue-1378/fooservice/config.yaml
index df64cfa03..4690bd037 100644
--- a/internal/test/issues/issue-1378/fooservice/config.yaml
+++ b/internal/test/issues/issue-1378/fooservice/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../../configuration-schema.json
package: fooservice
generate:
gorilla-server: true
@@ -5,6 +6,6 @@ generate:
strict-server: true
models: true
import-mapping:
- common.yaml: github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1378/common
- bionicle.yaml: github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1378/bionicle
+ common.yaml: github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1378/common
+ bionicle.yaml: github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1378/bionicle
output: fooservice.gen.go
diff --git a/internal/test/issues/issue-1378/fooservice/fooservice.gen.go b/internal/test/issues/issue-1378/fooservice/fooservice.gen.go
index 8d2bb1fc7..c74056ac5 100644
--- a/internal/test/issues/issue-1378/fooservice/fooservice.gen.go
+++ b/internal/test/issues/issue-1378/fooservice/fooservice.gen.go
@@ -1,6 +1,6 @@
// Package fooservice provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package fooservice
import (
@@ -15,10 +15,10 @@ import (
"path"
"strings"
- externalRef0 "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1378/bionicle"
- externalRef1 "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-1378/common"
"github.com/getkin/kin-openapi/openapi3"
"github.com/gorilla/mux"
+ externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1378/bionicle"
+ externalRef1 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-1378/common"
"github.com/oapi-codegen/runtime"
strictnethttp "github.com/oapi-codegen/runtime/strictmiddleware/nethttp"
)
diff --git a/internal/test/issues/issue-1378/fooservice/generate.go b/internal/test/issues/issue-1378/fooservice/generate.go
index 30826e829..2419719db 100644
--- a/internal/test/issues/issue-1378/fooservice/generate.go
+++ b/internal/test/issues/issue-1378/fooservice/generate.go
@@ -1,3 +1,3 @@
package fooservice
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../foo-service.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../foo-service.yaml
diff --git a/internal/test/issues/issue-1397/config.yaml b/internal/test/issues/issue-1397/config.yaml
new file mode 100644
index 000000000..d4a1284ee
--- /dev/null
+++ b/internal/test/issues/issue-1397/config.yaml
@@ -0,0 +1,8 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: issue1397
+generate:
+ echo-server: true
+ client: true
+ models: true
+ embedded-spec: true
+output: issue1397.gen.go
diff --git a/internal/test/issues/issue-1397/doc.go b/internal/test/issues/issue-1397/doc.go
new file mode 100644
index 000000000..e5964fe29
--- /dev/null
+++ b/internal/test/issues/issue-1397/doc.go
@@ -0,0 +1,3 @@
+package issue1397
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/issues/issue-1397/issue1397.gen.go b/internal/test/issues/issue-1397/issue1397.gen.go
new file mode 100644
index 000000000..2463641eb
--- /dev/null
+++ b/internal/test/issues/issue-1397/issue1397.gen.go
@@ -0,0 +1,440 @@
+// Package issue1397 provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package issue1397
+
+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"
+)
+
+// Defines values for TestField1.
+const (
+ Option1 TestField1 = "option1"
+ Option2 TestField1 = "option2"
+)
+
+// Test defines model for Test.
+type Test = MyTestRequest
+
+// TestField1 defines model for Test.Field1.
+type TestField1 string
+
+// MyTestRequestNestedField A nested object with allocated name
+type MyTestRequestNestedField struct {
+ Field1 bool `json:"field1"`
+ Field2 string `json:"field2"`
+}
+
+// MyTestRequest defines model for .
+type MyTestRequest struct {
+ // Field1 A array of enum values
+ Field1 *[]TestField1 `json:"field1,omitempty"`
+
+ // Field2 A nested object with allocated name
+ Field2 *MyTestRequestNestedField `json:"field2,omitempty"`
+
+ // Field3 A nested object without allocated name
+ Field3 *struct {
+ Field1 bool `json:"field1"`
+ Field2 string `json:"field2"`
+ } `json:"field3,omitempty"`
+}
+
+// TestApplicationTestPlusJSONRequestBody defines body for Test for application/test+json ContentType.
+type TestApplicationTestPlusJSONRequestBody = Test
+
+// 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 {
+ // TestWithBody request with any body
+ TestWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ TestWithApplicationTestPlusJSONBody(ctx context.Context, body TestApplicationTestPlusJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+func (c *Client) TestWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewTestRequestWithBody(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) TestWithApplicationTestPlusJSONBody(ctx context.Context, body TestApplicationTestPlusJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewTestRequestWithApplicationTestPlusJSONBody(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)
+}
+
+// NewTestRequestWithApplicationTestPlusJSONBody calls the generic Test builder with application/test+json body
+func NewTestRequestWithApplicationTestPlusJSONBody(server string, body TestApplicationTestPlusJSONRequestBody) (*http.Request, error) {
+ var bodyReader io.Reader
+ buf, err := json.Marshal(body)
+ if err != nil {
+ return nil, err
+ }
+ bodyReader = bytes.NewReader(buf)
+ return NewTestRequestWithBody(server, "application/test+json", bodyReader)
+}
+
+// NewTestRequestWithBody generates requests for Test with any type of body
+func NewTestRequestWithBody(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("/test")
+ if operationPath[0] == '/' {
+ operationPath = "." + operationPath
+ }
+
+ queryURL, err := serverURL.Parse(operationPath)
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest("GET", queryURL.String(), body)
+ if err != nil {
+ return nil, err
+ }
+
+ req.Header.Add("Content-Type", contentType)
+
+ 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 {
+ // TestWithBodyWithResponse request with any body
+ TestWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*TestResponse, error)
+
+ TestWithApplicationTestPlusJSONBodyWithResponse(ctx context.Context, body TestApplicationTestPlusJSONRequestBody, reqEditors ...RequestEditorFn) (*TestResponse, error)
+}
+
+type TestResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+}
+
+// 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
+}
+
+// TestWithBodyWithResponse request with arbitrary body returning *TestResponse
+func (c *ClientWithResponses) TestWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*TestResponse, error) {
+ rsp, err := c.TestWithBody(ctx, contentType, body, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParseTestResponse(rsp)
+}
+
+func (c *ClientWithResponses) TestWithApplicationTestPlusJSONBodyWithResponse(ctx context.Context, body TestApplicationTestPlusJSONRequestBody, reqEditors ...RequestEditorFn) (*TestResponse, error) {
+ rsp, err := c.TestWithApplicationTestPlusJSONBody(ctx, body, 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,
+ }
+
+ 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)
+
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+ "H4sIAAAAAAAC/8xTO2/bMBD+K8K1W2XLj3bh1g4FPLRD4C3IQEsnmQbFo8lTYsHQfw+OUmzkBSRbJh2O",
+ "9/F76HiGklpPDh1HUGeI5R5bncotRpavD+QxsMHUrQ3aailVhbEMxrMhBwp+ZzoE3WdUZ+i6NrvXtsMI",
+ "ORjGNiGlDeoWKEGWkE/VCu5y4N4jKIgcjGtgyKHVp82I/HU5TQxymESs3hLhMDJWGe0OWHL2YHifaWup",
+ "1NJ1ukXI3zU0seyILGr3nOeFviGHgMfOBKzE0nTHBXA1NAqBHE6zhmbSnCUVCv71EvANHjuM/D/J/ivo",
+ "C+/6Y/6o4y9hUQCfMw2DYIyrCZTrrJWFQKe9AQXr+WIubF7zPnkoeFrHBtNH/GmJZVOBGnd1FIyR/1DV",
+ "y0xJjtGlce29NWUCpJt+HKIk+rTwUn0PWIOCb8X1RRTTcyi2k9wUSvTk4pjsavHz9V9qiKo0PAyPAQAA",
+ "///99gukXwMAAA==",
+}
+
+// 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-1397/spec.yaml b/internal/test/issues/issue-1397/spec.yaml
new file mode 100644
index 000000000..93cc609ed
--- /dev/null
+++ b/internal/test/issues/issue-1397/spec.yaml
@@ -0,0 +1,52 @@
+openapi: "3.0.1"
+components:
+ schemas:
+ Test:
+ type: object
+ properties:
+ field1:
+ description: A array of enum values
+ items:
+ enum:
+ - option1
+ - option2
+ type: string
+ maxItems: 5
+ minItems: 0
+ type: array
+ field2:
+ description: A nested object with allocated name
+ properties:
+ field1:
+ type: boolean
+ field2:
+ type: string
+ required:
+ - field1
+ - field2
+ type: object
+ x-go-type-name: MyTestRequestNestedField
+ field3:
+ description: A nested object without allocated name
+ properties:
+ field1:
+ type: boolean
+ field2:
+ type: string
+ required:
+ - field1
+ - field2
+ type: object
+ x-go-type-name: MyTestRequest
+paths:
+ /test:
+ get:
+ operationId: test
+ requestBody:
+ content:
+ application/test+json:
+ schema:
+ $ref: "#/components/schemas/Test"
+ responses:
+ 204:
+ description: good
diff --git a/internal/test/issues/issue-312/config.yaml b/internal/test/issues/issue-312/config.yaml
index a0db7e978..39cb19051 100644
--- a/internal/test/issues/issue-312/config.yaml
+++ b/internal/test/issues/issue-312/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue312
generate:
echo-server: true
diff --git a/internal/test/issues/issue-312/doc.go b/internal/test/issues/issue-312/doc.go
index 475c1b4c2..768a4595b 100644
--- a/internal/test/issues/issue-312/doc.go
+++ b/internal/test/issues/issue-312/doc.go
@@ -1,3 +1,3 @@
package issue312
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/issues/issue-312/issue.gen.go b/internal/test/issues/issue-312/issue.gen.go
index 690705d21..f0285c071 100644
--- a/internal/test/issues/issue-312/issue.gen.go
+++ b/internal/test/issues/issue-312/issue.gen.go
@@ -1,6 +1,6 @@
// Package issue312 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue312
import (
diff --git a/internal/test/issues/issue-52/config.yaml b/internal/test/issues/issue-52/config.yaml
index 8ea198ff2..1277b9c97 100644
--- a/internal/test/issues/issue-52/config.yaml
+++ b/internal/test/issues/issue-52/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue52
generate:
echo-server: true
diff --git a/internal/test/issues/issue-52/doc.go b/internal/test/issues/issue-52/doc.go
index aa9f97725..3d239ebdc 100644
--- a/internal/test/issues/issue-52/doc.go
+++ b/internal/test/issues/issue-52/doc.go
@@ -1,3 +1,3 @@
package issue52
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/issues/issue-52/issue.gen.go b/internal/test/issues/issue-52/issue.gen.go
index 4664ce68c..f024999d6 100644
--- a/internal/test/issues/issue-52/issue.gen.go
+++ b/internal/test/issues/issue-52/issue.gen.go
@@ -1,6 +1,6 @@
// Package issue52 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue52
import (
diff --git a/internal/test/issues/issue-52/issue_test.go b/internal/test/issues/issue-52/issue_test.go
index 09cadd821..0288c2aea 100644
--- a/internal/test/issues/issue-52/issue_test.go
+++ b/internal/test/issues/issue-52/issue_test.go
@@ -4,8 +4,8 @@ import (
_ "embed"
"testing"
- "github.com/deepmap/oapi-codegen/v2/pkg/codegen"
"github.com/getkin/kin-openapi/openapi3"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen"
"github.com/stretchr/testify/require"
)
diff --git a/internal/test/issues/issue-579/gen.go b/internal/test/issues/issue-579/gen.go
index c77dc735c..7b198d0cd 100644
--- a/internal/test/issues/issue-579/gen.go
+++ b/internal/test/issues/issue-579/gen.go
@@ -1,3 +1,3 @@
package issue579
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --package=issue579 --generate=types,skip-prune --alias-types -o issue.gen.go spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --package=issue579 --generate=types,skip-prune --alias-types -o issue.gen.go spec.yaml
diff --git a/internal/test/issues/issue-579/issue.gen.go b/internal/test/issues/issue-579/issue.gen.go
index 3bb1dc89f..54326646d 100644
--- a/internal/test/issues/issue-579/issue.gen.go
+++ b/internal/test/issues/issue-579/issue.gen.go
@@ -1,6 +1,6 @@
// Package issue579 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue579
import (
diff --git a/internal/test/issues/issue-832/config.yaml b/internal/test/issues/issue-832/config.yaml
index e1eb4e5f6..446d7a14e 100644
--- a/internal/test/issues/issue-832/config.yaml
+++ b/internal/test/issues/issue-832/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue_832
generate:
models: true
diff --git a/internal/test/issues/issue-832/generate.go b/internal/test/issues/issue-832/generate.go
index 5fdb5aa06..79b06c713 100644
--- a/internal/test/issues/issue-832/generate.go
+++ b/internal/test/issues/issue-832/generate.go
@@ -1,3 +1,3 @@
package issue_832
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/issues/issue-832/issue.gen.go b/internal/test/issues/issue-832/issue.gen.go
index fc7a529f8..0aa74f232 100644
--- a/internal/test/issues/issue-832/issue.gen.go
+++ b/internal/test/issues/issue-832/issue.gen.go
@@ -1,6 +1,6 @@
// Package issue_832 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue_832
import (
diff --git a/internal/test/issues/issue-936/api.gen.go b/internal/test/issues/issue-936/api.gen.go
index 2e94df1e9..6b7c0cf22 100644
--- a/internal/test/issues/issue-936/api.gen.go
+++ b/internal/test/issues/issue-936/api.gen.go
@@ -1,6 +1,6 @@
// Package issue936 provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package issue936
import (
diff --git a/internal/test/issues/issue-936/gen.go b/internal/test/issues/issue-936/gen.go
index a84cbacd2..f1e62f42f 100644
--- a/internal/test/issues/issue-936/gen.go
+++ b/internal/test/issues/issue-936/gen.go
@@ -1,3 +1,3 @@
package issue936
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.config.yaml spec.yaml
diff --git a/internal/test/issues/issue-936/server.config.yaml b/internal/test/issues/issue-936/server.config.yaml
index aa459d00d..76b85471a 100644
--- a/internal/test/issues/issue-936/server.config.yaml
+++ b/internal/test/issues/issue-936/server.config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: issue936
output: api.gen.go
generate:
diff --git a/internal/test/issues/issue-grab_import_names/config.yaml b/internal/test/issues/issue-grab_import_names/config.yaml
index 3248a4893..85e3f15e6 100644
--- a/internal/test/issues/issue-grab_import_names/config.yaml
+++ b/internal/test/issues/issue-grab_import_names/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: grabimportnames
generate:
echo-server: true
diff --git a/internal/test/issues/issue-grab_import_names/doc.go b/internal/test/issues/issue-grab_import_names/doc.go
index ebdbdfc72..e986569fc 100644
--- a/internal/test/issues/issue-grab_import_names/doc.go
+++ b/internal/test/issues/issue-grab_import_names/doc.go
@@ -1,3 +1,3 @@
package grabimportnames
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/issues/issue-grab_import_names/issue.gen.go b/internal/test/issues/issue-grab_import_names/issue.gen.go
index 59924fa3a..52564c0dd 100644
--- a/internal/test/issues/issue-grab_import_names/issue.gen.go
+++ b/internal/test/issues/issue-grab_import_names/issue.gen.go
@@ -1,6 +1,6 @@
// Package grabimportnames provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package grabimportnames
import (
diff --git a/internal/test/issues/issue-grab_import_names/issue_test.go b/internal/test/issues/issue-grab_import_names/issue_test.go
index c954d6542..7d299fa22 100644
--- a/internal/test/issues/issue-grab_import_names/issue_test.go
+++ b/internal/test/issues/issue-grab_import_names/issue_test.go
@@ -3,8 +3,8 @@ package grabimportnames
import (
"testing"
- "github.com/deepmap/oapi-codegen/v2/pkg/codegen"
"github.com/getkin/kin-openapi/openapi3"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen"
"github.com/stretchr/testify/require"
)
diff --git a/internal/test/issues/issue-head-digit-of-httpheader/config.yaml b/internal/test/issues/issue-head-digit-of-httpheader/config.yaml
index 1f7ce9d39..37457c892 100644
--- a/internal/test/issues/issue-head-digit-of-httpheader/config.yaml
+++ b/internal/test/issues/issue-head-digit-of-httpheader/config.yaml
@@ -1,4 +1,5 @@
---
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: headdigitofhttpheader
generate:
strict-server: true
diff --git a/internal/test/issues/issue-head-digit-of-httpheader/doc.go b/internal/test/issues/issue-head-digit-of-httpheader/doc.go
index 69cb64af7..63904053b 100644
--- a/internal/test/issues/issue-head-digit-of-httpheader/doc.go
+++ b/internal/test/issues/issue-head-digit-of-httpheader/doc.go
@@ -1,3 +1,3 @@
package headdigitofhttpheader
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/issues/issue-head-digit-of-httpheader/issue.gen.go b/internal/test/issues/issue-head-digit-of-httpheader/issue.gen.go
index 14688abb4..6eadcef68 100644
--- a/internal/test/issues/issue-head-digit-of-httpheader/issue.gen.go
+++ b/internal/test/issues/issue-head-digit-of-httpheader/issue.gen.go
@@ -1,6 +1,6 @@
// Package headdigitofhttpheader provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package headdigitofhttpheader
type N200ResponseHeaders struct {
diff --git a/internal/test/issues/issue-head-digit-of-operation-id/config.yaml b/internal/test/issues/issue-head-digit-of-operation-id/config.yaml
index 5823c79eb..9ac5a0a12 100644
--- a/internal/test/issues/issue-head-digit-of-operation-id/config.yaml
+++ b/internal/test/issues/issue-head-digit-of-operation-id/config.yaml
@@ -1,4 +1,5 @@
---
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: head_digit_of_operation_id
generate:
strict-server: true
diff --git a/internal/test/issues/issue-head-digit-of-operation-id/doc.go b/internal/test/issues/issue-head-digit-of-operation-id/doc.go
index 23999975b..fb08e63e8 100644
--- a/internal/test/issues/issue-head-digit-of-operation-id/doc.go
+++ b/internal/test/issues/issue-head-digit-of-operation-id/doc.go
@@ -1,3 +1,3 @@
package head_digit_of_operation_id
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/issues/issue-head-digit-of-operation-id/issue.gen.go b/internal/test/issues/issue-head-digit-of-operation-id/issue.gen.go
index 1d2b6b0ac..00c0844af 100644
--- a/internal/test/issues/issue-head-digit-of-operation-id/issue.gen.go
+++ b/internal/test/issues/issue-head-digit-of-operation-id/issue.gen.go
@@ -1,4 +1,4 @@
// Package head_digit_of_operation_id provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package head_digit_of_operation_id
diff --git a/internal/test/issues/issue-illegal_enum_names/config.yaml b/internal/test/issues/issue-illegal_enum_names/config.yaml
index 9b426a0d5..e8bbe0e35 100644
--- a/internal/test/issues/issue-illegal_enum_names/config.yaml
+++ b/internal/test/issues/issue-illegal_enum_names/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: illegalenumnames
generate:
echo-server: true
diff --git a/internal/test/issues/issue-illegal_enum_names/doc.go b/internal/test/issues/issue-illegal_enum_names/doc.go
index 6249ddd6a..d8fb076b4 100644
--- a/internal/test/issues/issue-illegal_enum_names/doc.go
+++ b/internal/test/issues/issue-illegal_enum_names/doc.go
@@ -1,3 +1,3 @@
package illegalenumnames
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
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 395c171cb..a24b19da0 100644
--- a/internal/test/issues/issue-illegal_enum_names/issue.gen.go
+++ b/internal/test/issues/issue-illegal_enum_names/issue.gen.go
@@ -1,6 +1,6 @@
// Package illegalenumnames provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package illegalenumnames
import (
diff --git a/internal/test/issues/issue-illegal_enum_names/issue_test.go b/internal/test/issues/issue-illegal_enum_names/issue_test.go
index 2fdfb86ac..3a8b47510 100644
--- a/internal/test/issues/issue-illegal_enum_names/issue_test.go
+++ b/internal/test/issues/issue-illegal_enum_names/issue_test.go
@@ -6,8 +6,8 @@ import (
"go/token"
"testing"
- "github.com/deepmap/oapi-codegen/v2/pkg/codegen"
"github.com/getkin/kin-openapi/openapi3"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/codegen"
"github.com/stretchr/testify/require"
)
diff --git a/internal/test/issues/issue-removed-external-ref/config.base.yaml b/internal/test/issues/issue-removed-external-ref/config.base.yaml
index 2a0c84ba9..14faed834 100644
--- a/internal/test/issues/issue-removed-external-ref/config.base.yaml
+++ b/internal/test/issues/issue-removed-external-ref/config.base.yaml
@@ -1,11 +1,12 @@
---
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: spec_base
generate:
chi-server: true
strict-server: true
models: true
import-mapping:
- spec-ext.yaml: "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-removed-external-ref/gen/spec_ext"
+ spec-ext.yaml: "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-removed-external-ref/gen/spec_ext"
output: gen/spec_base/issue.gen.go
output-options:
skip-prune: true
diff --git a/internal/test/issues/issue-removed-external-ref/config.ext.yaml b/internal/test/issues/issue-removed-external-ref/config.ext.yaml
index 9d0478065..efb166ed2 100644
--- a/internal/test/issues/issue-removed-external-ref/config.ext.yaml
+++ b/internal/test/issues/issue-removed-external-ref/config.ext.yaml
@@ -1,4 +1,5 @@
---
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: spec_ext
generate:
chi-server: true
diff --git a/internal/test/issues/issue-removed-external-ref/doc.go b/internal/test/issues/issue-removed-external-ref/doc.go
index 9f222d4cf..6af4d981f 100644
--- a/internal/test/issues/issue-removed-external-ref/doc.go
+++ b/internal/test/issues/issue-removed-external-ref/doc.go
@@ -1,4 +1,4 @@
package head_digit_of_httpheader
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.ext.yaml spec-ext.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.base.yaml spec-base.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.ext.yaml spec-ext.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.base.yaml spec-base.yaml
diff --git a/internal/test/issues/issue-removed-external-ref/gen/spec_base/issue.gen.go b/internal/test/issues/issue-removed-external-ref/gen/spec_base/issue.gen.go
index 6b2de3157..627abde1f 100644
--- a/internal/test/issues/issue-removed-external-ref/gen/spec_base/issue.gen.go
+++ b/internal/test/issues/issue-removed-external-ref/gen/spec_base/issue.gen.go
@@ -1,6 +1,6 @@
// Package spec_base provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package spec_base
import (
@@ -9,8 +9,8 @@ import (
"fmt"
"net/http"
- externalRef0 "github.com/deepmap/oapi-codegen/v2/internal/test/issues/issue-removed-external-ref/gen/spec_ext"
"github.com/go-chi/chi/v5"
+ externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/internal/test/issues/issue-removed-external-ref/gen/spec_ext"
strictnethttp "github.com/oapi-codegen/runtime/strictmiddleware/nethttp"
)
diff --git a/internal/test/issues/issue-removed-external-ref/gen/spec_ext/issue.gen.go b/internal/test/issues/issue-removed-external-ref/gen/spec_ext/issue.gen.go
index 42eef1a8b..881f8be12 100644
--- a/internal/test/issues/issue-removed-external-ref/gen/spec_ext/issue.gen.go
+++ b/internal/test/issues/issue-removed-external-ref/gen/spec_ext/issue.gen.go
@@ -1,6 +1,6 @@
// Package spec_ext provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package spec_ext
import (
diff --git a/internal/test/issues/issue1469/config.yaml b/internal/test/issues/issue1469/config.yaml
new file mode 100644
index 000000000..0995b5f9f
--- /dev/null
+++ b/internal/test/issues/issue1469/config.yaml
@@ -0,0 +1,5 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: issue1469
+generate:
+ fiber-server: true
+output: main.gen.go
diff --git a/internal/test/issues/issue1469/doc.go b/internal/test/issues/issue1469/doc.go
new file mode 100644
index 000000000..d72f419f6
--- /dev/null
+++ b/internal/test/issues/issue1469/doc.go
@@ -0,0 +1,3 @@
+package issue1469
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/issues/issue1469/main.gen.go b/internal/test/issues/issue1469/main.gen.go
new file mode 100644
index 000000000..11f87b0c4
--- /dev/null
+++ b/internal/test/issues/issue1469/main.gen.go
@@ -0,0 +1,53 @@
+// Package issue1469 provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package issue1469
+
+import (
+ "github.com/gofiber/fiber/v2"
+)
+
+// 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)
+
+}
diff --git a/internal/test/issues/issue1469/main_test.go b/internal/test/issues/issue1469/main_test.go
new file mode 100644
index 000000000..3af67244a
--- /dev/null
+++ b/internal/test/issues/issue1469/main_test.go
@@ -0,0 +1,35 @@
+package issue1469
+
+import (
+ "testing"
+
+ "github.com/gofiber/fiber/v2"
+ "github.com/stretchr/testify/assert"
+)
+
+type impl struct{}
+
+// (GET /test)
+func (i *impl) Test(c *fiber.Ctx) error {
+ panic("not implemented") // TODO: Implement
+}
+
+func TestIssue1469(t *testing.T) {
+ server := &impl{}
+
+ r := fiber.New()
+
+ assert.NotPanics(t, func() {
+ RegisterHandlers(r, server)
+ })
+
+ assert.NotPanics(t, func() {
+ RegisterHandlersWithOptions(r, server, FiberServerOptions{
+ Middlewares: []MiddlewareFunc{
+ func(c *fiber.Ctx) error {
+ return nil
+ },
+ },
+ })
+ })
+}
diff --git a/internal/test/issues/issue1469/spec.yaml b/internal/test/issues/issue1469/spec.yaml
new file mode 100644
index 000000000..69a8a3e28
--- /dev/null
+++ b/internal/test/issues/issue1469/spec.yaml
@@ -0,0 +1,13 @@
+openapi: "3.0.1"
+paths:
+ /test:
+ get:
+ operationId: test
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+ responses:
+ 200:
+ description: good
diff --git a/internal/test/issues/issue193/config.yaml b/internal/test/issues/issue193/config.yaml
new file mode 100644
index 000000000..908d772c6
--- /dev/null
+++ b/internal/test/issues/issue193/config.yaml
@@ -0,0 +1,6 @@
+package: issue52
+generate:
+ models: true
+output: issue.gen.go
+output-options:
+ skip-prune: true
diff --git a/internal/test/issues/issue193/generate.go b/internal/test/issues/issue193/generate.go
new file mode 100644
index 000000000..3d239ebdc
--- /dev/null
+++ b/internal/test/issues/issue193/generate.go
@@ -0,0 +1,3 @@
+package issue52
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/issues/issue193/issue.gen.go b/internal/test/issues/issue193/issue.gen.go
new file mode 100644
index 000000000..eec8a25df
--- /dev/null
+++ b/internal/test/issues/issue193/issue.gen.go
@@ -0,0 +1,113 @@
+// Package issue52 provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package issue52
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+// Person defines model for Person.
+type Person struct {
+ Age *float32 `json:"age,omitempty"`
+ Metadata string `json:"metadata"`
+ Name *string `json:"name,omitempty"`
+ AdditionalProperties map[string]interface{} `json:"-"`
+}
+
+// Getter for additional properties for Person. Returns the specified
+// element and whether it was found
+func (a Person) Get(fieldName string) (value interface{}, found bool) {
+ if a.AdditionalProperties != nil {
+ value, found = a.AdditionalProperties[fieldName]
+ }
+ return
+}
+
+// Setter for additional properties for Person
+func (a *Person) Set(fieldName string, value interface{}) {
+ if a.AdditionalProperties == nil {
+ a.AdditionalProperties = make(map[string]interface{})
+ }
+ a.AdditionalProperties[fieldName] = value
+}
+
+// Override default JSON handling for Person to handle AdditionalProperties
+func (a *Person) UnmarshalJSON(b []byte) error {
+ object := make(map[string]json.RawMessage)
+ err := json.Unmarshal(b, &object)
+ if err != nil {
+ return err
+ }
+
+ if raw, found := object["age"]; found {
+ err = json.Unmarshal(raw, &a.Age)
+ if err != nil {
+ return fmt.Errorf("error reading 'age': %w", err)
+ }
+ delete(object, "age")
+ }
+
+ if raw, found := object["metadata"]; found {
+ err = json.Unmarshal(raw, &a.Metadata)
+ if err != nil {
+ return fmt.Errorf("error reading 'metadata': %w", err)
+ }
+ delete(object, "metadata")
+ }
+
+ if raw, found := object["name"]; found {
+ err = json.Unmarshal(raw, &a.Name)
+ if err != nil {
+ return fmt.Errorf("error reading 'name': %w", err)
+ }
+ delete(object, "name")
+ }
+
+ if len(object) != 0 {
+ a.AdditionalProperties = make(map[string]interface{})
+ for fieldName, fieldBuf := range object {
+ var fieldVal interface{}
+ err := json.Unmarshal(fieldBuf, &fieldVal)
+ if err != nil {
+ return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err)
+ }
+ a.AdditionalProperties[fieldName] = fieldVal
+ }
+ }
+ return nil
+}
+
+// Override default JSON handling for Person to handle AdditionalProperties
+func (a Person) MarshalJSON() ([]byte, error) {
+ var err error
+ object := make(map[string]json.RawMessage)
+
+ if a.Age != nil {
+ object["age"], err = json.Marshal(a.Age)
+ if err != nil {
+ return nil, fmt.Errorf("error marshaling 'age': %w", err)
+ }
+ }
+
+ object["metadata"], err = json.Marshal(a.Metadata)
+ if err != nil {
+ return nil, fmt.Errorf("error marshaling 'metadata': %w", err)
+ }
+
+ if a.Name != nil {
+ object["name"], err = json.Marshal(a.Name)
+ if err != nil {
+ return nil, fmt.Errorf("error marshaling 'name': %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/issue193/spec.yaml b/internal/test/issues/issue193/spec.yaml
new file mode 100644
index 000000000..4002ffbca
--- /dev/null
+++ b/internal/test/issues/issue193/spec.yaml
@@ -0,0 +1,26 @@
+openapi: 3.0.0
+info:
+ title: test schema
+
+paths:
+
+components:
+ schemas:
+ Person:
+ allOf:
+ # common fields
+ - type: object
+ additionalProperties: true
+ required:
+ - metadata
+ properties:
+ metadata:
+ type: string
+ # person specific fields
+ - type: object
+ additionalProperties: true
+ properties:
+ name:
+ type: string
+ age:
+ type: number
diff --git a/internal/test/outputoptions/disabletypealiases/config.yaml b/internal/test/outputoptions/disabletypealiases/config.yaml
index 615bfcda7..b82daa271 100644
--- a/internal/test/outputoptions/disabletypealiases/config.yaml
+++ b/internal/test/outputoptions/disabletypealiases/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: types
generate:
models: true
diff --git a/internal/test/outputoptions/disabletypealiases/generate.go b/internal/test/outputoptions/disabletypealiases/generate.go
index 8043e48f5..8f0dd5b3e 100644
--- a/internal/test/outputoptions/disabletypealiases/generate.go
+++ b/internal/test/outputoptions/disabletypealiases/generate.go
@@ -1,3 +1,3 @@
package types
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml
diff --git a/internal/test/outputoptions/disabletypealiases/types.gen.go b/internal/test/outputoptions/disabletypealiases/types.gen.go
index 8bb7b1ef5..f2537cfba 100644
--- a/internal/test/outputoptions/disabletypealiases/types.gen.go
+++ b/internal/test/outputoptions/disabletypealiases/types.gen.go
@@ -1,6 +1,6 @@
// Package types provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package types
// Example defines model for example.
diff --git a/internal/test/outputoptions/name-normalizer/spec.yaml b/internal/test/outputoptions/name-normalizer/spec.yaml
new file mode 100644
index 000000000..524ecb70a
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/spec.yaml
@@ -0,0 +1,64 @@
+openapi: "3.0.0"
+info:
+ version: 1.0.0
+ title: Example code for the `name-normalizer` output option
+paths:
+ /api/pets/{petId}:
+ get:
+ summary: Get pet given identifier.
+ operationId: getHttpPet
+ parameters:
+ - name: petId
+ in: path
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: valid pet
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet'
+components:
+ schemas:
+ Pet:
+ type: object
+ required:
+ - uuid
+ - name
+ properties:
+ uuid:
+ type: string
+ description: The pet uuid.
+ name:
+ type: string
+ description: The name of the pet.
+ Error:
+ required:
+ - code
+ - message
+ properties:
+ code:
+ type: integer
+ format: int32
+ description: Error code
+ message:
+ type: string
+ description: Error message
+ OneOf2things:
+ description: "Notice that the `things` is not capitalised"
+ oneOf:
+ - type: object
+ required:
+ - id
+ properties:
+ id:
+ type: integer
+ - type: object
+ required:
+ - id
+ properties:
+ id:
+ type: string
+ format: uuid
diff --git a/internal/test/outputoptions/name-normalizer/to-camel-case-with-digits/config.yaml b/internal/test/outputoptions/name-normalizer/to-camel-case-with-digits/config.yaml
new file mode 100644
index 000000000..59b69a9de
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/to-camel-case-with-digits/config.yaml
@@ -0,0 +1,11 @@
+# yaml-language-server: $schema=../../../../../configuration-schema.json
+package: tocamelcasewithdigits
+generate:
+ gorilla-server: true
+ client: true
+ models: true
+ embedded-spec: true
+output: name_normalizer.gen.go
+output-options:
+ skip-prune: true
+ name-normalizer: ToCamelCaseWithDigits
diff --git a/internal/test/outputoptions/name-normalizer/to-camel-case-with-digits/generate.go b/internal/test/outputoptions/name-normalizer/to-camel-case-with-digits/generate.go
new file mode 100644
index 000000000..4b4d2e44e
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/to-camel-case-with-digits/generate.go
@@ -0,0 +1,3 @@
+package tocamelcasewithdigits
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../spec.yaml
diff --git a/internal/test/outputoptions/name-normalizer/to-camel-case-with-digits/name_normalizer.gen.go b/internal/test/outputoptions/name-normalizer/to-camel-case-with-digits/name_normalizer.gen.go
new file mode 100644
index 000000000..8c8853d6f
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/to-camel-case-with-digits/name_normalizer.gen.go
@@ -0,0 +1,591 @@
+// Package tocamelcasewithdigits provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package tocamelcasewithdigits
+
+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/gorilla/mux"
+ "github.com/oapi-codegen/runtime"
+ openapi_types "github.com/oapi-codegen/runtime/types"
+)
+
+// Error defines model for Error.
+type Error struct {
+ // Code Error code
+ Code int32 `json:"code"`
+
+ // Message Error message
+ Message string `json:"message"`
+}
+
+// OneOf2Things Notice that the `things` is not capitalised
+type OneOf2Things struct {
+ union json.RawMessage
+}
+
+// OneOf2Things0 defines model for .
+type OneOf2Things0 struct {
+ Id int `json:"id"`
+}
+
+// OneOf2Things1 defines model for .
+type OneOf2Things1 struct {
+ Id openapi_types.UUID `json:"id"`
+}
+
+// Pet defines model for Pet.
+type Pet struct {
+ // Name The name of the pet.
+ Name string `json:"name"`
+
+ // Uuid The pet uuid.
+ Uuid string `json:"uuid"`
+}
+
+// AsOneOf2Things0 returns the union data inside the OneOf2Things as a OneOf2Things0
+func (t OneOf2Things) AsOneOf2Things0() (OneOf2Things0, error) {
+ var body OneOf2Things0
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromOneOf2Things0 overwrites any union data inside the OneOf2Things as the provided OneOf2Things0
+func (t *OneOf2Things) FromOneOf2Things0(v OneOf2Things0) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeOneOf2Things0 performs a merge with any union data inside the OneOf2Things, using the provided OneOf2Things0
+func (t *OneOf2Things) MergeOneOf2Things0(v OneOf2Things0) error {
+ b, err := json.Marshal(v)
+ if err != nil {
+ return err
+ }
+
+ merged, err := runtime.JSONMerge(t.union, b)
+ t.union = merged
+ return err
+}
+
+// AsOneOf2Things1 returns the union data inside the OneOf2Things as a OneOf2Things1
+func (t OneOf2Things) AsOneOf2Things1() (OneOf2Things1, error) {
+ var body OneOf2Things1
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromOneOf2Things1 overwrites any union data inside the OneOf2Things as the provided OneOf2Things1
+func (t *OneOf2Things) FromOneOf2Things1(v OneOf2Things1) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeOneOf2Things1 performs a merge with any union data inside the OneOf2Things, using the provided OneOf2Things1
+func (t *OneOf2Things) MergeOneOf2Things1(v OneOf2Things1) 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 OneOf2Things) MarshalJSON() ([]byte, error) {
+ b, err := t.union.MarshalJSON()
+ return b, err
+}
+
+func (t *OneOf2Things) UnmarshalJSON(b []byte) error {
+ err := t.union.UnmarshalJSON(b)
+ return err
+}
+
+// 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 {
+ // GetHttpPet request
+ GetHttpPet(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+func (c *Client) GetHttpPet(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewGetHttpPetRequest(c.Server, petId)
+ 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)
+}
+
+// NewGetHttpPetRequest generates requests for GetHttpPet
+func NewGetHttpPetRequest(server string, petId string) (*http.Request, error) {
+ var err error
+
+ var pathParam0 string
+
+ pathParam0, err = runtime.StyleParamWithLocation("simple", false, "petId", runtime.ParamLocationPath, petId)
+ if err != nil {
+ return nil, err
+ }
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/api/pets/%s", pathParam0)
+ 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 {
+ // GetHttpPetWithResponse request
+ GetHttpPetWithResponse(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*GetHttpPetResponse, error)
+}
+
+type GetHttpPetResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *Pet
+}
+
+// Status returns HTTPResponse.Status
+func (r GetHttpPetResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r GetHttpPetResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+// GetHttpPetWithResponse request returning *GetHttpPetResponse
+func (c *ClientWithResponses) GetHttpPetWithResponse(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*GetHttpPetResponse, error) {
+ rsp, err := c.GetHttpPet(ctx, petId, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParseGetHttpPetResponse(rsp)
+}
+
+// ParseGetHttpPetResponse parses an HTTP response from a GetHttpPetWithResponse call
+func ParseGetHttpPetResponse(rsp *http.Response) (*GetHttpPetResponse, error) {
+ bodyBytes, err := io.ReadAll(rsp.Body)
+ defer func() { _ = rsp.Body.Close() }()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &GetHttpPetResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest Pet
+ 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 pet given identifier.
+ // (GET /api/pets/{petId})
+ GetHttpPet(w http.ResponseWriter, r *http.Request, petId string)
+}
+
+// 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
+
+// GetHttpPet operation middleware
+func (siw *ServerInterfaceWrapper) GetHttpPet(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ var err error
+
+ // ------------- Path parameter "petId" -------------
+ var petId string
+
+ err = runtime.BindStyledParameterWithOptions("simple", "petId", mux.Vars(r)["petId"], &petId, runtime.BindStyledParameterOptions{Explode: false, Required: true})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "petId", Err: err})
+ return
+ }
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.GetHttpPet(w, r, petId)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+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, GorillaServerOptions{})
+}
+
+type GorillaServerOptions struct {
+ BaseURL string
+ BaseRouter *mux.Router
+ 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, r *mux.Router) http.Handler {
+ return HandlerWithOptions(si, GorillaServerOptions{
+ BaseRouter: r,
+ })
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, r *mux.Router, baseURL string) http.Handler {
+ return HandlerWithOptions(si, GorillaServerOptions{
+ BaseURL: baseURL,
+ BaseRouter: r,
+ })
+}
+
+// HandlerWithOptions creates http.Handler with additional options
+func HandlerWithOptions(si ServerInterface, options GorillaServerOptions) http.Handler {
+ r := options.BaseRouter
+
+ if r == nil {
+ r = mux.NewRouter()
+ }
+ 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,
+ }
+
+ r.HandleFunc(options.BaseURL+"/api/pets/{petId}", wrapper.GetHttpPet).Methods("GET")
+
+ return r
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+ "H4sIAAAAAAAC/4RTzY7TMBB+FWvgaJLSveW+gr2wHLitKtXEk2RWiW3sScVS5d3R2G0pbVe9tI5n/Pn7",
+ "8eyh9VPwDh0naPaQ2gEnk5ePMfooixB9wMiEebv1FuXfYmojBSbvoCnNKtc0dD5OhqEBcvywBg38FrB8",
+ "Yo8RFg0TpmT6d4GO5dPRxJFcD8uiIeKvmSJaaF7gcOGxfbNoeHb43K15INena/hvnqlFxYNhxQOqbWnc",
+ "KkrKeVatCcRmpIQWNHjBgubl0gOy8nup6oIbWdic+Pufr9gyLPo21MmxeSZ7V/VNZNH+Hfk6MGemGz7/",
+ "GFBJRfkuGxGQq+uLdSF083RAVlKt7vI9iMpErolLN7nOZ0uJR6k9/jZTGDE/KNX5WLISgE9OrBrpD8at",
+ "8jOHmZUvtDTsMKZC8HO1qlbC3wd0JhA08JC3NATDQzamNoHqgJzqfUB+sots9sVCMdAI6pOFBr4gf2UO",
+ "Yq+cj2ZCxpjyyyC5TjCPChvIaHDuAccZ9WG4zp7Oya+NNKfgXSqZrVerMmuO0WVCJoSR2kypfk2icX+G",
+ "9zFiBw18qP9Nc30Y5VpYZ5P/j3BnRrISYo4rzdNk4lvRmqPtaYdOkUXH1BHGSkCWvwEAAP//D5F1qDAE",
+ "AAA=",
+}
+
+// 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/outputoptions/name-normalizer/to-camel-case-with-digits/name_normalizer_test.go b/internal/test/outputoptions/name-normalizer/to-camel-case-with-digits/name_normalizer_test.go
new file mode 100644
index 000000000..32a01436e
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/to-camel-case-with-digits/name_normalizer_test.go
@@ -0,0 +1,24 @@
+package tocamelcasewithdigits
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGenCodeHasCorrectNames(t *testing.T) {
+ pet := &Pet{}
+ assert.Equal(t, "", pet.Name)
+ assert.Equal(t, "", pet.Uuid)
+
+ uri := "https://my-api.com/some-base-url/v1/"
+ client, err := NewClient(uri)
+ assert.Nil(t, err)
+ assert.NotNil(t, client.GetHttpPet)
+
+ server := &ServerInterfaceWrapper{}
+ assert.NotNil(t, server.GetHttpPet)
+
+ oneOf := OneOf2Things{}
+ assert.Zero(t, oneOf)
+}
diff --git a/internal/test/outputoptions/name-normalizer/to-camel-case-with-initialisms/config.yaml b/internal/test/outputoptions/name-normalizer/to-camel-case-with-initialisms/config.yaml
new file mode 100644
index 000000000..63e903aea
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/to-camel-case-with-initialisms/config.yaml
@@ -0,0 +1,11 @@
+# yaml-language-server: $schema=../../../../../configuration-schema.json
+package: tocamelcasewithinitialisms
+generate:
+ gorilla-server: true
+ client: true
+ models: true
+ embedded-spec: true
+output: name_normalizer.gen.go
+output-options:
+ skip-prune: true
+ name-normalizer: ToCamelCaseWithInitialisms
diff --git a/internal/test/outputoptions/name-normalizer/to-camel-case-with-initialisms/generate.go b/internal/test/outputoptions/name-normalizer/to-camel-case-with-initialisms/generate.go
new file mode 100644
index 000000000..5f6549131
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/to-camel-case-with-initialisms/generate.go
@@ -0,0 +1,3 @@
+package tocamelcasewithinitialisms
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../spec.yaml
diff --git a/internal/test/outputoptions/name-normalizer/to-camel-case-with-initialisms/name_normalizer.gen.go b/internal/test/outputoptions/name-normalizer/to-camel-case-with-initialisms/name_normalizer.gen.go
new file mode 100644
index 000000000..fc1286b8a
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/to-camel-case-with-initialisms/name_normalizer.gen.go
@@ -0,0 +1,591 @@
+// Package tocamelcasewithinitialisms provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package tocamelcasewithinitialisms
+
+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/gorilla/mux"
+ "github.com/oapi-codegen/runtime"
+ openapi_types "github.com/oapi-codegen/runtime/types"
+)
+
+// Error defines model for Error.
+type Error struct {
+ // Code Error code
+ Code int32 `json:"code"`
+
+ // Message Error message
+ Message string `json:"message"`
+}
+
+// OneOf2Things Notice that the `things` is not capitalised
+type OneOf2Things struct {
+ union json.RawMessage
+}
+
+// OneOf2Things0 defines model for .
+type OneOf2Things0 struct {
+ ID int `json:"id"`
+}
+
+// OneOf2Things1 defines model for .
+type OneOf2Things1 struct {
+ ID openapi_types.UUID `json:"id"`
+}
+
+// Pet defines model for Pet.
+type Pet struct {
+ // Name The name of the pet.
+ Name string `json:"name"`
+
+ // UUID The pet uuid.
+ UUID string `json:"uuid"`
+}
+
+// AsOneOf2Things0 returns the union data inside the OneOf2Things as a OneOf2Things0
+func (t OneOf2Things) AsOneOf2Things0() (OneOf2Things0, error) {
+ var body OneOf2Things0
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromOneOf2Things0 overwrites any union data inside the OneOf2Things as the provided OneOf2Things0
+func (t *OneOf2Things) FromOneOf2Things0(v OneOf2Things0) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeOneOf2Things0 performs a merge with any union data inside the OneOf2Things, using the provided OneOf2Things0
+func (t *OneOf2Things) MergeOneOf2Things0(v OneOf2Things0) error {
+ b, err := json.Marshal(v)
+ if err != nil {
+ return err
+ }
+
+ merged, err := runtime.JSONMerge(t.union, b)
+ t.union = merged
+ return err
+}
+
+// AsOneOf2Things1 returns the union data inside the OneOf2Things as a OneOf2Things1
+func (t OneOf2Things) AsOneOf2Things1() (OneOf2Things1, error) {
+ var body OneOf2Things1
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromOneOf2Things1 overwrites any union data inside the OneOf2Things as the provided OneOf2Things1
+func (t *OneOf2Things) FromOneOf2Things1(v OneOf2Things1) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeOneOf2Things1 performs a merge with any union data inside the OneOf2Things, using the provided OneOf2Things1
+func (t *OneOf2Things) MergeOneOf2Things1(v OneOf2Things1) 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 OneOf2Things) MarshalJSON() ([]byte, error) {
+ b, err := t.union.MarshalJSON()
+ return b, err
+}
+
+func (t *OneOf2Things) UnmarshalJSON(b []byte) error {
+ err := t.union.UnmarshalJSON(b)
+ return err
+}
+
+// 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 {
+ // GetHTTPPet request
+ GetHTTPPet(ctx context.Context, petID string, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+func (c *Client) GetHTTPPet(ctx context.Context, petID string, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewGetHTTPPetRequest(c.Server, petID)
+ 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)
+}
+
+// NewGetHTTPPetRequest generates requests for GetHTTPPet
+func NewGetHTTPPetRequest(server string, petID string) (*http.Request, error) {
+ var err error
+
+ var pathParam0 string
+
+ pathParam0, err = runtime.StyleParamWithLocation("simple", false, "petId", runtime.ParamLocationPath, petID)
+ if err != nil {
+ return nil, err
+ }
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/api/pets/%s", pathParam0)
+ 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 {
+ // GetHTTPPetWithResponse request
+ GetHTTPPetWithResponse(ctx context.Context, petID string, reqEditors ...RequestEditorFn) (*GetHTTPPetResponse, error)
+}
+
+type GetHTTPPetResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *Pet
+}
+
+// Status returns HTTPResponse.Status
+func (r GetHTTPPetResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r GetHTTPPetResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+// GetHTTPPetWithResponse request returning *GetHTTPPetResponse
+func (c *ClientWithResponses) GetHTTPPetWithResponse(ctx context.Context, petID string, reqEditors ...RequestEditorFn) (*GetHTTPPetResponse, error) {
+ rsp, err := c.GetHTTPPet(ctx, petID, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParseGetHTTPPetResponse(rsp)
+}
+
+// ParseGetHTTPPetResponse parses an HTTP response from a GetHTTPPetWithResponse call
+func ParseGetHTTPPetResponse(rsp *http.Response) (*GetHTTPPetResponse, error) {
+ bodyBytes, err := io.ReadAll(rsp.Body)
+ defer func() { _ = rsp.Body.Close() }()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &GetHTTPPetResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest Pet
+ 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 pet given identifier.
+ // (GET /api/pets/{petId})
+ GetHTTPPet(w http.ResponseWriter, r *http.Request, petID string)
+}
+
+// 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
+
+// GetHTTPPet operation middleware
+func (siw *ServerInterfaceWrapper) GetHTTPPet(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ var err error
+
+ // ------------- Path parameter "petId" -------------
+ var petID string
+
+ err = runtime.BindStyledParameterWithOptions("simple", "petId", mux.Vars(r)["petId"], &petID, runtime.BindStyledParameterOptions{Explode: false, Required: true})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "petId", Err: err})
+ return
+ }
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.GetHTTPPet(w, r, petID)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+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, GorillaServerOptions{})
+}
+
+type GorillaServerOptions struct {
+ BaseURL string
+ BaseRouter *mux.Router
+ 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, r *mux.Router) http.Handler {
+ return HandlerWithOptions(si, GorillaServerOptions{
+ BaseRouter: r,
+ })
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, r *mux.Router, baseURL string) http.Handler {
+ return HandlerWithOptions(si, GorillaServerOptions{
+ BaseURL: baseURL,
+ BaseRouter: r,
+ })
+}
+
+// HandlerWithOptions creates http.Handler with additional options
+func HandlerWithOptions(si ServerInterface, options GorillaServerOptions) http.Handler {
+ r := options.BaseRouter
+
+ if r == nil {
+ r = mux.NewRouter()
+ }
+ 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,
+ }
+
+ r.HandleFunc(options.BaseURL+"/api/pets/{petId}", wrapper.GetHTTPPet).Methods("GET")
+
+ return r
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+ "H4sIAAAAAAAC/4RTTW/bPAz+KwLf96jZWXrzvdh6WXvIrQgQzaJtFrakSXSwLvB/HyglWZZk6CWRRerR",
+ "8yEeoPVT8A4dJ2gOkNoBJ5OXjzH6KIsQfcDIhHm79Rbl32JqIwUm76ApzSrXNHQ+ToahAXL8sAYN/B6w",
+ "fGKPERYNE6Zk+n8Cncrno4kjuR6WRUPEHzNFtNC8wvHCU/t20fDs8Llb80CuT7fw3zxTi4oHw4oHVLvS",
+ "uFOUlPOsWhOIzUgJLWjwggXN67UHZOX3WtUVN7KwPfP339+wZVj0faizY/NM9kPVd5FF+wvybWDOTHd8",
+ "3gyopKJ8l40IyNXtxboQuns6ICupVh/yPYrKRG6JSze5zmdLiUepPf40UxgxPyjV+ViyEoBPTqwa6RfG",
+ "nfIzh5mVL7Q07DGmQvBztapWwt8HdCYQNPCQtzQEw0M2pjaB6oCc6kNAfrKLbPbFQjHQCOqThQa+IH/d",
+ "bF7EXjkfzYSMMeWXQXKdYJ4UNpDR4NIDjjPq43BdPJ2zX1tpTsG7VDJbr1Zl1hyjy4RMCCO1mVL9lkTj",
+ "4QLv/4gdNPBf/Wea6+Mo18I6m/x3hHszkpUQc1xpniYT34vWHG1Pe3SKLDqmjjBWArL8DgAA//+VcR3v",
+ "MAQAAA==",
+}
+
+// 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/outputoptions/name-normalizer/to-camel-case-with-initialisms/name_normalizer_test.go b/internal/test/outputoptions/name-normalizer/to-camel-case-with-initialisms/name_normalizer_test.go
new file mode 100644
index 000000000..fea7b84dc
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/to-camel-case-with-initialisms/name_normalizer_test.go
@@ -0,0 +1,24 @@
+package tocamelcasewithinitialisms
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGenCodeHasCorrectNames(t *testing.T) {
+ pet := &Pet{}
+ assert.Equal(t, "", pet.Name)
+ assert.Equal(t, "", pet.UUID)
+
+ uri := "https://my-api.com/some-base-url/v1/"
+ client, err := NewClient(uri)
+ assert.Nil(t, err)
+ assert.NotNil(t, client.GetHTTPPet)
+
+ server := &ServerInterfaceWrapper{}
+ assert.NotNil(t, server.GetHTTPPet)
+
+ oneOf := OneOf2Things{}
+ assert.Zero(t, oneOf)
+}
diff --git a/internal/test/outputoptions/name-normalizer/to-camel-case/config.yaml b/internal/test/outputoptions/name-normalizer/to-camel-case/config.yaml
new file mode 100644
index 000000000..b80cdda8e
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/to-camel-case/config.yaml
@@ -0,0 +1,11 @@
+# yaml-language-server: $schema=../../../../../configuration-schema.json
+package: tocamelcase
+generate:
+ gorilla-server: true
+ client: true
+ models: true
+ embedded-spec: true
+output: name_normalizer.gen.go
+output-options:
+ skip-prune: true
+ name-normalizer: ToCamelCase
diff --git a/internal/test/outputoptions/name-normalizer/to-camel-case/generate.go b/internal/test/outputoptions/name-normalizer/to-camel-case/generate.go
new file mode 100644
index 000000000..a6c179b79
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/to-camel-case/generate.go
@@ -0,0 +1,3 @@
+package tocamelcase
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../spec.yaml
diff --git a/internal/test/outputoptions/name-normalizer/to-camel-case/name_normalizer.gen.go b/internal/test/outputoptions/name-normalizer/to-camel-case/name_normalizer.gen.go
new file mode 100644
index 000000000..449d9e45e
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/to-camel-case/name_normalizer.gen.go
@@ -0,0 +1,591 @@
+// Package tocamelcase provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package tocamelcase
+
+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/gorilla/mux"
+ "github.com/oapi-codegen/runtime"
+ openapi_types "github.com/oapi-codegen/runtime/types"
+)
+
+// Error defines model for Error.
+type Error struct {
+ // Code Error code
+ Code int32 `json:"code"`
+
+ // Message Error message
+ Message string `json:"message"`
+}
+
+// OneOf2things Notice that the `things` is not capitalised
+type OneOf2things struct {
+ union json.RawMessage
+}
+
+// OneOf2things0 defines model for .
+type OneOf2things0 struct {
+ Id int `json:"id"`
+}
+
+// OneOf2things1 defines model for .
+type OneOf2things1 struct {
+ Id openapi_types.UUID `json:"id"`
+}
+
+// Pet defines model for Pet.
+type Pet struct {
+ // Name The name of the pet.
+ Name string `json:"name"`
+
+ // Uuid The pet uuid.
+ Uuid string `json:"uuid"`
+}
+
+// AsOneOf2things0 returns the union data inside the OneOf2things as a OneOf2things0
+func (t OneOf2things) AsOneOf2things0() (OneOf2things0, error) {
+ var body OneOf2things0
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromOneOf2things0 overwrites any union data inside the OneOf2things as the provided OneOf2things0
+func (t *OneOf2things) FromOneOf2things0(v OneOf2things0) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeOneOf2things0 performs a merge with any union data inside the OneOf2things, using the provided OneOf2things0
+func (t *OneOf2things) MergeOneOf2things0(v OneOf2things0) error {
+ b, err := json.Marshal(v)
+ if err != nil {
+ return err
+ }
+
+ merged, err := runtime.JSONMerge(t.union, b)
+ t.union = merged
+ return err
+}
+
+// AsOneOf2things1 returns the union data inside the OneOf2things as a OneOf2things1
+func (t OneOf2things) AsOneOf2things1() (OneOf2things1, error) {
+ var body OneOf2things1
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromOneOf2things1 overwrites any union data inside the OneOf2things as the provided OneOf2things1
+func (t *OneOf2things) FromOneOf2things1(v OneOf2things1) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeOneOf2things1 performs a merge with any union data inside the OneOf2things, using the provided OneOf2things1
+func (t *OneOf2things) MergeOneOf2things1(v OneOf2things1) 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 OneOf2things) MarshalJSON() ([]byte, error) {
+ b, err := t.union.MarshalJSON()
+ return b, err
+}
+
+func (t *OneOf2things) UnmarshalJSON(b []byte) error {
+ err := t.union.UnmarshalJSON(b)
+ return err
+}
+
+// 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 {
+ // GetHttpPet request
+ GetHttpPet(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+func (c *Client) GetHttpPet(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewGetHttpPetRequest(c.Server, petId)
+ 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)
+}
+
+// NewGetHttpPetRequest generates requests for GetHttpPet
+func NewGetHttpPetRequest(server string, petId string) (*http.Request, error) {
+ var err error
+
+ var pathParam0 string
+
+ pathParam0, err = runtime.StyleParamWithLocation("simple", false, "petId", runtime.ParamLocationPath, petId)
+ if err != nil {
+ return nil, err
+ }
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/api/pets/%s", pathParam0)
+ 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 {
+ // GetHttpPetWithResponse request
+ GetHttpPetWithResponse(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*GetHttpPetResponse, error)
+}
+
+type GetHttpPetResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *Pet
+}
+
+// Status returns HTTPResponse.Status
+func (r GetHttpPetResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r GetHttpPetResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+// GetHttpPetWithResponse request returning *GetHttpPetResponse
+func (c *ClientWithResponses) GetHttpPetWithResponse(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*GetHttpPetResponse, error) {
+ rsp, err := c.GetHttpPet(ctx, petId, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParseGetHttpPetResponse(rsp)
+}
+
+// ParseGetHttpPetResponse parses an HTTP response from a GetHttpPetWithResponse call
+func ParseGetHttpPetResponse(rsp *http.Response) (*GetHttpPetResponse, error) {
+ bodyBytes, err := io.ReadAll(rsp.Body)
+ defer func() { _ = rsp.Body.Close() }()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &GetHttpPetResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest Pet
+ 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 pet given identifier.
+ // (GET /api/pets/{petId})
+ GetHttpPet(w http.ResponseWriter, r *http.Request, petId string)
+}
+
+// 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
+
+// GetHttpPet operation middleware
+func (siw *ServerInterfaceWrapper) GetHttpPet(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ var err error
+
+ // ------------- Path parameter "petId" -------------
+ var petId string
+
+ err = runtime.BindStyledParameterWithOptions("simple", "petId", mux.Vars(r)["petId"], &petId, runtime.BindStyledParameterOptions{Explode: false, Required: true})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "petId", Err: err})
+ return
+ }
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.GetHttpPet(w, r, petId)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+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, GorillaServerOptions{})
+}
+
+type GorillaServerOptions struct {
+ BaseURL string
+ BaseRouter *mux.Router
+ 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, r *mux.Router) http.Handler {
+ return HandlerWithOptions(si, GorillaServerOptions{
+ BaseRouter: r,
+ })
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, r *mux.Router, baseURL string) http.Handler {
+ return HandlerWithOptions(si, GorillaServerOptions{
+ BaseURL: baseURL,
+ BaseRouter: r,
+ })
+}
+
+// HandlerWithOptions creates http.Handler with additional options
+func HandlerWithOptions(si ServerInterface, options GorillaServerOptions) http.Handler {
+ r := options.BaseRouter
+
+ if r == nil {
+ r = mux.NewRouter()
+ }
+ 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,
+ }
+
+ r.HandleFunc(options.BaseURL+"/api/pets/{petId}", wrapper.GetHttpPet).Methods("GET")
+
+ return r
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+ "H4sIAAAAAAAC/4RTzY7TMBB+FWvgaJLSveW+gr2wHLitKtXEk2RWiW3sScVS5d3R2G0pbVe9tI5n/Pn7",
+ "8eyh9VPwDh0naPaQ2gEnk5ePMfooixB9wMiEebv1FuXfYmojBSbvoCnNKtc0dD5OhqEBcvywBg38FrB8",
+ "Yo8RFg0TpmT6d4GO5dPRxJFcD8uiIeKvmSJaaF7gcOGxfbNoeHb43K15INena/hvnqlFxYNhxQOqbWnc",
+ "KkrKeVatCcRmpIQWNHjBgubl0gOy8nup6oIbWdic+Pufr9gyLPo21MmxeSZ7V/VNZNH+Hfk6MGemGz7/",
+ "GFBJRfkuGxGQq+uLdSF083RAVlKt7vI9iMpErolLN7nOZ0uJR6k9/jZTGDE/KNX5WLISgE9OrBrpD8at",
+ "8jOHmZUvtDTsMKZC8HO1qlbC3wd0JhA08JC3NATDQzamNoHqgJzqfUB+sots9sVCMdAI6pOFBr4gf2UO",
+ "Yq+cj2ZCxpjyyyC5TjCPChvIaHDuAccZ9WG4zp7Oya+NNKfgXSqZrVerMmuO0WVCJoSR2kypfk2icX+G",
+ "9zFiBw18qP9Nc30Y5VpYZ5P/j3BnRrISYo4rzdNk4lvRmqPtaYdOkUXH1BHGSkCWvwEAAP//D5F1qDAE",
+ "AAA=",
+}
+
+// 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/outputoptions/name-normalizer/to-camel-case/name_normalizer_test.go b/internal/test/outputoptions/name-normalizer/to-camel-case/name_normalizer_test.go
new file mode 100644
index 000000000..3e0d83fa8
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/to-camel-case/name_normalizer_test.go
@@ -0,0 +1,24 @@
+package tocamelcase
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGenCodeHasCorrectNames(t *testing.T) {
+ pet := &Pet{}
+ assert.Equal(t, "", pet.Name)
+ assert.Equal(t, "", pet.Uuid)
+
+ uri := "https://my-api.com/some-base-url/v1/"
+ client, err := NewClient(uri)
+ assert.Nil(t, err)
+ assert.NotNil(t, client.GetHttpPet)
+
+ server := &ServerInterfaceWrapper{}
+ assert.NotNil(t, server.GetHttpPet)
+
+ oneOf := OneOf2things{}
+ assert.Zero(t, oneOf)
+}
diff --git a/internal/test/outputoptions/name-normalizer/unset/config.yaml b/internal/test/outputoptions/name-normalizer/unset/config.yaml
new file mode 100644
index 000000000..bd2918ed5
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/unset/config.yaml
@@ -0,0 +1,11 @@
+# yaml-language-server: $schema=../../../../../configuration-schema.json
+package: unset
+generate:
+ gorilla-server: true
+ client: true
+ models: true
+ embedded-spec: true
+output: name_normalizer.gen.go
+output-options:
+ skip-prune: true
+ # When `name-normalizer` is unset
diff --git a/internal/test/outputoptions/name-normalizer/unset/generate.go b/internal/test/outputoptions/name-normalizer/unset/generate.go
new file mode 100644
index 000000000..84fac60cb
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/unset/generate.go
@@ -0,0 +1,3 @@
+package unset
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../spec.yaml
diff --git a/internal/test/outputoptions/name-normalizer/unset/name_normalizer.gen.go b/internal/test/outputoptions/name-normalizer/unset/name_normalizer.gen.go
new file mode 100644
index 000000000..ac6f4c896
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/unset/name_normalizer.gen.go
@@ -0,0 +1,591 @@
+// Package unset provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package unset
+
+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/gorilla/mux"
+ "github.com/oapi-codegen/runtime"
+ openapi_types "github.com/oapi-codegen/runtime/types"
+)
+
+// Error defines model for Error.
+type Error struct {
+ // Code Error code
+ Code int32 `json:"code"`
+
+ // Message Error message
+ Message string `json:"message"`
+}
+
+// OneOf2things Notice that the `things` is not capitalised
+type OneOf2things struct {
+ union json.RawMessage
+}
+
+// OneOf2things0 defines model for .
+type OneOf2things0 struct {
+ Id int `json:"id"`
+}
+
+// OneOf2things1 defines model for .
+type OneOf2things1 struct {
+ Id openapi_types.UUID `json:"id"`
+}
+
+// Pet defines model for Pet.
+type Pet struct {
+ // Name The name of the pet.
+ Name string `json:"name"`
+
+ // Uuid The pet uuid.
+ Uuid string `json:"uuid"`
+}
+
+// AsOneOf2things0 returns the union data inside the OneOf2things as a OneOf2things0
+func (t OneOf2things) AsOneOf2things0() (OneOf2things0, error) {
+ var body OneOf2things0
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromOneOf2things0 overwrites any union data inside the OneOf2things as the provided OneOf2things0
+func (t *OneOf2things) FromOneOf2things0(v OneOf2things0) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeOneOf2things0 performs a merge with any union data inside the OneOf2things, using the provided OneOf2things0
+func (t *OneOf2things) MergeOneOf2things0(v OneOf2things0) error {
+ b, err := json.Marshal(v)
+ if err != nil {
+ return err
+ }
+
+ merged, err := runtime.JSONMerge(t.union, b)
+ t.union = merged
+ return err
+}
+
+// AsOneOf2things1 returns the union data inside the OneOf2things as a OneOf2things1
+func (t OneOf2things) AsOneOf2things1() (OneOf2things1, error) {
+ var body OneOf2things1
+ err := json.Unmarshal(t.union, &body)
+ return body, err
+}
+
+// FromOneOf2things1 overwrites any union data inside the OneOf2things as the provided OneOf2things1
+func (t *OneOf2things) FromOneOf2things1(v OneOf2things1) error {
+ b, err := json.Marshal(v)
+ t.union = b
+ return err
+}
+
+// MergeOneOf2things1 performs a merge with any union data inside the OneOf2things, using the provided OneOf2things1
+func (t *OneOf2things) MergeOneOf2things1(v OneOf2things1) 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 OneOf2things) MarshalJSON() ([]byte, error) {
+ b, err := t.union.MarshalJSON()
+ return b, err
+}
+
+func (t *OneOf2things) UnmarshalJSON(b []byte) error {
+ err := t.union.UnmarshalJSON(b)
+ return err
+}
+
+// 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 {
+ // GetHttpPet request
+ GetHttpPet(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+func (c *Client) GetHttpPet(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewGetHttpPetRequest(c.Server, petId)
+ 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)
+}
+
+// NewGetHttpPetRequest generates requests for GetHttpPet
+func NewGetHttpPetRequest(server string, petId string) (*http.Request, error) {
+ var err error
+
+ var pathParam0 string
+
+ pathParam0, err = runtime.StyleParamWithLocation("simple", false, "petId", runtime.ParamLocationPath, petId)
+ if err != nil {
+ return nil, err
+ }
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/api/pets/%s", pathParam0)
+ 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 {
+ // GetHttpPetWithResponse request
+ GetHttpPetWithResponse(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*GetHttpPetResponse, error)
+}
+
+type GetHttpPetResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *Pet
+}
+
+// Status returns HTTPResponse.Status
+func (r GetHttpPetResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r GetHttpPetResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+// GetHttpPetWithResponse request returning *GetHttpPetResponse
+func (c *ClientWithResponses) GetHttpPetWithResponse(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*GetHttpPetResponse, error) {
+ rsp, err := c.GetHttpPet(ctx, petId, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParseGetHttpPetResponse(rsp)
+}
+
+// ParseGetHttpPetResponse parses an HTTP response from a GetHttpPetWithResponse call
+func ParseGetHttpPetResponse(rsp *http.Response) (*GetHttpPetResponse, error) {
+ bodyBytes, err := io.ReadAll(rsp.Body)
+ defer func() { _ = rsp.Body.Close() }()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &GetHttpPetResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest Pet
+ 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 pet given identifier.
+ // (GET /api/pets/{petId})
+ GetHttpPet(w http.ResponseWriter, r *http.Request, petId string)
+}
+
+// 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
+
+// GetHttpPet operation middleware
+func (siw *ServerInterfaceWrapper) GetHttpPet(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ var err error
+
+ // ------------- Path parameter "petId" -------------
+ var petId string
+
+ err = runtime.BindStyledParameterWithOptions("simple", "petId", mux.Vars(r)["petId"], &petId, runtime.BindStyledParameterOptions{Explode: false, Required: true})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "petId", Err: err})
+ return
+ }
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.GetHttpPet(w, r, petId)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+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, GorillaServerOptions{})
+}
+
+type GorillaServerOptions struct {
+ BaseURL string
+ BaseRouter *mux.Router
+ 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, r *mux.Router) http.Handler {
+ return HandlerWithOptions(si, GorillaServerOptions{
+ BaseRouter: r,
+ })
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, r *mux.Router, baseURL string) http.Handler {
+ return HandlerWithOptions(si, GorillaServerOptions{
+ BaseURL: baseURL,
+ BaseRouter: r,
+ })
+}
+
+// HandlerWithOptions creates http.Handler with additional options
+func HandlerWithOptions(si ServerInterface, options GorillaServerOptions) http.Handler {
+ r := options.BaseRouter
+
+ if r == nil {
+ r = mux.NewRouter()
+ }
+ 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,
+ }
+
+ r.HandleFunc(options.BaseURL+"/api/pets/{petId}", wrapper.GetHttpPet).Methods("GET")
+
+ return r
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+ "H4sIAAAAAAAC/4RTzY7TMBB+FWvgaJLSveW+gr2wHLitKtXEk2RWiW3sScVS5d3R2G0pbVe9tI5n/Pn7",
+ "8eyh9VPwDh0naPaQ2gEnk5ePMfooixB9wMiEebv1FuXfYmojBSbvoCnNKtc0dD5OhqEBcvywBg38FrB8",
+ "Yo8RFg0TpmT6d4GO5dPRxJFcD8uiIeKvmSJaaF7gcOGxfbNoeHb43K15INena/hvnqlFxYNhxQOqbWnc",
+ "KkrKeVatCcRmpIQWNHjBgubl0gOy8nup6oIbWdic+Pufr9gyLPo21MmxeSZ7V/VNZNH+Hfk6MGemGz7/",
+ "GFBJRfkuGxGQq+uLdSF083RAVlKt7vI9iMpErolLN7nOZ0uJR6k9/jZTGDE/KNX5WLISgE9OrBrpD8at",
+ "8jOHmZUvtDTsMKZC8HO1qlbC3wd0JhA08JC3NATDQzamNoHqgJzqfUB+sots9sVCMdAI6pOFBr4gf2UO",
+ "Yq+cj2ZCxpjyyyC5TjCPChvIaHDuAccZ9WG4zp7Oya+NNKfgXSqZrVerMmuO0WVCJoSR2kypfk2icX+G",
+ "9zFiBw18qP9Nc30Y5VpYZ5P/j3BnRrISYo4rzdNk4lvRmqPtaYdOkUXH1BHGSkCWvwEAAP//D5F1qDAE",
+ "AAA=",
+}
+
+// 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/outputoptions/name-normalizer/unset/name_normalizer_test.go b/internal/test/outputoptions/name-normalizer/unset/name_normalizer_test.go
new file mode 100644
index 000000000..9702a59c4
--- /dev/null
+++ b/internal/test/outputoptions/name-normalizer/unset/name_normalizer_test.go
@@ -0,0 +1,24 @@
+package unset
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGenCodeHasCorrectNames(t *testing.T) {
+ pet := &Pet{}
+ assert.Equal(t, "", pet.Name)
+ assert.Equal(t, "", pet.Uuid)
+
+ uri := "https://my-api.com/some-base-url/v1/"
+ client, err := NewClient(uri)
+ assert.Nil(t, err)
+ assert.NotNil(t, client.GetHttpPet)
+
+ server := &ServerInterfaceWrapper{}
+ assert.NotNil(t, server.GetHttpPet)
+
+ oneOf := OneOf2things{}
+ assert.Zero(t, oneOf)
+}
diff --git a/internal/test/parameters/config.yaml b/internal/test/parameters/config.yaml
index 962aa2c57..64850f5de 100644
--- a/internal/test/parameters/config.yaml
+++ b/internal/test/parameters/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
package: parameters
generate:
echo-server: true
diff --git a/internal/test/parameters/doc.go b/internal/test/parameters/doc.go
index 25168f610..30d5b502e 100644
--- a/internal/test/parameters/doc.go
+++ b/internal/test/parameters/doc.go
@@ -1,3 +1,3 @@
package parameters
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml parameters.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml parameters.yaml
diff --git a/internal/test/parameters/parameters.gen.go b/internal/test/parameters/parameters.gen.go
index 1da8aae1d..630770731 100644
--- a/internal/test/parameters/parameters.gen.go
+++ b/internal/test/parameters/parameters.gen.go
@@ -1,6 +1,6 @@
// Package parameters provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package parameters
import (
diff --git a/internal/test/schemas/config.yaml b/internal/test/schemas/config.yaml
index 908695365..a054e8daf 100644
--- a/internal/test/schemas/config.yaml
+++ b/internal/test/schemas/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
package: schemas
generate:
echo-server: true
diff --git a/internal/test/schemas/doc.go b/internal/test/schemas/doc.go
index f743377e5..a4147ee5a 100644
--- a/internal/test/schemas/doc.go
+++ b/internal/test/schemas/doc.go
@@ -1,3 +1,3 @@
package schemas
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml schemas.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml schemas.yaml
diff --git a/internal/test/schemas/schemas.gen.go b/internal/test/schemas/schemas.gen.go
index 12c629868..09efa4a01 100644
--- a/internal/test/schemas/schemas.gen.go
+++ b/internal/test/schemas/schemas.gen.go
@@ -1,6 +1,6 @@
// Package schemas provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package schemas
import (
diff --git a/internal/test/server/config.yaml b/internal/test/server/config.yaml
index 729401be7..4e8702b1f 100644
--- a/internal/test/server/config.yaml
+++ b/internal/test/server/config.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../configuration-schema.json
package: server
generate:
chi-server: true
diff --git a/internal/test/server/doc.go b/internal/test/server/doc.go
index a766b30b8..f46abed62 100644
--- a/internal/test/server/doc.go
+++ b/internal/test/server/doc.go
@@ -1,3 +1,3 @@
package server
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../test-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../test-schema.yaml
diff --git a/internal/test/server/server.gen.go b/internal/test/server/server.gen.go
index 0620e64c8..cfc75b65c 100644
--- a/internal/test/server/server.gen.go
+++ b/internal/test/server/server.gen.go
@@ -1,6 +1,6 @@
// Package server provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package server
import (
diff --git a/internal/test/strict-server/chi/server.cfg.yaml b/internal/test/strict-server/chi/server.cfg.yaml
index ca1c62c3c..35425d6ec 100644
--- a/internal/test/strict-server/chi/server.cfg.yaml
+++ b/internal/test/strict-server/chi/server.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
chi-server: true
diff --git a/internal/test/strict-server/chi/server.gen.go b/internal/test/strict-server/chi/server.gen.go
index c0579f98b..5725eb145 100644
--- a/internal/test/strict-server/chi/server.gen.go
+++ b/internal/test/strict-server/chi/server.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/internal/test/strict-server/chi/server.go b/internal/test/strict-server/chi/server.go
index fe744e250..c135a2a44 100644
--- a/internal/test/strict-server/chi/server.go
+++ b/internal/test/strict-server/chi/server.go
@@ -1,5 +1,5 @@
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
package api
diff --git a/internal/test/strict-server/chi/types.cfg.yaml b/internal/test/strict-server/chi/types.cfg.yaml
index 4ea1d8aa5..2ed9740ea 100644
--- a/internal/test/strict-server/chi/types.cfg.yaml
+++ b/internal/test/strict-server/chi/types.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
models: true
diff --git a/internal/test/strict-server/chi/types.gen.go b/internal/test/strict-server/chi/types.gen.go
index c16705f32..6682c1aca 100644
--- a/internal/test/strict-server/chi/types.gen.go
+++ b/internal/test/strict-server/chi/types.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
// Example defines model for example.
diff --git a/internal/test/strict-server/client/client.cfg.yaml b/internal/test/strict-server/client/client.cfg.yaml
index 637450eaa..8437bde14 100644
--- a/internal/test/strict-server/client/client.cfg.yaml
+++ b/internal/test/strict-server/client/client.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
models: true
diff --git a/internal/test/strict-server/client/client.gen.go b/internal/test/strict-server/client/client.gen.go
index 16e588bd6..e7959520e 100644
--- a/internal/test/strict-server/client/client.gen.go
+++ b/internal/test/strict-server/client/client.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/internal/test/strict-server/client/client.go b/internal/test/strict-server/client/client.go
index 51214137c..5b350a488 100644
--- a/internal/test/strict-server/client/client.go
+++ b/internal/test/strict-server/client/client.go
@@ -1,3 +1,3 @@
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=client.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=client.cfg.yaml ../strict-schema.yaml
package api
diff --git a/internal/test/strict-server/echo/server.cfg.yaml b/internal/test/strict-server/echo/server.cfg.yaml
index 3c3c5c9c5..143f57f07 100644
--- a/internal/test/strict-server/echo/server.cfg.yaml
+++ b/internal/test/strict-server/echo/server.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
echo-server: true
diff --git a/internal/test/strict-server/echo/server.gen.go b/internal/test/strict-server/echo/server.gen.go
index 8c5205262..f07dfa5e4 100644
--- a/internal/test/strict-server/echo/server.gen.go
+++ b/internal/test/strict-server/echo/server.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/internal/test/strict-server/echo/server.go b/internal/test/strict-server/echo/server.go
index fe744e250..c135a2a44 100644
--- a/internal/test/strict-server/echo/server.go
+++ b/internal/test/strict-server/echo/server.go
@@ -1,5 +1,5 @@
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
package api
diff --git a/internal/test/strict-server/echo/types.cfg.yaml b/internal/test/strict-server/echo/types.cfg.yaml
index 4ea1d8aa5..2ed9740ea 100644
--- a/internal/test/strict-server/echo/types.cfg.yaml
+++ b/internal/test/strict-server/echo/types.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
models: true
diff --git a/internal/test/strict-server/echo/types.gen.go b/internal/test/strict-server/echo/types.gen.go
index c16705f32..6682c1aca 100644
--- a/internal/test/strict-server/echo/types.gen.go
+++ b/internal/test/strict-server/echo/types.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
// Example defines model for example.
diff --git a/internal/test/strict-server/fiber/server.cfg.yaml b/internal/test/strict-server/fiber/server.cfg.yaml
index 3a6471261..73540ffc2 100644
--- a/internal/test/strict-server/fiber/server.cfg.yaml
+++ b/internal/test/strict-server/fiber/server.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
fiber-server: true
diff --git a/internal/test/strict-server/fiber/server.gen.go b/internal/test/strict-server/fiber/server.gen.go
index 81e8c95d0..b15d923fd 100644
--- a/internal/test/strict-server/fiber/server.gen.go
+++ b/internal/test/strict-server/fiber/server.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
@@ -206,7 +206,7 @@ func RegisterHandlersWithOptions(router fiber.Router, si ServerInterface, option
}
for _, m := range options.Middlewares {
- router.Use(m)
+ router.Use(fiber.Handler(m))
}
router.Post(options.BaseURL+"/json", wrapper.JSONExample)
diff --git a/internal/test/strict-server/fiber/server.go b/internal/test/strict-server/fiber/server.go
index fe744e250..c135a2a44 100644
--- a/internal/test/strict-server/fiber/server.go
+++ b/internal/test/strict-server/fiber/server.go
@@ -1,5 +1,5 @@
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
package api
diff --git a/internal/test/strict-server/fiber/types.cfg.yaml b/internal/test/strict-server/fiber/types.cfg.yaml
index 4ea1d8aa5..2ed9740ea 100644
--- a/internal/test/strict-server/fiber/types.cfg.yaml
+++ b/internal/test/strict-server/fiber/types.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
models: true
diff --git a/internal/test/strict-server/fiber/types.gen.go b/internal/test/strict-server/fiber/types.gen.go
index c16705f32..6682c1aca 100644
--- a/internal/test/strict-server/fiber/types.gen.go
+++ b/internal/test/strict-server/fiber/types.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
// Example defines model for example.
diff --git a/internal/test/strict-server/gin/server.cfg.yaml b/internal/test/strict-server/gin/server.cfg.yaml
index 66ffd5795..a79bf0e85 100644
--- a/internal/test/strict-server/gin/server.cfg.yaml
+++ b/internal/test/strict-server/gin/server.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
gin-server: true
diff --git a/internal/test/strict-server/gin/server.gen.go b/internal/test/strict-server/gin/server.gen.go
index 4b58ae0e6..21f9f3276 100644
--- a/internal/test/strict-server/gin/server.gen.go
+++ b/internal/test/strict-server/gin/server.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/internal/test/strict-server/gin/server.go b/internal/test/strict-server/gin/server.go
index fe744e250..c135a2a44 100644
--- a/internal/test/strict-server/gin/server.go
+++ b/internal/test/strict-server/gin/server.go
@@ -1,5 +1,5 @@
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
package api
diff --git a/internal/test/strict-server/gin/types.cfg.yaml b/internal/test/strict-server/gin/types.cfg.yaml
index 4ea1d8aa5..2ed9740ea 100644
--- a/internal/test/strict-server/gin/types.cfg.yaml
+++ b/internal/test/strict-server/gin/types.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
models: true
diff --git a/internal/test/strict-server/gin/types.gen.go b/internal/test/strict-server/gin/types.gen.go
index c16705f32..6682c1aca 100644
--- a/internal/test/strict-server/gin/types.gen.go
+++ b/internal/test/strict-server/gin/types.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
// Example defines model for example.
diff --git a/internal/test/strict-server/gorilla/server.cfg.yaml b/internal/test/strict-server/gorilla/server.cfg.yaml
index 4c40e5aee..a39491cbe 100644
--- a/internal/test/strict-server/gorilla/server.cfg.yaml
+++ b/internal/test/strict-server/gorilla/server.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
gorilla-server: true
diff --git a/internal/test/strict-server/gorilla/server.gen.go b/internal/test/strict-server/gorilla/server.gen.go
index 388da5199..07612e98f 100644
--- a/internal/test/strict-server/gorilla/server.gen.go
+++ b/internal/test/strict-server/gorilla/server.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/internal/test/strict-server/gorilla/server.go b/internal/test/strict-server/gorilla/server.go
index 83eb50339..5c5d7c9e7 100644
--- a/internal/test/strict-server/gorilla/server.go
+++ b/internal/test/strict-server/gorilla/server.go
@@ -1,5 +1,5 @@
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
package api
diff --git a/internal/test/strict-server/gorilla/types.cfg.yaml b/internal/test/strict-server/gorilla/types.cfg.yaml
index 4ea1d8aa5..2ed9740ea 100644
--- a/internal/test/strict-server/gorilla/types.cfg.yaml
+++ b/internal/test/strict-server/gorilla/types.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
models: true
diff --git a/internal/test/strict-server/gorilla/types.gen.go b/internal/test/strict-server/gorilla/types.gen.go
index c16705f32..6682c1aca 100644
--- a/internal/test/strict-server/gorilla/types.gen.go
+++ b/internal/test/strict-server/gorilla/types.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
// Example defines model for example.
diff --git a/internal/test/strict-server/iris/server.cfg.yaml b/internal/test/strict-server/iris/server.cfg.yaml
index e1d778202..481f842dc 100644
--- a/internal/test/strict-server/iris/server.cfg.yaml
+++ b/internal/test/strict-server/iris/server.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
iris-server: true
diff --git a/internal/test/strict-server/iris/server.gen.go b/internal/test/strict-server/iris/server.gen.go
index 54d6f4982..7f224b3b3 100644
--- a/internal/test/strict-server/iris/server.gen.go
+++ b/internal/test/strict-server/iris/server.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
import (
diff --git a/internal/test/strict-server/iris/server.go b/internal/test/strict-server/iris/server.go
index f35e2f82b..c0ab4c770 100644
--- a/internal/test/strict-server/iris/server.go
+++ b/internal/test/strict-server/iris/server.go
@@ -1,5 +1,5 @@
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
-//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
package api
diff --git a/internal/test/strict-server/iris/types.cfg.yaml b/internal/test/strict-server/iris/types.cfg.yaml
index 4ea1d8aa5..2ed9740ea 100644
--- a/internal/test/strict-server/iris/types.cfg.yaml
+++ b/internal/test/strict-server/iris/types.cfg.yaml
@@ -1,3 +1,4 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
package: api
generate:
models: true
diff --git a/internal/test/strict-server/iris/types.gen.go b/internal/test/strict-server/iris/types.gen.go
index c16705f32..6682c1aca 100644
--- a/internal/test/strict-server/iris/types.gen.go
+++ b/internal/test/strict-server/iris/types.gen.go
@@ -1,6 +1,6 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
-// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
package api
// Example defines model for example.
diff --git a/internal/test/strict-server/stdhttp/Makefile b/internal/test/strict-server/stdhttp/Makefile
new file mode 100644
index 000000000..dac22331f
--- /dev/null
+++ b/internal/test/strict-server/stdhttp/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 -f2 -d. <<< $(GOVER)")
+
+define execute-if-go-122
+@{ \
+if [[ 22 -le $(GOMINOR) ]]; then \
+ $1; \
+else \
+ echo -e "$(YELLOW)Skipping task as you're running Go v1.$(GOMINOR).x which is < Go 1.22, which this module requires$(RESET)"; \
+fi \
+}
+endef
+
+lint:
+ $(call execute-if-go-122,$(GOBIN)/golangci-lint run ./...)
+
+lint-ci:
+
+ $(call execute-if-go-122,$(GOBIN)/golangci-lint run ./... --out-format=github-actions --timeout=5m)
+
+generate:
+ $(call execute-if-go-122,go generate ./...)
+
+test:
+ $(call execute-if-go-122,go test -cover ./...)
+
+tidy:
+ $(call execute-if-go-122,go mod tidy)
+
+tidy-ci:
+ $(call execute-if-go-122,tidied -verbose)
diff --git a/internal/test/strict-server/stdhttp/go.mod b/internal/test/strict-server/stdhttp/go.mod
new file mode 100644
index 000000000..61c4982ac
--- /dev/null
+++ b/internal/test/strict-server/stdhttp/go.mod
@@ -0,0 +1,35 @@
+module github.com/oapi-codegen/oapi-codegen/v2/internal/test/strict-server/stdhttp
+
+go 1.22
+
+replace github.com/oapi-codegen/oapi-codegen/v2 => ../../../../
+
+replace github.com/oapi-codegen/oapi-codegen/v2/internal/test => ../..
+
+require (
+ github.com/getkin/kin-openapi v0.124.0
+ github.com/oapi-codegen/oapi-codegen/v2 v2.0.0-00010101000000-000000000000
+ github.com/oapi-codegen/oapi-codegen/v2/internal/test v0.0.0-00010101000000-000000000000
+ github.com/oapi-codegen/runtime v1.1.0
+ github.com/oapi-codegen/testutil v1.1.0
+ github.com/stretchr/testify v1.9.0
+)
+
+require (
+ github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/go-openapi/jsonpointer v0.20.2 // indirect
+ github.com/go-openapi/swag v0.22.8 // indirect
+ github.com/google/uuid v1.4.0 // indirect
+ github.com/invopop/yaml v0.2.0 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
+ github.com/perimeterx/marshmallow v1.1.5 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ golang.org/x/mod v0.17.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/tools v0.21.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
new file mode 100644
index 000000000..f6b222730
--- /dev/null
+++ b/internal/test/strict-server/stdhttp/go.sum
@@ -0,0 +1,63 @@
+github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
+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/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/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M=
+github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
+github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
+github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
+github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
+github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
+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/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
+github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
+github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
+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/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+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/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/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.1.0 h1:EufqpNg43acR3qzr3ObhXmWg3Sl2kwtRnUN5GYY4d5g=
+github.com/oapi-codegen/testutil v1.1.0/go.mod h1:ttCaYbHvJtHuiyeBF0tPIX+4uhEPTeizXKx28okijLw=
+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/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/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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
+github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
+golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
+golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/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/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/stdhttp/server.cfg.yaml b/internal/test/strict-server/stdhttp/server.cfg.yaml
new file mode 100644
index 000000000..fb4ed1a46
--- /dev/null
+++ b/internal/test/strict-server/stdhttp/server.cfg.yaml
@@ -0,0 +1,7 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: api
+generate:
+ std-http-server: true
+ strict-server: true
+ embedded-spec: true
+output: server.gen.go
diff --git a/internal/test/strict-server/stdhttp/server.gen.go b/internal/test/strict-server/stdhttp/server.gen.go
new file mode 100644
index 000000000..57140ea31
--- /dev/null
+++ b/internal/test/strict-server/stdhttp/server.gen.go
@@ -0,0 +1,1543 @@
+//go:build go1.22
+
+// Package api provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package api
+
+import (
+ "bytes"
+ "compress/gzip"
+ "context"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "io"
+ "mime"
+ "mime/multipart"
+ "net/http"
+ "net/url"
+ "path"
+ "strings"
+
+ "github.com/getkin/kin-openapi/openapi3"
+ "github.com/oapi-codegen/runtime"
+ strictnethttp "github.com/oapi-codegen/runtime/strictmiddleware/nethttp"
+)
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+ // (POST /json)
+ JSONExample(w http.ResponseWriter, r *http.Request)
+
+ // (POST /multipart)
+ MultipartExample(w http.ResponseWriter, r *http.Request)
+
+ // (POST /multipart-related)
+ MultipartRelatedExample(w http.ResponseWriter, r *http.Request)
+
+ // (POST /multiple)
+ MultipleRequestAndResponseTypes(w http.ResponseWriter, r *http.Request)
+
+ // (GET /reserved-go-keyword-parameters/{type})
+ ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request, pType string)
+
+ // (POST /reusable-responses)
+ ReusableResponses(w http.ResponseWriter, r *http.Request)
+
+ // (POST /text)
+ TextExample(w http.ResponseWriter, r *http.Request)
+
+ // (POST /unknown)
+ UnknownExample(w http.ResponseWriter, r *http.Request)
+
+ // (POST /unspecified-content-type)
+ UnspecifiedContentType(w http.ResponseWriter, r *http.Request)
+
+ // (POST /urlencoded)
+ URLEncodedExample(w http.ResponseWriter, r *http.Request)
+
+ // (POST /with-headers)
+ HeadersExample(w http.ResponseWriter, r *http.Request, params HeadersExampleParams)
+
+ // (POST /with-union)
+ UnionExample(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
+
+// JSONExample operation middleware
+func (siw *ServerInterfaceWrapper) JSONExample(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.JSONExample(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// MultipartExample operation middleware
+func (siw *ServerInterfaceWrapper) MultipartExample(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.MultipartExample(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// MultipartRelatedExample operation middleware
+func (siw *ServerInterfaceWrapper) MultipartRelatedExample(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.MultipartRelatedExample(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// MultipleRequestAndResponseTypes operation middleware
+func (siw *ServerInterfaceWrapper) MultipleRequestAndResponseTypes(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.MultipleRequestAndResponseTypes(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// ReservedGoKeywordParameters operation middleware
+func (siw *ServerInterfaceWrapper) ReservedGoKeywordParameters(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ var err error
+
+ // ------------- Path parameter "type" -------------
+ var pType string
+
+ err = runtime.BindStyledParameterWithOptions("simple", "type", r.PathValue("type"), &pType, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "type", Err: err})
+ return
+ }
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.ReservedGoKeywordParameters(w, r, pType)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// ReusableResponses operation middleware
+func (siw *ServerInterfaceWrapper) ReusableResponses(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.ReusableResponses(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// TextExample operation middleware
+func (siw *ServerInterfaceWrapper) TextExample(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.TextExample(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// UnknownExample operation middleware
+func (siw *ServerInterfaceWrapper) UnknownExample(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.UnknownExample(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// UnspecifiedContentType operation middleware
+func (siw *ServerInterfaceWrapper) UnspecifiedContentType(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.UnspecifiedContentType(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// URLEncodedExample operation middleware
+func (siw *ServerInterfaceWrapper) URLEncodedExample(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.URLEncodedExample(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// HeadersExample operation middleware
+func (siw *ServerInterfaceWrapper) HeadersExample(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ var err error
+
+ // Parameter object where we will unmarshal all parameters from the context
+ var params HeadersExampleParams
+
+ headers := r.Header
+
+ // ------------- Required header parameter "header1" -------------
+ if valueList, found := headers[http.CanonicalHeaderKey("header1")]; found {
+ var Header1 string
+ n := len(valueList)
+ if n != 1 {
+ siw.ErrorHandlerFunc(w, r, &TooManyValuesForParamError{ParamName: "header1", Count: n})
+ return
+ }
+
+ err = runtime.BindStyledParameterWithOptions("simple", "header1", valueList[0], &Header1, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: false, Required: true})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "header1", Err: err})
+ return
+ }
+
+ params.Header1 = Header1
+
+ } else {
+ err := fmt.Errorf("Header parameter header1 is required, but not found")
+ siw.ErrorHandlerFunc(w, r, &RequiredHeaderError{ParamName: "header1", Err: err})
+ return
+ }
+
+ // ------------- Optional header parameter "header2" -------------
+ if valueList, found := headers[http.CanonicalHeaderKey("header2")]; found {
+ var Header2 int
+ n := len(valueList)
+ if n != 1 {
+ siw.ErrorHandlerFunc(w, r, &TooManyValuesForParamError{ParamName: "header2", Count: n})
+ return
+ }
+
+ err = runtime.BindStyledParameterWithOptions("simple", "header2", valueList[0], &Header2, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: false, Required: false})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "header2", Err: err})
+ return
+ }
+
+ params.Header2 = &Header2
+
+ }
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.HeadersExample(w, r, params)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+// UnionExample operation middleware
+func (siw *ServerInterfaceWrapper) UnionExample(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.UnionExample(w, r)
+ }))
+
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+
+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{})
+}
+
+type StdHTTPServerOptions struct {
+ BaseURL string
+ BaseRouter *http.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 *http.ServeMux) http.Handler {
+ return HandlerWithOptions(si, StdHTTPServerOptions{
+ BaseRouter: m,
+ })
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, m *http.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("POST "+options.BaseURL+"/json", wrapper.JSONExample)
+ 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("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)
+ m.HandleFunc("POST "+options.BaseURL+"/unknown", wrapper.UnknownExample)
+ m.HandleFunc("POST "+options.BaseURL+"/unspecified-content-type", wrapper.UnspecifiedContentType)
+ m.HandleFunc("POST "+options.BaseURL+"/urlencoded", wrapper.URLEncodedExample)
+ m.HandleFunc("POST "+options.BaseURL+"/with-headers", wrapper.HeadersExample)
+ m.HandleFunc("POST "+options.BaseURL+"/with-union", wrapper.UnionExample)
+
+ return m
+}
+
+type BadrequestResponse struct {
+}
+
+type ReusableresponseResponseHeaders struct {
+ Header1 string
+ Header2 int
+}
+type ReusableresponseJSONResponse struct {
+ Body Example
+
+ Headers ReusableresponseResponseHeaders
+}
+
+type JSONExampleRequestObject struct {
+ Body *JSONExampleJSONRequestBody
+}
+
+type JSONExampleResponseObject interface {
+ VisitJSONExampleResponse(w http.ResponseWriter) error
+}
+
+type JSONExample200JSONResponse Example
+
+func (response JSONExample200JSONResponse) VisitJSONExampleResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(200)
+
+ return json.NewEncoder(w).Encode(response)
+}
+
+type JSONExample400Response = BadrequestResponse
+
+func (response JSONExample400Response) VisitJSONExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(400)
+ return nil
+}
+
+type JSONExampledefaultResponse struct {
+ StatusCode int
+}
+
+func (response JSONExampledefaultResponse) VisitJSONExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(response.StatusCode)
+ return nil
+}
+
+type MultipartExampleRequestObject struct {
+ Body *multipart.Reader
+}
+
+type MultipartExampleResponseObject interface {
+ VisitMultipartExampleResponse(w http.ResponseWriter) error
+}
+
+type MultipartExample200MultipartResponse func(writer *multipart.Writer) error
+
+func (response MultipartExample200MultipartResponse) VisitMultipartExampleResponse(w http.ResponseWriter) error {
+ writer := multipart.NewWriter(w)
+ w.Header().Set("Content-Type", writer.FormDataContentType())
+ w.WriteHeader(200)
+
+ defer writer.Close()
+ return response(writer)
+}
+
+type MultipartExample400Response = BadrequestResponse
+
+func (response MultipartExample400Response) VisitMultipartExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(400)
+ return nil
+}
+
+type MultipartExampledefaultResponse struct {
+ StatusCode int
+}
+
+func (response MultipartExampledefaultResponse) VisitMultipartExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(response.StatusCode)
+ return nil
+}
+
+type MultipartRelatedExampleRequestObject struct {
+ Body *multipart.Reader
+}
+
+type MultipartRelatedExampleResponseObject interface {
+ VisitMultipartRelatedExampleResponse(w http.ResponseWriter) error
+}
+
+type MultipartRelatedExample200MultipartResponse func(writer *multipart.Writer) error
+
+func (response MultipartRelatedExample200MultipartResponse) VisitMultipartRelatedExampleResponse(w http.ResponseWriter) error {
+ writer := multipart.NewWriter(w)
+ w.Header().Set("Content-Type", mime.FormatMediaType("multipart/related", map[string]string{"boundary": writer.Boundary()}))
+ w.WriteHeader(200)
+
+ defer writer.Close()
+ return response(writer)
+}
+
+type MultipartRelatedExample400Response = BadrequestResponse
+
+func (response MultipartRelatedExample400Response) VisitMultipartRelatedExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(400)
+ return nil
+}
+
+type MultipartRelatedExampledefaultResponse struct {
+ StatusCode int
+}
+
+func (response MultipartRelatedExampledefaultResponse) VisitMultipartRelatedExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(response.StatusCode)
+ return nil
+}
+
+type MultipleRequestAndResponseTypesRequestObject struct {
+ JSONBody *MultipleRequestAndResponseTypesJSONRequestBody
+ FormdataBody *MultipleRequestAndResponseTypesFormdataRequestBody
+ Body io.Reader
+ MultipartBody *multipart.Reader
+ TextBody *MultipleRequestAndResponseTypesTextRequestBody
+}
+
+type MultipleRequestAndResponseTypesResponseObject interface {
+ VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error
+}
+
+type MultipleRequestAndResponseTypes200JSONResponse Example
+
+func (response MultipleRequestAndResponseTypes200JSONResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(200)
+
+ return json.NewEncoder(w).Encode(response)
+}
+
+type MultipleRequestAndResponseTypes200FormdataResponse Example
+
+func (response MultipleRequestAndResponseTypes200FormdataResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+ w.WriteHeader(200)
+
+ if form, err := runtime.MarshalForm(response, nil); err != nil {
+ return err
+ } else {
+ _, err := w.Write([]byte(form.Encode()))
+ return err
+ }
+}
+
+type MultipleRequestAndResponseTypes200ImagepngResponse struct {
+ Body io.Reader
+ ContentLength int64
+}
+
+func (response MultipleRequestAndResponseTypes200ImagepngResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "image/png")
+ if response.ContentLength != 0 {
+ w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+ }
+ w.WriteHeader(200)
+
+ if closer, ok := response.Body.(io.ReadCloser); ok {
+ defer closer.Close()
+ }
+ _, err := io.Copy(w, response.Body)
+ return err
+}
+
+type MultipleRequestAndResponseTypes200MultipartResponse func(writer *multipart.Writer) error
+
+func (response MultipleRequestAndResponseTypes200MultipartResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+ writer := multipart.NewWriter(w)
+ w.Header().Set("Content-Type", writer.FormDataContentType())
+ w.WriteHeader(200)
+
+ defer writer.Close()
+ return response(writer)
+}
+
+type MultipleRequestAndResponseTypes200TextResponse string
+
+func (response MultipleRequestAndResponseTypes200TextResponse) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "text/plain")
+ w.WriteHeader(200)
+
+ _, err := w.Write([]byte(response))
+ return err
+}
+
+type MultipleRequestAndResponseTypes400Response = BadrequestResponse
+
+func (response MultipleRequestAndResponseTypes400Response) VisitMultipleRequestAndResponseTypesResponse(w http.ResponseWriter) error {
+ w.WriteHeader(400)
+ return nil
+}
+
+type ReservedGoKeywordParametersRequestObject struct {
+ Type string `json:"type"`
+}
+
+type ReservedGoKeywordParametersResponseObject interface {
+ VisitReservedGoKeywordParametersResponse(w http.ResponseWriter) error
+}
+
+type ReservedGoKeywordParameters200TextResponse string
+
+func (response ReservedGoKeywordParameters200TextResponse) VisitReservedGoKeywordParametersResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "text/plain")
+ w.WriteHeader(200)
+
+ _, err := w.Write([]byte(response))
+ return err
+}
+
+type ReusableResponsesRequestObject struct {
+ Body *ReusableResponsesJSONRequestBody
+}
+
+type ReusableResponsesResponseObject interface {
+ VisitReusableResponsesResponse(w http.ResponseWriter) error
+}
+
+type ReusableResponses200JSONResponse struct{ ReusableresponseJSONResponse }
+
+func (response ReusableResponses200JSONResponse) VisitReusableResponsesResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "application/json")
+ w.Header().Set("header1", fmt.Sprint(response.Headers.Header1))
+ w.Header().Set("header2", fmt.Sprint(response.Headers.Header2))
+ w.WriteHeader(200)
+
+ return json.NewEncoder(w).Encode(response.Body)
+}
+
+type ReusableResponses400Response = BadrequestResponse
+
+func (response ReusableResponses400Response) VisitReusableResponsesResponse(w http.ResponseWriter) error {
+ w.WriteHeader(400)
+ return nil
+}
+
+type ReusableResponsesdefaultResponse struct {
+ StatusCode int
+}
+
+func (response ReusableResponsesdefaultResponse) VisitReusableResponsesResponse(w http.ResponseWriter) error {
+ w.WriteHeader(response.StatusCode)
+ return nil
+}
+
+type TextExampleRequestObject struct {
+ Body *TextExampleTextRequestBody
+}
+
+type TextExampleResponseObject interface {
+ VisitTextExampleResponse(w http.ResponseWriter) error
+}
+
+type TextExample200TextResponse string
+
+func (response TextExample200TextResponse) VisitTextExampleResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "text/plain")
+ w.WriteHeader(200)
+
+ _, err := w.Write([]byte(response))
+ return err
+}
+
+type TextExample400Response = BadrequestResponse
+
+func (response TextExample400Response) VisitTextExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(400)
+ return nil
+}
+
+type TextExampledefaultResponse struct {
+ StatusCode int
+}
+
+func (response TextExampledefaultResponse) VisitTextExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(response.StatusCode)
+ return nil
+}
+
+type UnknownExampleRequestObject struct {
+ Body io.Reader
+}
+
+type UnknownExampleResponseObject interface {
+ VisitUnknownExampleResponse(w http.ResponseWriter) error
+}
+
+type UnknownExample200Videomp4Response struct {
+ Body io.Reader
+ ContentLength int64
+}
+
+func (response UnknownExample200Videomp4Response) VisitUnknownExampleResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "video/mp4")
+ if response.ContentLength != 0 {
+ w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+ }
+ w.WriteHeader(200)
+
+ if closer, ok := response.Body.(io.ReadCloser); ok {
+ defer closer.Close()
+ }
+ _, err := io.Copy(w, response.Body)
+ return err
+}
+
+type UnknownExample400Response = BadrequestResponse
+
+func (response UnknownExample400Response) VisitUnknownExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(400)
+ return nil
+}
+
+type UnknownExampledefaultResponse struct {
+ StatusCode int
+}
+
+func (response UnknownExampledefaultResponse) VisitUnknownExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(response.StatusCode)
+ return nil
+}
+
+type UnspecifiedContentTypeRequestObject struct {
+ ContentType string
+ Body io.Reader
+}
+
+type UnspecifiedContentTypeResponseObject interface {
+ VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error
+}
+
+type UnspecifiedContentType200VideoResponse struct {
+ Body io.Reader
+ ContentType string
+ ContentLength int64
+}
+
+func (response UnspecifiedContentType200VideoResponse) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", response.ContentType)
+ if response.ContentLength != 0 {
+ w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength))
+ }
+ w.WriteHeader(200)
+
+ if closer, ok := response.Body.(io.ReadCloser); ok {
+ defer closer.Close()
+ }
+ _, err := io.Copy(w, response.Body)
+ return err
+}
+
+type UnspecifiedContentType400Response = BadrequestResponse
+
+func (response UnspecifiedContentType400Response) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+ w.WriteHeader(400)
+ return nil
+}
+
+type UnspecifiedContentType401Response struct {
+}
+
+func (response UnspecifiedContentType401Response) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+ w.WriteHeader(401)
+ return nil
+}
+
+type UnspecifiedContentType403Response struct {
+}
+
+func (response UnspecifiedContentType403Response) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+ w.WriteHeader(403)
+ return nil
+}
+
+type UnspecifiedContentTypedefaultResponse struct {
+ StatusCode int
+}
+
+func (response UnspecifiedContentTypedefaultResponse) VisitUnspecifiedContentTypeResponse(w http.ResponseWriter) error {
+ w.WriteHeader(response.StatusCode)
+ return nil
+}
+
+type URLEncodedExampleRequestObject struct {
+ Body *URLEncodedExampleFormdataRequestBody
+}
+
+type URLEncodedExampleResponseObject interface {
+ VisitURLEncodedExampleResponse(w http.ResponseWriter) error
+}
+
+type URLEncodedExample200FormdataResponse Example
+
+func (response URLEncodedExample200FormdataResponse) VisitURLEncodedExampleResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+ w.WriteHeader(200)
+
+ if form, err := runtime.MarshalForm(response, nil); err != nil {
+ return err
+ } else {
+ _, err := w.Write([]byte(form.Encode()))
+ return err
+ }
+}
+
+type URLEncodedExample400Response = BadrequestResponse
+
+func (response URLEncodedExample400Response) VisitURLEncodedExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(400)
+ return nil
+}
+
+type URLEncodedExampledefaultResponse struct {
+ StatusCode int
+}
+
+func (response URLEncodedExampledefaultResponse) VisitURLEncodedExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(response.StatusCode)
+ return nil
+}
+
+type HeadersExampleRequestObject struct {
+ Params HeadersExampleParams
+ Body *HeadersExampleJSONRequestBody
+}
+
+type HeadersExampleResponseObject interface {
+ VisitHeadersExampleResponse(w http.ResponseWriter) error
+}
+
+type HeadersExample200ResponseHeaders struct {
+ Header1 string
+ Header2 int
+}
+
+type HeadersExample200JSONResponse struct {
+ Body Example
+ Headers HeadersExample200ResponseHeaders
+}
+
+func (response HeadersExample200JSONResponse) VisitHeadersExampleResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "application/json")
+ w.Header().Set("header1", fmt.Sprint(response.Headers.Header1))
+ w.Header().Set("header2", fmt.Sprint(response.Headers.Header2))
+ w.WriteHeader(200)
+
+ return json.NewEncoder(w).Encode(response.Body)
+}
+
+type HeadersExample400Response = BadrequestResponse
+
+func (response HeadersExample400Response) VisitHeadersExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(400)
+ return nil
+}
+
+type HeadersExampledefaultResponse struct {
+ StatusCode int
+}
+
+func (response HeadersExampledefaultResponse) VisitHeadersExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(response.StatusCode)
+ return nil
+}
+
+type UnionExampleRequestObject struct {
+ Body *UnionExampleJSONRequestBody
+}
+
+type UnionExampleResponseObject interface {
+ VisitUnionExampleResponse(w http.ResponseWriter) error
+}
+
+type UnionExample200ResponseHeaders struct {
+ Header1 string
+ Header2 int
+}
+
+type UnionExample200ApplicationAlternativePlusJSONResponse struct {
+ Body Example
+ Headers UnionExample200ResponseHeaders
+}
+
+func (response UnionExample200ApplicationAlternativePlusJSONResponse) VisitUnionExampleResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "application/alternative+json")
+ w.Header().Set("header1", fmt.Sprint(response.Headers.Header1))
+ w.Header().Set("header2", fmt.Sprint(response.Headers.Header2))
+ w.WriteHeader(200)
+
+ return json.NewEncoder(w).Encode(response.Body)
+}
+
+type UnionExample200JSONResponse struct {
+ Body struct {
+ union json.RawMessage
+ }
+ Headers UnionExample200ResponseHeaders
+}
+
+func (response UnionExample200JSONResponse) VisitUnionExampleResponse(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "application/json")
+ w.Header().Set("header1", fmt.Sprint(response.Headers.Header1))
+ w.Header().Set("header2", fmt.Sprint(response.Headers.Header2))
+ w.WriteHeader(200)
+
+ return json.NewEncoder(w).Encode(response.Body.union)
+}
+
+type UnionExample400Response = BadrequestResponse
+
+func (response UnionExample400Response) VisitUnionExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(400)
+ return nil
+}
+
+type UnionExampledefaultResponse struct {
+ StatusCode int
+}
+
+func (response UnionExampledefaultResponse) VisitUnionExampleResponse(w http.ResponseWriter) error {
+ w.WriteHeader(response.StatusCode)
+ return nil
+}
+
+// StrictServerInterface represents all server handlers.
+type StrictServerInterface interface {
+
+ // (POST /json)
+ JSONExample(ctx context.Context, request JSONExampleRequestObject) (JSONExampleResponseObject, error)
+
+ // (POST /multipart)
+ MultipartExample(ctx context.Context, request MultipartExampleRequestObject) (MultipartExampleResponseObject, error)
+
+ // (POST /multipart-related)
+ MultipartRelatedExample(ctx context.Context, request MultipartRelatedExampleRequestObject) (MultipartRelatedExampleResponseObject, error)
+
+ // (POST /multiple)
+ MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error)
+
+ // (GET /reserved-go-keyword-parameters/{type})
+ ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error)
+
+ // (POST /reusable-responses)
+ ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error)
+
+ // (POST /text)
+ TextExample(ctx context.Context, request TextExampleRequestObject) (TextExampleResponseObject, error)
+
+ // (POST /unknown)
+ UnknownExample(ctx context.Context, request UnknownExampleRequestObject) (UnknownExampleResponseObject, error)
+
+ // (POST /unspecified-content-type)
+ UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) (UnspecifiedContentTypeResponseObject, error)
+
+ // (POST /urlencoded)
+ URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) (URLEncodedExampleResponseObject, error)
+
+ // (POST /with-headers)
+ HeadersExample(ctx context.Context, request HeadersExampleRequestObject) (HeadersExampleResponseObject, error)
+
+ // (POST /with-union)
+ UnionExample(ctx context.Context, request UnionExampleRequestObject) (UnionExampleResponseObject, 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
+}
+
+// JSONExample operation middleware
+func (sh *strictHandler) JSONExample(w http.ResponseWriter, r *http.Request) {
+ var request JSONExampleRequestObject
+
+ 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
+ }
+ 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))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "JSONExample")
+ }
+
+ response, err := handler(r.Context(), w, r, request)
+
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(JSONExampleResponseObject); ok {
+ if err := validResponse.VisitJSONExampleResponse(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))
+ }
+}
+
+// MultipartExample operation middleware
+func (sh *strictHandler) MultipartExample(w http.ResponseWriter, r *http.Request) {
+ var request MultipartExampleRequestObject
+
+ if reader, err := r.MultipartReader(); err != nil {
+ sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode multipart body: %w", err))
+ return
+ } else {
+ request.Body = reader
+ }
+
+ handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
+ return sh.ssi.MultipartExample(ctx, request.(MultipartExampleRequestObject))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "MultipartExample")
+ }
+
+ response, err := handler(r.Context(), w, r, request)
+
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(MultipartExampleResponseObject); ok {
+ if err := validResponse.VisitMultipartExampleResponse(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))
+ }
+}
+
+// MultipartRelatedExample operation middleware
+func (sh *strictHandler) MultipartRelatedExample(w http.ResponseWriter, r *http.Request) {
+ var request MultipartRelatedExampleRequestObject
+
+ if _, params, err := mime.ParseMediaType(r.Header.Get("Content-Type")); err != nil {
+ sh.options.RequestErrorHandlerFunc(w, r, err)
+ return
+ } else if boundary := params["boundary"]; boundary == "" {
+ sh.options.RequestErrorHandlerFunc(w, r, http.ErrMissingBoundary)
+ return
+ } else {
+ request.Body = multipart.NewReader(r.Body, boundary)
+ }
+
+ handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
+ return sh.ssi.MultipartRelatedExample(ctx, request.(MultipartRelatedExampleRequestObject))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "MultipartRelatedExample")
+ }
+
+ response, err := handler(r.Context(), w, r, request)
+
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(MultipartRelatedExampleResponseObject); ok {
+ if err := validResponse.VisitMultipartRelatedExampleResponse(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))
+ }
+}
+
+// MultipleRequestAndResponseTypes operation middleware
+func (sh *strictHandler) MultipleRequestAndResponseTypes(w http.ResponseWriter, r *http.Request) {
+ var request MultipleRequestAndResponseTypesRequestObject
+
+ if strings.HasPrefix(r.Header.Get("Content-Type"), "application/json") {
+
+ 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
+ }
+ request.JSONBody = &body
+ }
+ if strings.HasPrefix(r.Header.Get("Content-Type"), "application/x-www-form-urlencoded") {
+ if err := r.ParseForm(); err != nil {
+ sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode formdata: %w", err))
+ return
+ }
+ var body MultipleRequestAndResponseTypesFormdataRequestBody
+ if err := runtime.BindForm(&body, r.Form, nil, nil); err != nil {
+ sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't bind formdata: %w", err))
+ return
+ }
+ request.FormdataBody = &body
+ }
+ if strings.HasPrefix(r.Header.Get("Content-Type"), "image/png") {
+ request.Body = r.Body
+ }
+ if strings.HasPrefix(r.Header.Get("Content-Type"), "multipart/form-data") {
+ if reader, err := r.MultipartReader(); err != nil {
+ sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode multipart body: %w", err))
+ return
+ } else {
+ request.MultipartBody = reader
+ }
+ }
+ if strings.HasPrefix(r.Header.Get("Content-Type"), "text/plain") {
+ data, err := io.ReadAll(r.Body)
+ if err != nil {
+ sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err))
+ return
+ }
+ body := MultipleRequestAndResponseTypesTextRequestBody(data)
+ request.TextBody = &body
+ }
+
+ handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
+ return sh.ssi.MultipleRequestAndResponseTypes(ctx, request.(MultipleRequestAndResponseTypesRequestObject))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "MultipleRequestAndResponseTypes")
+ }
+
+ response, err := handler(r.Context(), w, r, request)
+
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(MultipleRequestAndResponseTypesResponseObject); ok {
+ if err := validResponse.VisitMultipleRequestAndResponseTypesResponse(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
+
+ request.Type = pType
+
+ handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
+ return sh.ssi.ReservedGoKeywordParameters(ctx, request.(ReservedGoKeywordParametersRequestObject))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "ReservedGoKeywordParameters")
+ }
+
+ response, err := handler(r.Context(), w, r, request)
+
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(ReservedGoKeywordParametersResponseObject); ok {
+ if err := validResponse.VisitReservedGoKeywordParametersResponse(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))
+ }
+}
+
+// ReusableResponses operation middleware
+func (sh *strictHandler) ReusableResponses(w http.ResponseWriter, r *http.Request) {
+ var request ReusableResponsesRequestObject
+
+ 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
+ }
+ 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))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "ReusableResponses")
+ }
+
+ response, err := handler(r.Context(), w, r, request)
+
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(ReusableResponsesResponseObject); ok {
+ if err := validResponse.VisitReusableResponsesResponse(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))
+ }
+}
+
+// TextExample operation middleware
+func (sh *strictHandler) TextExample(w http.ResponseWriter, r *http.Request) {
+ var request TextExampleRequestObject
+
+ data, err := io.ReadAll(r.Body)
+ if err != nil {
+ sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't read body: %w", err))
+ return
+ }
+ 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))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "TextExample")
+ }
+
+ response, err := handler(r.Context(), w, r, request)
+
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(TextExampleResponseObject); ok {
+ if err := validResponse.VisitTextExampleResponse(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))
+ }
+}
+
+// UnknownExample operation middleware
+func (sh *strictHandler) UnknownExample(w http.ResponseWriter, r *http.Request) {
+ var request UnknownExampleRequestObject
+
+ request.Body = r.Body
+
+ handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
+ return sh.ssi.UnknownExample(ctx, request.(UnknownExampleRequestObject))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "UnknownExample")
+ }
+
+ response, err := handler(r.Context(), w, r, request)
+
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(UnknownExampleResponseObject); ok {
+ if err := validResponse.VisitUnknownExampleResponse(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))
+ }
+}
+
+// UnspecifiedContentType operation middleware
+func (sh *strictHandler) UnspecifiedContentType(w http.ResponseWriter, r *http.Request) {
+ var request UnspecifiedContentTypeRequestObject
+
+ request.ContentType = r.Header.Get("Content-Type")
+
+ request.Body = r.Body
+
+ handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
+ return sh.ssi.UnspecifiedContentType(ctx, request.(UnspecifiedContentTypeRequestObject))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "UnspecifiedContentType")
+ }
+
+ response, err := handler(r.Context(), w, r, request)
+
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(UnspecifiedContentTypeResponseObject); ok {
+ if err := validResponse.VisitUnspecifiedContentTypeResponse(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))
+ }
+}
+
+// URLEncodedExample operation middleware
+func (sh *strictHandler) URLEncodedExample(w http.ResponseWriter, r *http.Request) {
+ var request URLEncodedExampleRequestObject
+
+ if err := r.ParseForm(); err != nil {
+ sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode formdata: %w", err))
+ return
+ }
+ var body URLEncodedExampleFormdataRequestBody
+ if err := runtime.BindForm(&body, r.Form, nil, nil); err != nil {
+ sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't bind formdata: %w", err))
+ return
+ }
+ request.Body = &body
+
+ handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) {
+ return sh.ssi.URLEncodedExample(ctx, request.(URLEncodedExampleRequestObject))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "URLEncodedExample")
+ }
+
+ response, err := handler(r.Context(), w, r, request)
+
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(URLEncodedExampleResponseObject); ok {
+ if err := validResponse.VisitURLEncodedExampleResponse(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))
+ }
+}
+
+// HeadersExample operation middleware
+func (sh *strictHandler) HeadersExample(w http.ResponseWriter, r *http.Request, params HeadersExampleParams) {
+ var request HeadersExampleRequestObject
+
+ request.Params = params
+
+ 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
+ }
+ 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))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "HeadersExample")
+ }
+
+ response, err := handler(r.Context(), w, r, request)
+
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(HeadersExampleResponseObject); ok {
+ if err := validResponse.VisitHeadersExampleResponse(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))
+ }
+}
+
+// UnionExample operation middleware
+func (sh *strictHandler) UnionExample(w http.ResponseWriter, r *http.Request) {
+ var request UnionExampleRequestObject
+
+ 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
+ }
+ 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))
+ }
+ for _, middleware := range sh.middlewares {
+ handler = middleware(handler, "UnionExample")
+ }
+
+ response, err := handler(r.Context(), w, r, request)
+
+ if err != nil {
+ sh.options.ResponseErrorHandlerFunc(w, r, err)
+ } else if validResponse, ok := response.(UnionExampleResponseObject); ok {
+ if err := validResponse.VisitUnionExampleResponse(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))
+ }
+}
+
+// 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",
+}
+
+// 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/strict-server/stdhttp/server.go b/internal/test/strict-server/stdhttp/server.go
new file mode 100644
index 000000000..a142a6b81
--- /dev/null
+++ b/internal/test/strict-server/stdhttp/server.go
@@ -0,0 +1,146 @@
+//go:build go1.22
+
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=server.cfg.yaml ../strict-schema.yaml
+//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=types.cfg.yaml ../strict-schema.yaml
+
+package api
+
+import (
+ "context"
+ "encoding/json"
+ "io"
+ "mime/multipart"
+)
+
+type StrictServer struct {
+}
+
+func (s StrictServer) JSONExample(ctx context.Context, request JSONExampleRequestObject) (JSONExampleResponseObject, error) {
+ return JSONExample200JSONResponse(*request.Body), nil
+}
+
+func (s StrictServer) MultipartExample(ctx context.Context, request MultipartExampleRequestObject) (MultipartExampleResponseObject, error) {
+ return MultipartExample200MultipartResponse(func(writer *multipart.Writer) error {
+ for {
+ part, err := request.Body.NextPart()
+ if err == io.EOF {
+ return nil
+ } else if err != nil {
+ return err
+ }
+ w, err := writer.CreatePart(part.Header)
+ if err != nil {
+ return err
+ }
+ _, err = io.Copy(w, part)
+ if err != nil {
+ return err
+ }
+ if err = part.Close(); err != nil {
+ return err
+ }
+ }
+ }), nil
+}
+
+func (s StrictServer) MultipartRelatedExample(ctx context.Context, request MultipartRelatedExampleRequestObject) (MultipartRelatedExampleResponseObject, error) {
+ return MultipartRelatedExample200MultipartResponse(func(writer *multipart.Writer) error {
+ for {
+ part, err := request.Body.NextPart()
+ if err == io.EOF {
+ return nil
+ } else if err != nil {
+ return err
+ }
+ w, err := writer.CreatePart(part.Header)
+ if err != nil {
+ return err
+ }
+ _, err = io.Copy(w, part)
+ if err != nil {
+ return err
+ }
+ if err = part.Close(); err != nil {
+ return err
+ }
+ }
+ }), nil
+}
+
+func (s StrictServer) MultipleRequestAndResponseTypes(ctx context.Context, request MultipleRequestAndResponseTypesRequestObject) (MultipleRequestAndResponseTypesResponseObject, error) {
+ switch {
+ case request.Body != nil:
+ return MultipleRequestAndResponseTypes200ImagepngResponse{Body: request.Body}, nil
+ case request.JSONBody != nil:
+ return MultipleRequestAndResponseTypes200JSONResponse(*request.JSONBody), nil
+ case request.FormdataBody != nil:
+ return MultipleRequestAndResponseTypes200FormdataResponse(*request.FormdataBody), nil
+ case request.TextBody != nil:
+ return MultipleRequestAndResponseTypes200TextResponse(*request.TextBody), nil
+ case request.MultipartBody != nil:
+ return MultipleRequestAndResponseTypes200MultipartResponse(func(writer *multipart.Writer) error {
+ for {
+ part, err := request.MultipartBody.NextPart()
+ if err == io.EOF {
+ return nil
+ } else if err != nil {
+ return err
+ }
+ w, err := writer.CreatePart(part.Header)
+ if err != nil {
+ return err
+ }
+ _, err = io.Copy(w, part)
+ if err != nil {
+ return err
+ }
+ if err = part.Close(); err != nil {
+ return err
+ }
+ }
+ }), nil
+ default:
+ return MultipleRequestAndResponseTypes400Response{}, nil
+ }
+}
+
+func (s StrictServer) TextExample(ctx context.Context, request TextExampleRequestObject) (TextExampleResponseObject, error) {
+ return TextExample200TextResponse(*request.Body), nil
+}
+
+func (s StrictServer) UnknownExample(ctx context.Context, request UnknownExampleRequestObject) (UnknownExampleResponseObject, error) {
+ return UnknownExample200Videomp4Response{Body: request.Body}, nil
+}
+
+func (s StrictServer) UnspecifiedContentType(ctx context.Context, request UnspecifiedContentTypeRequestObject) (UnspecifiedContentTypeResponseObject, error) {
+ return UnspecifiedContentType200VideoResponse{Body: request.Body, ContentType: request.ContentType}, nil
+}
+
+func (s StrictServer) URLEncodedExample(ctx context.Context, request URLEncodedExampleRequestObject) (URLEncodedExampleResponseObject, error) {
+ return URLEncodedExample200FormdataResponse(*request.Body), nil
+}
+
+func (s StrictServer) HeadersExample(ctx context.Context, request HeadersExampleRequestObject) (HeadersExampleResponseObject, error) {
+ return HeadersExample200JSONResponse{Body: *request.Body, Headers: HeadersExample200ResponseHeaders{Header1: request.Params.Header1, Header2: *request.Params.Header2}}, nil
+}
+
+func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error) {
+ return ReusableResponses200JSONResponse{ReusableresponseJSONResponse: ReusableresponseJSONResponse{Body: *request.Body}}, nil
+}
+
+func (s StrictServer) ReservedGoKeywordParameters(ctx context.Context, request ReservedGoKeywordParametersRequestObject) (ReservedGoKeywordParametersResponseObject, error) {
+ return ReservedGoKeywordParameters200TextResponse(""), nil
+}
+
+func (s StrictServer) UnionExample(ctx context.Context, request UnionExampleRequestObject) (UnionExampleResponseObject, error) {
+ union, err := json.Marshal(*request.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ return UnionExample200JSONResponse{
+ Body: struct{ union json.RawMessage }{
+ union: union,
+ },
+ }, nil
+}
diff --git a/internal/test/strict-server/stdhttp/std_strict_test.go b/internal/test/strict-server/stdhttp/std_strict_test.go
new file mode 100644
index 000000000..40d362a54
--- /dev/null
+++ b/internal/test/strict-server/stdhttp/std_strict_test.go
@@ -0,0 +1,229 @@
+//go:build go1.22
+
+package api
+
+import (
+ "bytes"
+ "encoding/json"
+ "io"
+ "mime"
+ "mime/multipart"
+ "net/http"
+ "net/url"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ clientAPI "github.com/oapi-codegen/oapi-codegen/v2/internal/test/strict-server/client"
+ "github.com/oapi-codegen/runtime"
+ "github.com/oapi-codegen/testutil"
+)
+
+func TestStdHTTPServer(t *testing.T) {
+ server := StrictServer{}
+ strictHandler := NewStrictHandler(server, nil)
+ m := http.NewServeMux()
+ HandlerFromMux(strictHandler, m)
+ testImpl(t, m)
+}
+
+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/stdhttp/tools/tools.go b/internal/test/strict-server/stdhttp/tools/tools.go
new file mode 100644
index 000000000..8615cb4c5
--- /dev/null
+++ b/internal/test/strict-server/stdhttp/tools/tools.go
@@ -0,0 +1,8 @@
+//go:build tools
+// +build tools
+
+package tools
+
+import (
+ _ "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen"
+)
diff --git a/internal/test/strict-server/stdhttp/types.cfg.yaml b/internal/test/strict-server/stdhttp/types.cfg.yaml
new file mode 100644
index 000000000..2ed9740ea
--- /dev/null
+++ b/internal/test/strict-server/stdhttp/types.cfg.yaml
@@ -0,0 +1,5 @@
+# yaml-language-server: $schema=../../../../configuration-schema.json
+package: api
+generate:
+ models: true
+output: types.gen.go
diff --git a/internal/test/strict-server/stdhttp/types.gen.go b/internal/test/strict-server/stdhttp/types.gen.go
new file mode 100644
index 000000000..6682c1aca
--- /dev/null
+++ b/internal/test/strict-server/stdhttp/types.gen.go
@@ -0,0 +1,60 @@
+// Package api provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT.
+package api
+
+// Example defines model for example.
+type Example struct {
+ Value *string `json:"value,omitempty"`
+}
+
+// Reusableresponse defines model for reusableresponse.
+type Reusableresponse = Example
+
+// MultipleRequestAndResponseTypesTextBody defines parameters for MultipleRequestAndResponseTypes.
+type MultipleRequestAndResponseTypesTextBody = string
+
+// TextExampleTextBody defines parameters for TextExample.
+type TextExampleTextBody = string
+
+// HeadersExampleParams defines parameters for HeadersExample.
+type HeadersExampleParams struct {
+ Header1 string `json:"header1"`
+ Header2 *int `json:"header2,omitempty"`
+}
+
+// JSONExampleJSONRequestBody defines body for JSONExample for application/json ContentType.
+type JSONExampleJSONRequestBody = Example
+
+// MultipartExampleMultipartRequestBody defines body for MultipartExample for multipart/form-data ContentType.
+type MultipartExampleMultipartRequestBody = Example
+
+// MultipartRelatedExampleMultipartRequestBody defines body for MultipartRelatedExample for multipart/related ContentType.
+type MultipartRelatedExampleMultipartRequestBody = Example
+
+// MultipleRequestAndResponseTypesJSONRequestBody defines body for MultipleRequestAndResponseTypes for application/json ContentType.
+type MultipleRequestAndResponseTypesJSONRequestBody = Example
+
+// MultipleRequestAndResponseTypesFormdataRequestBody defines body for MultipleRequestAndResponseTypes for application/x-www-form-urlencoded ContentType.
+type MultipleRequestAndResponseTypesFormdataRequestBody = Example
+
+// MultipleRequestAndResponseTypesMultipartRequestBody defines body for MultipleRequestAndResponseTypes for multipart/form-data ContentType.
+type MultipleRequestAndResponseTypesMultipartRequestBody = Example
+
+// MultipleRequestAndResponseTypesTextRequestBody defines body for MultipleRequestAndResponseTypes for text/plain ContentType.
+type MultipleRequestAndResponseTypesTextRequestBody = MultipleRequestAndResponseTypesTextBody
+
+// ReusableResponsesJSONRequestBody defines body for ReusableResponses for application/json ContentType.
+type ReusableResponsesJSONRequestBody = Example
+
+// TextExampleTextRequestBody defines body for TextExample for text/plain ContentType.
+type TextExampleTextRequestBody = TextExampleTextBody
+
+// URLEncodedExampleFormdataRequestBody defines body for URLEncodedExample for application/x-www-form-urlencoded ContentType.
+type URLEncodedExampleFormdataRequestBody = Example
+
+// HeadersExampleJSONRequestBody defines body for HeadersExample for application/json ContentType.
+type HeadersExampleJSONRequestBody = Example
+
+// UnionExampleJSONRequestBody defines body for UnionExample for application/json ContentType.
+type UnionExampleJSONRequestBody = Example
diff --git a/internal/test/strict-server/strict_test.go b/internal/test/strict-server/strict_test.go
index a1143e89f..0ae094df0 100644
--- a/internal/test/strict-server/strict_test.go
+++ b/internal/test/strict-server/strict_test.go
@@ -19,12 +19,12 @@ import (
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert"
- chiAPI "github.com/deepmap/oapi-codegen/v2/internal/test/strict-server/chi"
- clientAPI "github.com/deepmap/oapi-codegen/v2/internal/test/strict-server/client"
- echoAPI "github.com/deepmap/oapi-codegen/v2/internal/test/strict-server/echo"
- fiberAPI "github.com/deepmap/oapi-codegen/v2/internal/test/strict-server/fiber"
- ginAPI "github.com/deepmap/oapi-codegen/v2/internal/test/strict-server/gin"
- irisAPI "github.com/deepmap/oapi-codegen/v2/internal/test/strict-server/iris"
+ chiAPI "github.com/oapi-codegen/oapi-codegen/v2/internal/test/strict-server/chi"
+ clientAPI "github.com/oapi-codegen/oapi-codegen/v2/internal/test/strict-server/client"
+ echoAPI "github.com/oapi-codegen/oapi-codegen/v2/internal/test/strict-server/echo"
+ fiberAPI "github.com/oapi-codegen/oapi-codegen/v2/internal/test/strict-server/fiber"
+ ginAPI "github.com/oapi-codegen/oapi-codegen/v2/internal/test/strict-server/gin"
+ irisAPI "github.com/oapi-codegen/oapi-codegen/v2/internal/test/strict-server/iris"
"github.com/oapi-codegen/runtime"
"github.com/oapi-codegen/testutil"
diff --git a/pkg/codegen/codegen.go b/pkg/codegen/codegen.go
index 51fb49bae..4146e1f77 100644
--- a/pkg/codegen/codegen.go
+++ b/pkg/codegen/codegen.go
@@ -37,7 +37,7 @@ import (
"github.com/getkin/kin-openapi/openapi3"
"golang.org/x/tools/imports"
- "github.com/deepmap/oapi-codegen/v2/pkg/util"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/util"
)
// Embed the templates directory
@@ -128,6 +128,13 @@ func Generate(spec *openapi3.T, opts Configuration) (string, error) {
globalState.options.OutputOptions.ClientTypeName = defaultClientTypeName
}
+ nameNormalizerFunction := NameNormalizerFunction(opts.OutputOptions.NameNormalizer)
+ nameNormalizer = NameNormalizers[nameNormalizerFunction]
+ if nameNormalizer == nil {
+ return "", fmt.Errorf(`the name-normalizer option %v could not be found among options %q`,
+ opts.OutputOptions.NameNormalizer, NameNormalizers.Options())
+ }
+
// This creates the golang templates text package
TemplateFunctions["opts"] = func() Configuration { return globalState.options }
maps.Copy(TemplateFunctions, sprig.FuncMap())
@@ -256,6 +263,14 @@ func Generate(spec *openapi3.T, opts Configuration) (string, error) {
}
}
+ var stdHTTPServerOut string
+ if opts.Generate.StdHTTPServer {
+ stdHTTPServerOut, err = GenerateStdHTTPServer(t, ops)
+ if err != nil {
+ return "", fmt.Errorf("error generating Go handlers for Paths: %w", err)
+ }
+ }
+
var strictServerOut string
if opts.Generate.Strict {
var responses []ResponseDefinition
@@ -383,6 +398,13 @@ func Generate(spec *openapi3.T, opts Configuration) (string, error) {
}
}
+ if opts.Generate.StdHTTPServer {
+ _, err = w.WriteString(stdHTTPServerOut)
+ if err != nil {
+ return "", fmt.Errorf("error writing server path handlers: %w", err)
+ }
+ }
+
if opts.Generate.Strict {
_, err = w.WriteString(strictServerOut)
if err != nil {
@@ -545,7 +567,7 @@ func GenerateTypesForSchemas(t *template.Template, schemas map[string]*openapi3.
Schema: goSchema,
})
- types = append(types, goSchema.GetAdditionalTypeDefs()...)
+ types = append(types, goSchema.AdditionalTypes...)
}
return types, nil
}
@@ -554,7 +576,7 @@ func GenerateTypesForSchemas(t *template.Template, schemas map[string]*openapi3.
// components/parameters section of the Swagger spec.
func GenerateTypesForParameters(t *template.Template, params map[string]*openapi3.ParameterRef) ([]TypeDefinition, error) {
var types []TypeDefinition
- for _, paramName := range SortedParameterKeys(params) {
+ for _, paramName := range SortedMapKeys(params) {
paramOrRef := params[paramName]
goType, err := paramToGoType(paramOrRef.Value, nil)
@@ -592,7 +614,7 @@ func GenerateTypesForParameters(t *template.Template, params map[string]*openapi
func GenerateTypesForResponses(t *template.Template, responses openapi3.ResponseBodies) ([]TypeDefinition, error) {
var types []TypeDefinition
- for _, responseName := range SortedResponsesKeys(responses) {
+ for _, responseName := range SortedMapKeys(responses) {
responseOrRef := responses[responseName]
// We have to generate the response object. We're only going to
@@ -607,8 +629,8 @@ func GenerateTypesForResponses(t *template.Template, responses openapi3.Response
}
}
- sortedContentKeys := SortedContentKeys(response.Content)
- for _, mediaType := range sortedContentKeys {
+ SortedMapKeys := SortedMapKeys(response.Content)
+ for _, mediaType := range SortedMapKeys {
response := response.Content[mediaType]
if !util.IsMediaTypeJson(mediaType) {
continue
@@ -654,7 +676,7 @@ func GenerateTypesForResponses(t *template.Template, responses openapi3.Response
func GenerateTypesForRequestBodies(t *template.Template, bodies map[string]*openapi3.RequestBodyRef) ([]TypeDefinition, error) {
var types []TypeDefinition
- for _, requestBodyName := range SortedRequestBodyKeys(bodies) {
+ for _, requestBodyName := range SortedMapKeys(bodies) {
requestBodyRef := bodies[requestBodyName]
// As for responses, we will only generate Go code for JSON bodies,
@@ -1096,8 +1118,7 @@ func GoSchemaImports(schemas ...*openapi3.SchemaRef) (map[string]goImport, error
schemaVal := sref.Value
t := schemaVal.Type
- switch t {
- case "", "object":
+ if t.Slice() == nil || t.Is("object") {
for _, v := range schemaVal.Properties {
imprts, err := GoSchemaImports(v)
if err != nil {
@@ -1105,7 +1126,7 @@ func GoSchemaImports(schemas ...*openapi3.SchemaRef) (map[string]goImport, error
}
MergeImports(res, imprts)
}
- case "array":
+ } else if t.Is("array") {
imprts, err := GoSchemaImports(schemaVal.Items)
if err != nil {
return nil, err
diff --git a/pkg/codegen/codegen_test.go b/pkg/codegen/codegen_test.go
index b44bf4202..1d752601b 100644
--- a/pkg/codegen/codegen_test.go
+++ b/pkg/codegen/codegen_test.go
@@ -8,24 +8,16 @@ import (
"github.com/getkin/kin-openapi/openapi3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "golang.org/x/lint"
- "github.com/deepmap/oapi-codegen/v2/pkg/util"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/util"
)
const (
remoteRefFile = `https://raw.githubusercontent.com/deepmap/oapi-codegen/master/examples/petstore-expanded` +
`/petstore-expanded.yaml`
- remoteRefImport = `github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded`
+ remoteRefImport = `github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded`
)
-func checkLint(t *testing.T, filename string, code []byte) {
- linter := new(lint.Linter)
- problems, err := linter.Lint(filename, code)
- assert.NoError(t, err)
- assert.Len(t, problems, 0)
-}
-
func TestExampleOpenAPICodeGeneration(t *testing.T) {
// Input vars for code generation:
@@ -91,9 +83,6 @@ type GetTestByNameResponse struct {
assert.Contains(t, code, "type EnumTestEnumNames int")
assert.Contains(t, code, "Two EnumTestEnumNames = 2")
assert.Contains(t, code, "Double EnumTestEnumVarnames = 2")
-
- // Make sure the generated code is valid:
- checkLint(t, "test.gen.go", []byte(code))
}
func TestExtPropGoTypeSkipOptionalPointer(t *testing.T) {
@@ -175,10 +164,6 @@ func TestGoTypeImport(t *testing.T) {
for _, imp := range imports {
assert.Contains(t, code, imp)
}
-
- // Make sure the generated code is valid:
- checkLint(t, "test.gen.go", []byte(code))
-
}
func TestRemoteExternalReference(t *testing.T) {
@@ -213,7 +198,7 @@ func TestRemoteExternalReference(t *testing.T) {
assert.Contains(t, code, "package api")
// Check import
- assert.Contains(t, code, `externalRef0 "github.com/deepmap/oapi-codegen/v2/examples/petstore-expanded"`)
+ assert.Contains(t, code, `externalRef0 "github.com/oapi-codegen/oapi-codegen/v2/examples/petstore-expanded"`)
// Check generated oneOf structure:
assert.Contains(t, code, `
@@ -240,10 +225,6 @@ func (t *ExampleSchema_Item) FromExternalRef0NewPet(v externalRef0.NewPet) error
// FromExternalRef0NewPet overwrites any union data inside the ExampleSchema_Item as the provided externalRef0.NewPet
func (t *ExampleSchema_Item) FromExternalRef0NewPet(v externalRef0.NewPet) error {
`)
-
- // Make sure the generated code is valid:
- checkLint(t, "test.gen.go", []byte(code))
-
}
//go:embed test_spec.yaml
diff --git a/pkg/codegen/configuration.go b/pkg/codegen/configuration.go
index 8f26fad18..90cd6dce3 100644
--- a/pkg/codegen/configuration.go
+++ b/pkg/codegen/configuration.go
@@ -12,12 +12,18 @@ type AdditionalImport struct {
// Configuration defines code generation customizations
type Configuration struct {
- PackageName string `yaml:"package"` // PackageName to generate
- Generate GenerateOptions `yaml:"generate,omitempty"`
- Compatibility CompatibilityOptions `yaml:"compatibility,omitempty"`
- OutputOptions OutputOptions `yaml:"output-options,omitempty"`
- ImportMapping map[string]string `yaml:"import-mapping,omitempty"` // ImportMapping specifies the golang package path for each external reference
- AdditionalImports []AdditionalImport `yaml:"additional-imports,omitempty"`
+ // PackageName to generate the code under
+ PackageName string `yaml:"package"`
+ // Generate specifies which supported output formats to generate
+ Generate GenerateOptions `yaml:"generate,omitempty"`
+ // CompatibilityOptions specifies backward compatibility settings for the code generator
+ Compatibility CompatibilityOptions `yaml:"compatibility,omitempty"`
+ // OutputOptions are used to modify the output code in some way.
+ OutputOptions OutputOptions `yaml:"output-options,omitempty"`
+ // ImportMapping specifies the golang package path for each external reference
+ ImportMapping map[string]string `yaml:"import-mapping,omitempty"`
+ // AdditionalImports defines any additional Go imports to add to the generated code
+ AdditionalImports []AdditionalImport `yaml:"additional-imports,omitempty"`
// NoVCSVersionOverride allows overriding the version of the application for cases where no Version Control System (VCS) is available when building, for instance when using a Nix derivation.
// See documentation for how to use it in examples/no-vcs-version-override/README.md
NoVCSVersionOverride *string `yaml:"-"`
@@ -25,16 +31,28 @@ type Configuration struct {
// GenerateOptions specifies which supported output formats to generate.
type GenerateOptions struct {
- IrisServer bool `yaml:"iris-server,omitempty"` // IrisServer specifies whether to generate iris server boilerplate
- ChiServer bool `yaml:"chi-server,omitempty"` // ChiServer specifies whether to generate chi server boilerplate
- FiberServer bool `yaml:"fiber-server,omitempty"` // FiberServer specifies whether to generate fiber server boilerplate
- EchoServer bool `yaml:"echo-server,omitempty"` // EchoServer specifies whether to generate echo server boilerplate
- GinServer bool `yaml:"gin-server,omitempty"` // GinServer specifies whether to generate gin server boilerplate
- GorillaServer bool `yaml:"gorilla-server,omitempty"` // GorillaServer specifies whether to generate Gorilla server boilerplate
- Strict bool `yaml:"strict-server,omitempty"` // Strict specifies whether to generate strict server wrapper
- Client bool `yaml:"client,omitempty"` // Client specifies whether to generate client boilerplate
- Models bool `yaml:"models,omitempty"` // Models specifies whether to generate type definitions
- EmbeddedSpec bool `yaml:"embedded-spec,omitempty"` // Whether to embed the swagger spec in the generated code
+ // IrisServer specifies whether to generate iris server boilerplate
+ IrisServer bool `yaml:"iris-server,omitempty"`
+ // ChiServer specifies whether to generate chi server boilerplate
+ ChiServer bool `yaml:"chi-server,omitempty"`
+ // FiberServer specifies whether to generate fiber server boilerplate
+ FiberServer bool `yaml:"fiber-server,omitempty"`
+ // EchoServer specifies whether to generate echo server boilerplate
+ EchoServer bool `yaml:"echo-server,omitempty"`
+ // GinServer specifies whether to generate gin server boilerplate
+ GinServer bool `yaml:"gin-server,omitempty"`
+ // GorillaServer specifies whether to generate Gorilla server boilerplate
+ GorillaServer bool `yaml:"gorilla-server,omitempty"`
+ // StdHTTPServer specifies whether to generate stdlib http server boilerplate
+ StdHTTPServer bool `yaml:"std-http-server,omitempty"`
+ // Strict specifies whether to generate strict server wrapper
+ Strict bool `yaml:"strict-server,omitempty"`
+ // Client specifies whether to generate client boilerplate
+ Client bool `yaml:"client,omitempty"`
+ // Models specifies whether to generate type definitions
+ Models bool `yaml:"models,omitempty"`
+ // EmbeddedSpec indicates whether to embed the swagger spec in the generated code
+ EmbeddedSpec bool `yaml:"embedded-spec,omitempty"`
}
// CompatibilityOptions specifies backward compatibility settings for the
@@ -60,7 +78,7 @@ type CompatibilityOptions struct {
// Please see https://github.com/deepmap/oapi-codegen/issues/549
OldAliasing bool `yaml:"old-aliasing,omitempty"`
// When an object contains no members, and only an additionalProperties specification,
- // it is flattened to a map. Set
+ // it is flattened to a map
DisableFlattenAdditionalProperties bool `yaml:"disable-flatten-additional-properties,omitempty"`
// When an object property is both required and readOnly the go model is generated
// as a pointer. Set DisableRequiredReadOnlyAsPointer to true to mark them as non pointer.
@@ -88,25 +106,40 @@ type CompatibilityOptions struct {
// OutputOptions are used to modify the output code in some way.
type OutputOptions struct {
- SkipFmt bool `yaml:"skip-fmt,omitempty"` // Whether to skip go imports on the generated code
- SkipPrune bool `yaml:"skip-prune,omitempty"` // Whether to skip pruning unused components on the generated code
- IncludeTags []string `yaml:"include-tags,omitempty"` // Only include operations that have one of these tags. Ignored when empty.
- ExcludeTags []string `yaml:"exclude-tags,omitempty"` // Exclude operations that have one of these tags. Ignored when empty.
- IncludeOperationIDs []string `yaml:"include-operation-ids,omitempty"` // Only include operations that have one of these operation-ids. Ignored when empty.
- ExcludeOperationIDs []string `yaml:"exclude-operation-ids,omitempty"` // Exclude operations that have one of these operation-ids. Ignored when empty.
- UserTemplates map[string]string `yaml:"user-templates,omitempty"` // Override built-in templates from user-provided files
- UserTemplatesDir string `yaml:"user-templates-dir,omitempty"` // Override built-in tempolates from user-provided directory. Ignored when empty.
+ // Whether to skip go imports on the generated code
+ SkipFmt bool `yaml:"skip-fmt,omitempty"`
+ // Whether to skip pruning unused components on the generated code
+ SkipPrune bool `yaml:"skip-prune,omitempty"`
+ // Only include operations that have one of these tags. Ignored when empty.
+ IncludeTags []string `yaml:"include-tags,omitempty"`
+ // Exclude operations that have one of these tags. Ignored when empty.
+ ExcludeTags []string `yaml:"exclude-tags,omitempty"`
+ // Only include operations that have one of these operation-ids. Ignored when empty.
+ IncludeOperationIDs []string `yaml:"include-operation-ids,omitempty"`
+ // Exclude operations that have one of these operation-ids. Ignored when empty.
+ ExcludeOperationIDs []string `yaml:"exclude-operation-ids,omitempty"`
+ // Override built-in templates from user-provided files
+ UserTemplatesDir string `yaml:"user-templates-dir,omitempty"` // Override built-in tempolates from user-provided directory. Ignored when empty.
+ UserTemplates map[string]string `yaml:"user-templates,omitempty"`
- ExcludeSchemas []string `yaml:"exclude-schemas,omitempty"` // Exclude from generation schemas with given names. Ignored when empty.
- ResponseTypeSuffix string `yaml:"response-type-suffix,omitempty"` // The suffix used for responses types
- ClientTypeName string `yaml:"client-type-name,omitempty"` // Override the default generated client type with the value
- InitialismOverrides bool `yaml:"initialism-overrides,omitempty"` // Whether to use the initialism overrides
- NullableType bool `yaml:"nullable-type,omitempty"` // Whether to generate nullable type for nullable fields
+ // Exclude from generation schemas with given names. Ignored when empty.
+ ExcludeSchemas []string `yaml:"exclude-schemas,omitempty"`
+ // The suffix used for responses types
+ ResponseTypeSuffix string `yaml:"response-type-suffix,omitempty"`
+ // Override the default generated client type with the value
+ ClientTypeName string `yaml:"client-type-name,omitempty"`
+ // Whether to use the initialism overrides
+ InitialismOverrides bool `yaml:"initialism-overrides,omitempty"`
+ // Whether to generate nullable type for nullable fields
+ NullableType bool `yaml:"nullable-type,omitempty"`
// DisableTypeAliasesForType allows defining which OpenAPI `type`s will explicitly not use type aliases
// Currently supports:
// "array"
DisableTypeAliasesForType []string `yaml:"disable-type-aliases-for-type"`
+
+ // NameNormalizer is the method used to normalize Go names and types, for instance converting the text `MyApi` to `MyAPI`. Corresponds with the constants defined for `codegen.NameNormalizerFunction`
+ NameNormalizer string `yaml:"name-normalizer,omitempty"`
}
// UpdateDefaults sets reasonable default values for unset fields in Configuration
@@ -141,6 +174,12 @@ func (o Configuration) Validate() error {
if o.Generate.EchoServer {
nServers++
}
+ if o.Generate.GorillaServer {
+ nServers++
+ }
+ if o.Generate.StdHTTPServer {
+ nServers++
+ }
if o.Generate.GinServer {
nServers++
}
diff --git a/pkg/codegen/extension.go b/pkg/codegen/extension.go
index aa4e183ee..13ed64ce5 100644
--- a/pkg/codegen/extension.go
+++ b/pkg/codegen/extension.go
@@ -22,6 +22,7 @@ const (
extEnumVarNames = "x-enum-varnames"
extEnumNames = "x-enumNames"
extDeprecationReason = "x-deprecated-reason"
+ extOrder = "x-order"
// breu related schema extensions
extBreuEntity = "x-breu-entity"
extBreuEntityType = "x-breu-entity-type"
diff --git a/pkg/codegen/merge_schemas.go b/pkg/codegen/merge_schemas.go
index 419d52bd9..d2ab35bb7 100644
--- a/pkg/codegen/merge_schemas.go
+++ b/pkg/codegen/merge_schemas.go
@@ -86,19 +86,14 @@ func mergeAllOf(allOf []*openapi3.SchemaRef) (openapi3.Schema, error) {
// all of whose fields are composed.
func mergeOpenapiSchemas(s1, s2 openapi3.Schema, allOf bool) (openapi3.Schema, error) {
var result openapi3.Schema
- if s1.Extensions != nil || s2.Extensions != nil {
- result.Extensions = make(map[string]interface{})
- if s1.Extensions != nil {
- for k, v := range s1.Extensions {
- result.Extensions[k] = v
- }
- }
- if s2.Extensions != nil {
- for k, v := range s2.Extensions {
- // TODO: Check for collisions
- result.Extensions[k] = v
- }
- }
+
+ result.Extensions = make(map[string]interface{})
+ for k, v := range s1.Extensions {
+ result.Extensions[k] = v
+ }
+ for k, v := range s2.Extensions {
+ // TODO: Check for collisions
+ result.Extensions[k] = v
}
result.OneOf = append(s1.OneOf, s2.OneOf...)
@@ -125,8 +120,8 @@ func mergeOpenapiSchemas(s1, s2 openapi3.Schema, allOf bool) (openapi3.Schema, e
result.AllOf = append(s1.AllOf, s2.AllOf...)
- if s1.Type != "" && s2.Type != "" && s1.Type != s2.Type {
- return openapi3.Schema{}, errors.New("can not merge incompatible types")
+ if s1.Type.Slice() != nil && s2.Type.Slice() != nil && !equalTypes(s1.Type, s2.Type) {
+ return openapi3.Schema{}, fmt.Errorf("can not merge incompatible types: %v, %v", s1.Type.Slice(), s2.Type.Slice())
}
result.Type = s1.Type
@@ -234,3 +229,21 @@ func mergeOpenapiSchemas(s1, s2 openapi3.Schema, allOf bool) (openapi3.Schema, e
return result, nil
}
+
+func equalTypes(t1 *openapi3.Types, t2 *openapi3.Types) bool {
+ s1 := t1.Slice()
+ s2 := t2.Slice()
+
+ if len(s1) != len(s2) {
+ return false
+ }
+
+ // NOTE that ideally we'd use `slices.Equal` but as we're currently supporting Go 1.20+, we can't use it (yet https://github.com/deepmap/oapi-codegen/issues/1634)
+ for i := range s1 {
+ if s1[i] != s2[i] {
+ return false
+ }
+ }
+
+ return true
+}
diff --git a/pkg/codegen/operations.go b/pkg/codegen/operations.go
index ce0fb8afb..da903810d 100644
--- a/pkg/codegen/operations.go
+++ b/pkg/codegen/operations.go
@@ -25,7 +25,7 @@ import (
"github.com/getkin/kin-openapi/openapi3"
- "github.com/deepmap/oapi-codegen/v2/pkg/util"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/util"
)
type ParameterDefinition struct {
@@ -115,7 +115,7 @@ func (pd *ParameterDefinition) Explode() bool {
}
func (pd ParameterDefinition) GoVariableName() string {
- name := LowercaseFirstCharacter(pd.GoName())
+ name := LowercaseFirstCharacters(pd.GoName())
if IsGoKeyword(name) {
name = "p" + UppercaseFirstCharacter(name)
}
@@ -127,8 +127,8 @@ func (pd ParameterDefinition) GoVariableName() string {
func (pd ParameterDefinition) GoName() string {
goName := pd.ParamName
- if _, ok := pd.Spec.Extensions[extGoName]; ok {
- if extGoFieldName, err := extParseGoFieldName(pd.Spec.Extensions[extGoName]); err == nil {
+ if extension, ok := pd.Spec.Extensions[extGoName]; ok {
+ if extGoFieldName, err := extParseGoFieldName(extension); err == nil {
goName = extGoFieldName
}
}
@@ -197,7 +197,7 @@ func DescribeSecurityDefinition(securityRequirements openapi3.SecurityRequiremen
outDefs := make([]SecurityDefinition, 0)
for _, sr := range securityRequirements {
- for _, k := range SortedSecurityRequirementKeys(sr) {
+ for _, k := range SortedMapKeys(sr) {
v := sr[k]
outDefs = append(outDefs, SecurityDefinition{ProviderName: k, Scopes: v})
}
@@ -279,7 +279,7 @@ func (o *OperationDefinition) GetResponseTypeDefinitions() ([]ResponseTypeDefini
return tds, nil
}
- sortedResponsesKeys := SortedResponsesKeys(o.Spec.Responses.Map())
+ sortedResponsesKeys := SortedMapKeys(o.Spec.Responses.Map())
for _, responseName := range sortedResponsesKeys {
responseRef := o.Spec.Responses.Value(responseName)
@@ -292,7 +292,7 @@ func (o *OperationDefinition) GetResponseTypeDefinitions() ([]ResponseTypeDefini
}
}
- sortedContentKeys := SortedContentKeys(responseRef.Value.Content)
+ sortedContentKeys := SortedMapKeys(responseRef.Value.Content)
for _, contentTypeName := range sortedContentKeys {
contentType := responseRef.Value.Content[contentTypeName]
// We can only generate a type if we have a schema:
@@ -307,21 +307,21 @@ func (o *OperationDefinition) GetResponseTypeDefinitions() ([]ResponseTypeDefini
// HAL+JSON:
case StringInArray(contentTypeName, contentTypesHalJSON):
- typeName = fmt.Sprintf("HALJSON%s", ToCamelCase(responseName))
+ typeName = fmt.Sprintf("HALJSON%s", nameNormalizer(responseName))
case "application/json" == contentTypeName:
// if it's the standard application/json
- typeName = fmt.Sprintf("JSON%s", ToCamelCase(responseName))
+ typeName = fmt.Sprintf("JSON%s", nameNormalizer(responseName))
// Vendored JSON
case StringInArray(contentTypeName, contentTypesJSON) || util.IsMediaTypeJson(contentTypeName):
- baseTypeName := fmt.Sprintf("%s%s", ToCamelCase(contentTypeName), ToCamelCase(responseName))
+ baseTypeName := fmt.Sprintf("%s%s", nameNormalizer(contentTypeName), nameNormalizer(responseName))
typeName = strings.ReplaceAll(baseTypeName, "Json", "JSON")
// YAML:
case StringInArray(contentTypeName, contentTypesYAML):
- typeName = fmt.Sprintf("YAML%s", ToCamelCase(responseName))
+ typeName = fmt.Sprintf("YAML%s", nameNormalizer(responseName))
// XML:
case StringInArray(contentTypeName, contentTypesXML):
- typeName = fmt.Sprintf("XML%s", ToCamelCase(responseName))
+ typeName = fmt.Sprintf("XML%s", nameNormalizer(responseName))
default:
continue
}
@@ -544,7 +544,7 @@ func OperationDefinitions(swagger *openapi3.T, initialismOverrides bool) ([]Oper
return operations, nil
}
- for _, requestPath := range SortedPathsKeys(swagger.Paths.Map()) {
+ for _, requestPath := range SortedMapKeys(swagger.Paths.Map()) {
pathItem := swagger.Paths.Value(requestPath)
// These are parameters defined for all methods on a given path. They
// are shared by all methods.
@@ -556,7 +556,7 @@ func OperationDefinitions(swagger *openapi3.T, initialismOverrides bool) ([]Oper
// Each path can have a number of operations, POST, GET, OPTIONS, etc.
pathOps := pathItem.Operations()
- for _, opName := range SortedOperationsKeys(pathOps) {
+ for _, opName := range SortedMapKeys(pathOps) {
op := pathOps[opName]
if pathItem.Servers != nil {
op.Servers = &pathItem.Servers
@@ -569,7 +569,7 @@ func OperationDefinitions(swagger *openapi3.T, initialismOverrides bool) ([]Oper
opName, requestPath, err)
}
} else {
- op.OperationID = toCamelCaseFunc(op.OperationID)
+ op.OperationID = nameNormalizer(op.OperationID)
}
op.OperationID = typeNamePrefix(op.OperationID) + op.OperationID
@@ -617,7 +617,7 @@ func OperationDefinitions(swagger *openapi3.T, initialismOverrides bool) ([]Oper
HeaderParams: FilterParameterDefinitionByType(allParams, "header"),
QueryParams: FilterParameterDefinitionByType(allParams, "query"),
CookieParams: FilterParameterDefinitionByType(allParams, "cookie"),
- OperationId: toCamelCaseFunc(op.OperationID),
+ OperationId: nameNormalizer(op.OperationID),
// Replace newlines in summary.
Summary: op.Summary,
Method: opName,
@@ -672,7 +672,7 @@ func generateDefaultOperationID(opName string, requestPath string, toCamelCaseFu
}
}
- return toCamelCaseFunc(operationId), nil
+ return nameNormalizer(operationId), nil
}
// GenerateBodyDefinitions turns the Swagger body definitions into a list of our body
@@ -686,7 +686,7 @@ func GenerateBodyDefinitions(operationID string, bodyOrRef *openapi3.RequestBody
var bodyDefinitions []RequestBodyDefinition
var typeDefinitions []TypeDefinition
- for _, contentType := range SortedContentKeys(body.Content) {
+ for _, contentType := range SortedMapKeys(body.Content) {
content := body.Content[contentType]
var tag string
var defaultBody bool
@@ -781,7 +781,7 @@ func GenerateResponseDefinitions(operationID string, responses map[string]*opena
// do not let multiple status codes ref to same response, it will break the type switch
refSet := make(map[string]struct{})
- for _, statusCode := range SortedResponsesKeys(responses) {
+ for _, statusCode := range SortedMapKeys(responses) {
responseOrRef := responses[statusCode]
if responseOrRef == nil {
continue
@@ -790,7 +790,7 @@ func GenerateResponseDefinitions(operationID string, responses map[string]*opena
var responseContentDefinitions []ResponseContentDefinition
- for _, contentType := range SortedContentKeys(response.Content) {
+ for _, contentType := range SortedMapKeys(response.Content) {
content := response.Content[contentType]
var tag string
switch {
@@ -828,7 +828,7 @@ func GenerateResponseDefinitions(operationID string, responses map[string]*opena
}
var responseHeaderDefinitions []ResponseHeaderDefinition
- for _, headerName := range SortedHeadersKeys(response.Headers) {
+ for _, headerName := range SortedMapKeys(response.Headers) {
header := response.Headers[headerName]
contentSchema, err := GenerateGoSchema(header.Value.Schema, []string{})
if err != nil {
@@ -875,11 +875,11 @@ func GenerateTypeDefsForOperation(op OperationDefinition) []TypeDefinition {
// Now, go through all the additional types we need to declare.
for _, param := range op.AllParams() {
- typeDefs = append(typeDefs, param.Schema.GetAdditionalTypeDefs()...)
+ typeDefs = append(typeDefs, param.Schema.AdditionalTypes...)
}
for _, body := range op.Bodies {
- typeDefs = append(typeDefs, body.Schema.GetAdditionalTypeDefs()...)
+ typeDefs = append(typeDefs, body.Schema.AdditionalTypes...)
}
return typeDefs
}
@@ -1003,11 +1003,17 @@ func GenerateGorillaServer(t *template.Template, operations []OperationDefinitio
return GenerateTemplates([]string{"gorilla/gorilla-interface.tmpl", "gorilla/gorilla-middleware.tmpl", "gorilla/gorilla-register.tmpl"}, t, operations)
}
+// GenerateStdHTTPServer generates all the go code for the ServerInterface as well as
+// all the wrapper functions around our handlers.
+func GenerateStdHTTPServer(t *template.Template, operations []OperationDefinition) (string, error) {
+ return GenerateTemplates([]string{"stdhttp/std-http-interface.tmpl", "stdhttp/std-http-middleware.tmpl", "stdhttp/std-http-handler.tmpl"}, t, operations)
+}
+
func GenerateStrictServer(t *template.Template, operations []OperationDefinition, opts Configuration) (string, error) {
var templates []string
- if opts.Generate.ChiServer || opts.Generate.GorillaServer {
+ if opts.Generate.ChiServer || opts.Generate.GorillaServer || opts.Generate.StdHTTPServer {
templates = append(templates, "strict/strict-interface.tmpl", "strict/strict-http.tmpl")
}
if opts.Generate.EchoServer {
diff --git a/pkg/codegen/schema.go b/pkg/codegen/schema.go
index 1b7d38cdb..ab0dd6377 100644
--- a/pkg/codegen/schema.go
+++ b/pkg/codegen/schema.go
@@ -80,12 +80,7 @@ func (s *Schema) AddProperty(p Property) error {
}
func (s Schema) GetAdditionalTypeDefs() []TypeDefinition {
- var result []TypeDefinition
- for _, p := range s.Properties {
- result = append(result, p.Schema.GetAdditionalTypeDefs()...)
- }
- result = append(result, s.AdditionalTypes...)
- return result
+ return s.AdditionalTypes
}
type Property struct {
@@ -102,7 +97,14 @@ type Property struct {
}
func (p Property) GoFieldName() string {
- return SchemaNameToTypeName(p.JsonFieldName)
+ goFieldName := p.JsonFieldName
+ if extension, ok := p.Extensions[extGoName]; ok {
+ if extGoFieldName, err := extParseGoFieldName(extension); err == nil {
+ goFieldName = extGoFieldName
+ }
+ }
+
+ return SchemaNameToTypeName(goFieldName)
}
func (p Property) GoTypeDef() string {
@@ -321,13 +323,13 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) {
// Schema type and format, eg. string / binary
t := schema.Type
// Handle objects and empty schemas first as a special case
- if t == "" || t == "object" {
+ if t.Slice() == nil || t.Is("object") {
var outType string
if len(schema.Properties) == 0 && !SchemaHasAdditionalProperties(schema) && schema.AnyOf == nil && schema.OneOf == nil {
// If the object has no properties or additional properties, we
// have some special cases for its type.
- if t == "object" {
+ if t.Is("object") {
// We have an object with no properties. This is a generic object
// expressed as a map.
outType = "map[string]interface{}"
@@ -437,6 +439,9 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) {
Deprecated: p.Value.Deprecated,
}
outSchema.Properties = append(outSchema.Properties, prop)
+ if len(pSchema.AdditionalTypes) > 0 {
+ outSchema.AdditionalTypes = append(outSchema.AdditionalTypes, pSchema.AdditionalTypes...)
+ }
}
if schema.AnyOf != nil {
@@ -470,7 +475,7 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) {
Description: newTypeDef.Schema.Description,
GoType: typeName,
DefineViaAlias: true,
- AdditionalTypes: []TypeDefinition{newTypeDef},
+ AdditionalTypes: append(outSchema.AdditionalTypes, newTypeDef),
}
}
@@ -492,8 +497,8 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) {
enumNames := enumValues
for _, key := range []string{extEnumVarNames, extEnumNames} {
- if _, ok := schema.Extensions[key]; ok {
- if extEnumNames, err := extParseEnumVarNames(schema.Extensions[key]); err == nil {
+ if extension, ok := schema.Extensions[key]; ok {
+ if extEnumNames, err := extParseEnumVarNames(extension); err == nil {
enumNames = extEnumNames
break
}
@@ -552,8 +557,7 @@ func oapiSchemaToGoType(schema *openapi3.Schema, path []string, outSchema *Schem
f := schema.Format
t := schema.Type
- switch t {
- case "array":
+ if t.Is("array") {
// For arrays, we'll get the type of the Items and throw a
// [] in front of it.
arrayType, err := GenerateGoSchema(schema.Items, path)
@@ -585,7 +589,7 @@ func oapiSchemaToGoType(schema *openapi3.Schema, path []string, outSchema *Schem
outSchema.DefineViaAlias = false
}
- case "integer":
+ } else if t.Is("integer") {
// We default to int if format doesn't ask for something else.
if f == "int64" {
outSchema.GoType = "int64"
@@ -611,7 +615,7 @@ func oapiSchemaToGoType(schema *openapi3.Schema, path []string, outSchema *Schem
outSchema.GoType = "int"
}
outSchema.DefineViaAlias = true
- case "number":
+ } else if t.Is("number") {
// We default to float for "number"
if f == "double" {
outSchema.GoType = "float64"
@@ -621,13 +625,13 @@ func oapiSchemaToGoType(schema *openapi3.Schema, path []string, outSchema *Schem
return fmt.Errorf("invalid number format: %s", f)
}
outSchema.DefineViaAlias = true
- case "boolean":
+ } else if t.Is("boolean") {
if f != "" {
return fmt.Errorf("invalid format (%s) for boolean", f)
}
outSchema.GoType = "bool"
outSchema.DefineViaAlias = true
- case "string":
+ } else if t.Is("string") {
// Special case string formats here.
switch f {
case "byte":
@@ -650,8 +654,8 @@ func oapiSchemaToGoType(schema *openapi3.Schema, path []string, outSchema *Schem
outSchema.GoType = "string"
}
outSchema.DefineViaAlias = true
- default:
- return fmt.Errorf("unhandled Schema type: %s", t)
+ } else {
+ return fmt.Errorf("unhandled Schema type: %v", t)
}
return nil
}
@@ -679,11 +683,6 @@ func GenFieldsFromProperties(props []Property, entity, entitype string) []string
field := ""
goFieldName := p.GoFieldName()
- if _, ok := p.Extensions[extGoName]; ok {
- if extGoFieldName, err := extParseGoFieldName(p.Extensions[extGoName]); err == nil {
- goFieldName = extGoFieldName
- }
- }
// Add a comment to a field in case we have one, otherwise skip.
if p.Description != "" {
@@ -698,8 +697,8 @@ func GenFieldsFromProperties(props []Property, entity, entitype string) []string
if p.Deprecated {
// This comment has to be on its own line for godoc & IDEs to pick up
var deprecationReason string
- if _, ok := p.Extensions[extDeprecationReason]; ok {
- if extOmitEmpty, err := extParseDeprecationReason(p.Extensions[extDeprecationReason]); err == nil {
+ if extension, ok := p.Extensions[extDeprecationReason]; ok {
+ if extOmitEmpty, err := extParseDeprecationReason(extension); err == nil {
deprecationReason = extOmitEmpty
}
}
@@ -748,8 +747,8 @@ func GenFieldsFromProperties(props []Property, entity, entitype string) []string
}
// Support x-go-json-ignore
- if _, ok := p.Extensions[extPropGoJsonIgnore]; ok {
- if goJsonIgnore, err := extParseGoJsonIgnore(p.Extensions[extPropGoJsonIgnore]); err == nil && goJsonIgnore {
+ if extension, ok := p.Extensions[extPropGoJsonIgnore]; ok {
+ if goJsonIgnore, err := extParseGoJsonIgnore(extension); err == nil && goJsonIgnore {
fieldTags["json"] = "-"
}
}
@@ -762,14 +761,14 @@ func GenFieldsFromProperties(props []Property, entity, entitype string) []string
// Support x-oapi-codegen-extra-tags
if extension, ok := p.Extensions[extPropExtraTags]; ok {
if tags, err := extExtraTags(extension); err == nil {
- keys := SortedStringKeys(tags)
+ keys := SortedMapKeys(tags)
for _, k := range keys {
fieldTags[k] = tags[k]
}
}
}
// Convert the fieldTags map into Go field annotations.
- keys := SortedStringKeys(fieldTags)
+ keys := SortedMapKeys(fieldTags)
tags := make([]string, len(keys))
for i, k := range keys {
tags[i] = fmt.Sprintf(`%s:"%s"`, k, fieldTags[k])
diff --git a/pkg/codegen/template_helpers.go b/pkg/codegen/template_helpers.go
index 3cf337bcb..84293b5d3 100644
--- a/pkg/codegen/template_helpers.go
+++ b/pkg/codegen/template_helpers.go
@@ -24,7 +24,7 @@ import (
"golang.org/x/text/cases"
"golang.org/x/text/language"
- "github.com/deepmap/oapi-codegen/v2/pkg/util"
+ "github.com/oapi-codegen/oapi-codegen/v2/pkg/util"
)
const (
@@ -144,15 +144,15 @@ func genResponseUnmarshal(op *OperationDefinition) string {
}
// If we made it this far then we need to handle unmarshaling for each content-type:
- sortedContentKeys := SortedContentKeys(responseRef.Value.Content)
+ SortedMapKeys := SortedMapKeys(responseRef.Value.Content)
jsonCount := 0
- for _, contentTypeName := range sortedContentKeys {
+ for _, contentTypeName := range SortedMapKeys {
if StringInArray(contentTypeName, contentTypesJSON) || util.IsMediaTypeJson(contentTypeName) {
jsonCount++
}
}
- for _, contentTypeName := range sortedContentKeys {
+ for _, contentTypeName := range SortedMapKeys {
// We get "interface{}" when using "anyOf" or "oneOf" (which doesn't work with Go types):
if typeDefinition.TypeName == "interface{}" {
@@ -229,11 +229,11 @@ func genResponseUnmarshal(op *OperationDefinition) string {
// See: https://github.com/deepmap/oapi-codegen/issues/127 for why we handle this in two separate
// groups.
fmt.Fprintf(buffer, "switch {\n")
- for _, caseClauseKey := range SortedStringKeys(handledCaseClauses) {
+ for _, caseClauseKey := range SortedMapKeys(handledCaseClauses) {
fmt.Fprintf(buffer, "%s\n", handledCaseClauses[caseClauseKey])
}
- for _, caseClauseKey := range SortedStringKeys(unhandledCaseClauses) {
+ for _, caseClauseKey := range SortedMapKeys(unhandledCaseClauses) {
fmt.Fprintf(buffer, "%s\n", unhandledCaseClauses[caseClauseKey])
}
@@ -363,6 +363,7 @@ var TemplateFunctions = template.FuncMap{
"swaggerUriToChiUri": SwaggerUriToChiUri,
"swaggerUriToGinUri": SwaggerUriToGinUri,
"swaggerUriToGorillaUri": SwaggerUriToGorillaUri,
+ "swaggerUriToStdHttpUri": SwaggerUriToStdHttpUri,
"lcFirst": LowercaseFirstCharacter,
"ucFirst": UppercaseFirstCharacter,
"ucFirstWithPkgName": UppercaseFirstCharacterWithPkgName,
diff --git a/pkg/codegen/templates/fiber/fiber-handler.tmpl b/pkg/codegen/templates/fiber/fiber-handler.tmpl
index 4a55b3c51..7745e0d88 100644
--- a/pkg/codegen/templates/fiber/fiber-handler.tmpl
+++ b/pkg/codegen/templates/fiber/fiber-handler.tmpl
@@ -16,7 +16,7 @@ Handler: si,
}
for _, m := range options.Middlewares {
- router.Use(m)
+ router.Use(fiber.Handler(m))
}
{{end}}
{{range .}}
diff --git a/pkg/codegen/templates/imports.tmpl b/pkg/codegen/templates/imports.tmpl
index cc1f51587..4d1942242 100644
--- a/pkg/codegen/templates/imports.tmpl
+++ b/pkg/codegen/templates/imports.tmpl
@@ -1,3 +1,6 @@
+{{- if opts.Generate.StdHTTPServer}}//go:build go1.22
+
+{{- end}}
// Package {{.PackageName}} provides primitives to interact with the openapi HTTP API.
//
// Code generated by {{.ModuleName}} version {{.Version}} DO NOT EDIT.
@@ -24,6 +27,7 @@ import (
"time"
"github.com/oapi-codegen/runtime"
+ "github.com/oapi-codegen/nullable"
strictecho "github.com/oapi-codegen/runtime/strictmiddleware/echo"
strictgin "github.com/oapi-codegen/runtime/strictmiddleware/gin"
strictiris "github.com/oapi-codegen/runtime/strictmiddleware/iris"
diff --git a/pkg/codegen/templates/stdhttp/std-http-handler.tmpl b/pkg/codegen/templates/stdhttp/std-http-handler.tmpl
new file mode 100644
index 000000000..9542fabae
--- /dev/null
+++ b/pkg/codegen/templates/stdhttp/std-http-handler.tmpl
@@ -0,0 +1,49 @@
+// Handler creates http.Handler with routing matching OpenAPI spec.
+func Handler(si ServerInterface) http.Handler {
+ return HandlerWithOptions(si, StdHTTPServerOptions{})
+}
+
+type StdHTTPServerOptions struct {
+ BaseURL string
+ BaseRouter *http.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 *http.ServeMux) http.Handler {
+ return HandlerWithOptions(si, StdHTTPServerOptions {
+ BaseRouter: m,
+ })
+}
+
+func HandlerFromMuxWithBaseURL(si ServerInterface, m *http.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)
+ }
+ }
+{{if .}}
+ wrapper := ServerInterfaceWrapper{
+ Handler: si,
+ HandlerMiddlewares: options.Middlewares,
+ ErrorHandlerFunc: options.ErrorHandlerFunc,
+ }
+{{end}}
+{{range .}}m.HandleFunc("{{.Method }} "+options.BaseURL+"{{.Path | swaggerUriToStdHttpUri}}", wrapper.{{.OperationId}})
+{{end}}
+ return m
+}
diff --git a/pkg/codegen/templates/stdhttp/std-http-interface.tmpl b/pkg/codegen/templates/stdhttp/std-http-interface.tmpl
new file mode 100644
index 000000000..79a51fd75
--- /dev/null
+++ b/pkg/codegen/templates/stdhttp/std-http-interface.tmpl
@@ -0,0 +1,7 @@
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+{{range .}}{{.SummaryAsComment }}
+// ({{.Method}} {{.Path}})
+{{.OperationId}}(w http.ResponseWriter, r *http.Request{{genParamArgs .PathParams}}{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}})
+{{end}}
+}
diff --git a/pkg/codegen/templates/stdhttp/std-http-middleware.tmpl b/pkg/codegen/templates/stdhttp/std-http-middleware.tmpl
new file mode 100644
index 000000000..8ef7187a2
--- /dev/null
+++ b/pkg/codegen/templates/stdhttp/std-http-middleware.tmpl
@@ -0,0 +1,261 @@
+// 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
+
+{{range .}}{{$opid := .OperationId}}
+
+// {{$opid}} operation middleware
+func (siw *ServerInterfaceWrapper) {{$opid}}(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+ {{if or .RequiresParamObject (gt (len .PathParams) 0) }}
+ var err error
+ {{end}}
+
+ {{range .PathParams}}// ------------- Path parameter "{{.ParamName}}" -------------
+ var {{$varName := .GoVariableName}}{{$varName}} {{.TypeDef}}
+
+ {{if .IsPassThrough}}
+ {{$varName}} = r.PathValue("{{.ParamName}}")
+ {{end}}
+ {{if .IsJson}}
+ err = json.Unmarshal([]byte(r.PathValue("{{.ParamName}}")), &{{$varName}})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
+ return
+ }
+ {{end}}
+ {{if .IsStyled}}
+ err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", r.PathValue("{{.ParamName}}"), &{{$varName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: {{.Explode}}, Required: {{.Required}}})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
+ return
+ }
+ {{end}}
+
+ {{end}}
+
+{{range .SecurityDefinitions}}
+ ctx = context.WithValue(ctx, {{.ProviderName | sanitizeGoIdentity | ucFirst}}Scopes, {{toStringArray .Scopes}})
+{{end}}
+
+ {{if .RequiresParamObject}}
+ // Parameter object where we will unmarshal all parameters from the context
+ var params {{.OperationId}}Params
+
+ {{range $paramIdx, $param := .QueryParams}}
+ {{- if (or (or .Required .IsPassThrough) (or .IsJson .IsStyled)) -}}
+ // ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" -------------
+ {{ end }}
+ {{ if (or (or .Required .IsPassThrough) .IsJson) }}
+ if paramValue := r.URL.Query().Get("{{.ParamName}}"); paramValue != "" {
+
+ {{if .IsPassThrough}}
+ params.{{.GoName}} = {{if not .Required}}&{{end}}paramValue
+ {{end}}
+
+ {{if .IsJson}}
+ var value {{.TypeDef}}
+ err = json.Unmarshal([]byte(paramValue), &value)
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
+ return
+ }
+
+ params.{{.GoName}} = {{if not .Required}}&{{end}}value
+ {{end}}
+ }{{if .Required}} else {
+ siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "{{.ParamName}}"})
+ return
+ }{{end}}
+ {{end}}
+ {{if .IsStyled}}
+ err = runtime.BindQueryParameter("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", r.URL.Query(), ¶ms.{{.GoName}})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
+ return
+ }
+ {{end}}
+ {{end}}
+
+ {{if .HeaderParams}}
+ headers := r.Header
+
+ {{range .HeaderParams}}// ------------- {{if .Required}}Required{{else}}Optional{{end}} header parameter "{{.ParamName}}" -------------
+ if valueList, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found {
+ var {{.GoName}} {{.TypeDef}}
+ n := len(valueList)
+ if n != 1 {
+ siw.ErrorHandlerFunc(w, r, &TooManyValuesForParamError{ParamName: "{{.ParamName}}", Count: n})
+ return
+ }
+
+ {{if .IsPassThrough}}
+ params.{{.GoName}} = {{if not .Required}}&{{end}}valueList[0]
+ {{end}}
+
+ {{if .IsJson}}
+ err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
+ return
+ }
+ {{end}}
+
+ {{if .IsStyled}}
+ err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", valueList[0], &{{.GoName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: {{.Explode}}, Required: {{.Required}}})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
+ return
+ }
+ {{end}}
+
+ params.{{.GoName}} = {{if not .Required}}&{{end}}{{.GoName}}
+
+ } {{if .Required}}else {
+ err := fmt.Errorf("Header parameter {{.ParamName}} is required, but not found")
+ siw.ErrorHandlerFunc(w, r, &RequiredHeaderError{ParamName: "{{.ParamName}}", Err: err})
+ return
+ }{{end}}
+
+ {{end}}
+ {{end}}
+
+ {{range .CookieParams}}
+ var cookie *http.Cookie
+
+ if cookie, err = r.Cookie("{{.ParamName}}"); err == nil {
+
+ {{- if .IsPassThrough}}
+ params.{{.GoName}} = {{if not .Required}}&{{end}}cookie.Value
+ {{end}}
+
+ {{- if .IsJson}}
+ var value {{.TypeDef}}
+ var decoded string
+ decoded, err := url.QueryUnescape(cookie.Value)
+ if err != nil {
+ err = fmt.Errorf("Error unescaping cookie parameter '{{.ParamName}}'")
+ siw.ErrorHandlerFunc(w, r, &UnescapedCookieParamError{ParamName: "{{.ParamName}}", Err: err})
+ return
+ }
+
+ err = json.Unmarshal([]byte(decoded), &value)
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &UnmarshalingParamError{ParamName: "{{.ParamName}}", Err: err})
+ return
+ }
+
+ params.{{.GoName}} = {{if not .Required}}&{{end}}value
+ {{end}}
+
+ {{- if .IsStyled}}
+ var value {{.TypeDef}}
+ err = runtime.BindStyledParameterWithOptions("simple", "{{.ParamName}}", cookie.Value, &value, runtime.BindStyledParameterOptions{Explode: {{.Explode}}, Required: {{.Required}}})
+ if err != nil {
+ siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "{{.ParamName}}", Err: err})
+ return
+ }
+ params.{{.GoName}} = {{if not .Required}}&{{end}}value
+ {{end}}
+
+ }
+
+ {{- if .Required}} else {
+ siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "{{.ParamName}}"})
+ return
+ }
+ {{- end}}
+ {{end}}
+ {{end}}
+
+ handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ siw.Handler.{{.OperationId}}(w, r{{genParamNames .PathParams}}{{if .RequiresParamObject}}, params{{end}})
+ }))
+
+ {{if opts.Compatibility.ApplyChiMiddlewareFirstToLast}}
+ for i := len(siw.HandlerMiddlewares) -1; i >= 0; i-- {
+ handler = siw.HandlerMiddlewares[i](handler)
+ }
+ {{else}}
+ for _, middleware := range siw.HandlerMiddlewares {
+ handler = middleware(handler)
+ }
+ {{end}}
+
+ handler.ServeHTTP(w, r.WithContext(ctx))
+}
+{{end}}
+
+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)
+}
diff --git a/pkg/codegen/utils.go b/pkg/codegen/utils.go
index 16d92ac74..b955e5290 100644
--- a/pkg/codegen/utils.go
+++ b/pkg/codegen/utils.go
@@ -14,6 +14,7 @@
package codegen
import (
+ "bytes"
"fmt"
"go/token"
"net/url"
@@ -31,8 +32,70 @@ var (
pathParamRE *regexp.Regexp
predeclaredSet map[string]struct{}
separatorSet map[rune]struct{}
+ nameNormalizer NameNormalizer = ToCamelCase
)
+type NameNormalizerFunction string
+
+const (
+ // NameNormalizerFunctionUnset is the default case, where the `name-normalizer` option hasn't been set. This will use the `ToCamelCase` function.
+ //
+ // See the docs for `NameNormalizerFunctionToCamelCase` for more details.
+ NameNormalizerFunctionUnset NameNormalizerFunction = ""
+ // NameNormalizerFunctionToCamelCase will use the `ToCamelCase` function.
+ //
+ // For instance:
+ //
+ // - `getHttpPet` => `GetHttpPet`
+ // - `OneOf2things` => `OneOf2things`
+ NameNormalizerFunctionToCamelCase NameNormalizerFunction = "ToCamelCase"
+ // NameNormalizerFunctionToCamelCaseWithDigits will use the `NameNormalizerFunctionToCamelCaseWithDigits` function.
+ //
+ // For instance:
+ //
+ // - `getHttpPet` => `GetHttpPet`
+ // - `OneOf2things` => `OneOf2Things`
+ NameNormalizerFunctionToCamelCaseWithDigits NameNormalizerFunction = "ToCamelCaseWithDigits"
+ // NameNormalizerFunctionToCamelCaseWithInitialisms will use the `NameNormalizerFunctionToCamelCaseWithInitialisms` function.
+ //
+ // For instance:
+ //
+ // - `getHttpPet` => `GetHTTPPet`
+ // - `OneOf2things` => `OneOf2things`
+ NameNormalizerFunctionToCamelCaseWithInitialisms NameNormalizerFunction = "ToCamelCaseWithInitialisms"
+)
+
+// NameNormalizer is a function that takes a type name, and returns that type name converted into a different format.
+//
+// This may be an Operation ID i.e. `retrieveUserRequests` or a Schema name i.e. `BigBlockOfCheese`
+//
+// NOTE: this must return a string that can be used as a valid Go type name
+type NameNormalizer func(string) string
+
+type NameNormalizerMap map[NameNormalizerFunction]NameNormalizer
+
+func (m NameNormalizerMap) Options() []string {
+ options := make([]string, 0, len(m))
+
+ for key := range NameNormalizers {
+ options = append(options, string(key))
+ }
+
+ sort.Strings(options)
+
+ return options
+}
+
+// NameNormalizers contains the valid options for `NameNormalizerFunction`s that `oapi-codegen` supports.
+//
+// If you are calling `oapi-codegen` as a library, this allows you to specify your own normalisation types before generating code.
+var NameNormalizers = NameNormalizerMap{
+ NameNormalizerFunctionUnset: ToCamelCase,
+ NameNormalizerFunctionToCamelCase: ToCamelCase,
+ NameNormalizerFunctionToCamelCaseWithDigits: ToCamelCaseWithDigits,
+ NameNormalizerFunctionToCamelCaseWithInitialisms: ToCamelCaseWithInitialisms,
+}
+
func init() {
pathParamRE = regexp.MustCompile(`{[.;?]?([^{}*]+)\*?}`)
@@ -133,6 +196,27 @@ func LowercaseFirstCharacter(str string) string {
return string(runes)
}
+// Lowercase the first upper characters in a string for case of abbreviation.
+// This assumes UTF-8, so we have to be careful with unicode, don't treat it as a byte array.
+func LowercaseFirstCharacters(str string) string {
+ if str == "" {
+ return ""
+ }
+
+ runes := []rune(str)
+
+ for i := 0; i < len(runes); i++ {
+ next := i + 1
+ if i != 0 && next < len(runes) && unicode.IsLower(runes[next]) {
+ break
+ }
+
+ runes[i] = unicode.ToLower(runes[i])
+ }
+
+ return string(runes)
+}
+
// ToCamelCase will convert query-arg style strings to CamelCase. We will
// use `., -, +, :, ;, _, ~, ' ', (, ), {, }, [, ]` as valid delimiters for words.
// So, "word.word-word+word:word;word_word~word word(word)word{word}[word]"
@@ -161,6 +245,69 @@ func ToCamelCase(str string) string {
return n
}
+// ToCamelCaseWithDigits function will convert query-arg style strings to CamelCase. We will
+// use `., -, +, :, ;, _, ~, ' ', (, ), {, }, [, ]` as valid delimiters for words.
+// The difference of ToCamelCase that letter after a number becomes capitalized.
+// So, "word.word-word+word:word;word_word~word word(word)word{word}[word]3word"
+// would be converted to WordWordWordWordWordWordWordWordWordWordWordWordWord3Word
+func ToCamelCaseWithDigits(s string) string {
+ res := bytes.NewBuffer(nil)
+ capNext := true
+ for _, v := range s {
+ if unicode.IsUpper(v) {
+ res.WriteRune(v)
+ capNext = false
+ continue
+ }
+ if unicode.IsDigit(v) {
+ res.WriteRune(v)
+ capNext = true
+ continue
+ }
+ if unicode.IsLower(v) {
+ if capNext {
+ res.WriteRune(unicode.ToUpper(v))
+ } else {
+ res.WriteRune(v)
+ }
+ capNext = false
+ continue
+ }
+ capNext = true
+ }
+ return res.String()
+}
+
+// ToCamelCaseWithInitialisms function will convert query-arg style strings to CamelCase with initialisms in uppercase.
+// So, httpOperationId would be converted to HTTPOperationID
+func ToCamelCaseWithInitialisms(s string) string {
+ parts := camelCaseMatchParts.FindAllString(ToCamelCaseWithDigits(s), -1)
+ for i := range parts {
+ if v, ok := initialismsMap[strings.ToLower(parts[i])]; ok {
+ parts[i] = v
+ }
+ }
+ return strings.Join(parts, "")
+}
+
+var camelCaseMatchParts = regexp.MustCompile(`[\p{Lu}\d]+([\p{Ll}\d]+|$)`)
+
+// initialismsMap stores initialisms as "lower(initialism) -> initialism" map.
+// List of initialisms was taken from https://staticcheck.io/docs/configuration/options/#initialisms.
+var initialismsMap = makeInitialismsMap([]string{
+ "ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON",
+ "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID",
+ "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS", "SIP", "RTP", "AMQP", "DB", "TS",
+})
+
+func makeInitialismsMap(l []string) map[string]string {
+ m := make(map[string]string, len(l))
+ for i := range l {
+ m[strings.ToLower(l[i])] = l[i]
+ }
+ return m
+}
+
func ToCamelCaseWithInitialism(str string) string {
return replaceInitialism(ToCamelCase(str))
}
@@ -190,8 +337,21 @@ func mediaTypeToCamelCase(s string) string {
return ToCamelCaseWithInitialism(s)
}
+// SortedMapKeys takes a map with keys of type string and returns a slice of those
+// keys sorted lexicographically.
+func SortedMapKeys[T any](m map[string]T) []string {
+ keys := make([]string, 0, len(m))
+ for k := range m {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ return keys
+}
+
// SortedSchemaKeys returns the keys of the given SchemaRef dictionary in sorted
-// order, since Golang scrambles dictionary keys
+// order, since Golang scrambles dictionary keys. This isn't a generic key sort, because
+// we support an extension to grant specific orders to schemas to help control output
+// ordering.
func SortedSchemaKeys(dict map[string]*openapi3.SchemaRef) []string {
keys := make([]string, len(dict))
orders := make(map[string]int64, len(dict))
@@ -205,7 +365,7 @@ func SortedSchemaKeys(dict map[string]*openapi3.SchemaRef) []string {
continue
}
- ext := v.Value.Extensions["x-order"]
+ ext := v.Value.Extensions[extOrder]
if ext == nil {
continue
}
@@ -225,112 +385,6 @@ func SortedSchemaKeys(dict map[string]*openapi3.SchemaRef) []string {
return keys
}
-// SortedPathsKeys is the same as above, except it sorts the keys for a Paths
-// dictionary.
-func SortedPathsKeys(dict map[string]*openapi3.PathItem) []string {
- keys := make([]string, len(dict))
- i := 0
- for key := range dict {
- keys[i] = key
- i++
- }
- sort.Strings(keys)
- return keys
-}
-
-// SortedOperationsKeys returns Operation dictionary keys in sorted order
-func SortedOperationsKeys(dict map[string]*openapi3.Operation) []string {
- keys := make([]string, len(dict))
- i := 0
- for key := range dict {
- keys[i] = key
- i++
- }
- sort.Strings(keys)
- return keys
-}
-
-// SortedResponsesKeys returns Responses dictionary keys in sorted order
-func SortedResponsesKeys(dict map[string]*openapi3.ResponseRef) []string {
- keys := make([]string, len(dict))
- i := 0
- for key := range dict {
- keys[i] = key
- i++
- }
- sort.Strings(keys)
- return keys
-}
-
-func SortedHeadersKeys(dict openapi3.Headers) []string {
- keys := make([]string, len(dict))
- i := 0
- for key := range dict {
- keys[i] = key
- i++
- }
- sort.Strings(keys)
- return keys
-}
-
-// SortedContentKeys returns Content dictionary keys in sorted order
-func SortedContentKeys(dict openapi3.Content) []string {
- keys := make([]string, len(dict))
- i := 0
- for key := range dict {
- keys[i] = key
- i++
- }
- sort.Strings(keys)
- return keys
-}
-
-// SortedStringKeys returns string map keys in sorted order
-func SortedStringKeys(dict map[string]string) []string {
- keys := make([]string, len(dict))
- i := 0
- for key := range dict {
- keys[i] = key
- i++
- }
- sort.Strings(keys)
- return keys
-}
-
-// SortedParameterKeys returns sorted keys for a ParameterRef dict
-func SortedParameterKeys(dict map[string]*openapi3.ParameterRef) []string {
- keys := make([]string, len(dict))
- i := 0
- for key := range dict {
- keys[i] = key
- i++
- }
- sort.Strings(keys)
- return keys
-}
-
-func SortedRequestBodyKeys(dict map[string]*openapi3.RequestBodyRef) []string {
- keys := make([]string, len(dict))
- i := 0
- for key := range dict {
- keys[i] = key
- i++
- }
- sort.Strings(keys)
- return keys
-}
-
-func SortedSecurityRequirementKeys(sr openapi3.SecurityRequirement) []string {
- keys := make([]string, len(sr))
- i := 0
- for key := range sr {
- keys[i] = key
- i++
- }
- sort.Strings(keys)
- return keys
-}
-
// StringInArray checks whether the specified string is present in an array
// of strings
func StringInArray(str string, array []string) bool {
@@ -527,6 +581,22 @@ func SwaggerUriToGorillaUri(uri string) string {
return pathParamRE.ReplaceAllString(uri, "{$1}")
}
+// SwaggerUriToStdHttpUri converts a swagger style path URI with parameters to a
+// Chi compatible path URI. We need to replace all Swagger parameters with
+// "{param}". Valid input parameters are:
+//
+// {param}
+// {param*}
+// {.param}
+// {.param*}
+// {;param}
+// {;param*}
+// {?param}
+// {?param*}
+func SwaggerUriToStdHttpUri(uri string) string {
+ return pathParamRE.ReplaceAllString(uri, "{$1}")
+}
+
// OrderedParamsFromUri returns the argument names, in order, in a given URI string, so for
// /path/{param1}/{.param2*}/{?param3}, it would return param1, param2, param3
func OrderedParamsFromUri(uri string) []string {
@@ -719,7 +789,7 @@ func typeNamePrefix(name string) (prefix string) {
// SchemaNameToTypeName converts a Schema name to a valid Go type name. It converts to camel case, and makes sure the name is
// valid in Go
func SchemaNameToTypeName(name string) string {
- return typeNamePrefix(name) + ToCamelCase(name)
+ return typeNamePrefix(name) + nameNormalizer(name)
}
// According to the spec, additionalProperties may be true, false, or a
@@ -743,7 +813,7 @@ func SchemaHasAdditionalProperties(schema *openapi3.Schema) bool {
// type name.
func PathToTypeName(path []string) string {
for i, p := range path {
- path[i] = ToCamelCase(p)
+ path[i] = nameNormalizer(p)
}
return strings.Join(path, "_")
}
diff --git a/pkg/codegen/utils_test.go b/pkg/codegen/utils_test.go
index 85c279f1b..a55e648e8 100644
--- a/pkg/codegen/utils_test.go
+++ b/pkg/codegen/utils_test.go
@@ -21,27 +21,139 @@ import (
"github.com/stretchr/testify/require"
)
-func TestStringOps(t *testing.T) {
- // Test that each substitution works
- assert.Equal(t, "WordWordWORDWordWordWordWordWordWordWordWordWordWord", ToCamelCase("word.word-WORD+Word_word~word(Word)Word{Word}Word[Word]Word:Word;"), "Camel case conversion failed")
-
- // Make sure numbers don't interact in a funny way.
- assert.Equal(t, "Number1234", ToCamelCase("number-1234"), "Number Camelcasing not working.")
+func TestToCamelCase(t *testing.T) {
+ tests := []struct {
+ str string
+ want string
+ }{{
+ str: "",
+ want: "",
+ }, {
+ str: " foo_bar ",
+ want: "FooBar",
+ }, {
+ str: "hi hello-hey-hallo",
+ want: "HiHelloHeyHallo",
+ }, {
+ str: "foo#bar",
+ want: "FooBar",
+ }, {
+ str: "foo2bar",
+ want: "Foo2bar",
+ }, {
+ // Test that each substitution works
+ str: "word.word-WORD+Word_word~word(Word)Word{Word}Word[Word]Word:Word;",
+ want: "WordWordWORDWordWordWordWordWordWordWordWordWordWord",
+ }, {
+ // Make sure numbers don't interact in a funny way.
+ str: "number-1234",
+ want: "Number1234",
+ },
+ }
+ for i := range tests {
+ tt := tests[i]
+ t.Run(tt.str, func(t *testing.T) {
+ require.Equal(t, tt.want, ToCamelCase(tt.str))
+ })
+ }
}
-func TestSortedSchemaKeys(t *testing.T) {
- dict := map[string]*openapi3.SchemaRef{
- "f": nil,
- "c": nil,
- "b": nil,
- "e": nil,
- "d": nil,
- "a": nil,
+func TestToCamelCaseWithDigits(t *testing.T) {
+ tests := []struct {
+ str string
+ want string
+ }{{
+ str: "",
+ want: "",
+ }, {
+ str: " foo_bar ",
+ want: "FooBar",
+ }, {
+ str: "hi hello-hey-hallo",
+ want: "HiHelloHeyHallo",
+ }, {
+ str: "foo#bar",
+ want: "FooBar",
+ }, {
+ str: "foo2bar",
+ want: "Foo2Bar",
+ }, {
+ str: "пир2пир",
+ want: "Пир2Пир",
+ }, {
+ // Test that each substitution works
+ str: "word.word3word-WORD+Word_word~word(Word)Word{Word}Word[Word]Word:Word;",
+ want: "WordWord3WordWORDWordWordWordWordWordWordWordWordWordWord",
+ }, {
+ // Make sure numbers don't interact in a funny way.
+ str: "number-1234",
+ want: "Number1234",
+ },
}
+ for i := range tests {
+ tt := tests[i]
+ t.Run(tt.str, func(t *testing.T) {
+ require.Equal(t, tt.want, ToCamelCaseWithDigits(tt.str))
+ })
+ }
+}
- expected := []string{"a", "b", "c", "d", "e", "f"}
-
- assert.EqualValues(t, expected, SortedSchemaKeys(dict), "Keys are not sorted properly")
+func TestToCamelCaseWithInitialisms(t *testing.T) {
+ tests := []struct {
+ str string
+ want string
+ }{{
+ str: "",
+ want: "",
+ }, {
+ str: "hello",
+ want: "Hello",
+ }, {
+ str: "DBError",
+ want: "DBError",
+ }, {
+ str: "httpOperationId",
+ want: "HTTPOperationID",
+ }, {
+ str: "OperationId",
+ want: "OperationID",
+ }, {
+ str: "peer2peer",
+ want: "Peer2Peer",
+ }, {
+ str: "makeUtf8",
+ want: "MakeUTF8",
+ }, {
+ str: "utf8Hello",
+ want: "UTF8Hello",
+ }, {
+ str: "myDBError",
+ want: "MyDBError",
+ }, {
+ str: " DbLayer ",
+ want: "DBLayer",
+ }, {
+ str: "FindPetById",
+ want: "FindPetByID",
+ }, {
+ str: "MyHttpUrl",
+ want: "MyHTTPURL",
+ }, {
+ str: "find_user_by_uuid",
+ want: "FindUserByUUID",
+ }, {
+ str: "HelloПриветWorldМир42",
+ want: "HelloПриветWorldМир42",
+ }, {
+ str: "пир2пир",
+ want: "Пир2Пир",
+ }}
+ for i := range tests {
+ tt := tests[i]
+ t.Run(tt.str, func(t *testing.T) {
+ require.Equal(t, tt.want, ToCamelCaseWithInitialisms(tt.str))
+ })
+ }
}
func TestSortedSchemaKeysWithXOrder(t *testing.T) {
@@ -119,96 +231,6 @@ components:
}
-func TestSortedPathsKeys(t *testing.T) {
- dict := map[string]*openapi3.PathItem{
- "f": nil,
- "c": nil,
- "b": nil,
- "e": nil,
- "d": nil,
- "a": nil,
- }
-
- expected := []string{"a", "b", "c", "d", "e", "f"}
-
- assert.EqualValues(t, expected, SortedPathsKeys(dict), "Keys are not sorted properly")
-}
-
-func TestSortedOperationsKeys(t *testing.T) {
- dict := map[string]*openapi3.Operation{
- "f": nil,
- "c": nil,
- "b": nil,
- "e": nil,
- "d": nil,
- "a": nil,
- }
-
- expected := []string{"a", "b", "c", "d", "e", "f"}
-
- assert.EqualValues(t, expected, SortedOperationsKeys(dict), "Keys are not sorted properly")
-}
-
-func TestSortedResponsesKeys(t *testing.T) {
- dict := map[string]*openapi3.ResponseRef{
- "f": nil,
- "c": nil,
- "b": nil,
- "e": nil,
- "d": nil,
- "a": nil,
- }
-
- expected := []string{"a", "b", "c", "d", "e", "f"}
-
- assert.EqualValues(t, expected, SortedResponsesKeys(dict), "Keys are not sorted properly")
-}
-
-func TestSortedContentKeys(t *testing.T) {
- dict := openapi3.Content{
- "f": nil,
- "c": nil,
- "b": nil,
- "e": nil,
- "d": nil,
- "a": nil,
- }
-
- expected := []string{"a", "b", "c", "d", "e", "f"}
-
- assert.EqualValues(t, expected, SortedContentKeys(dict), "Keys are not sorted properly")
-}
-
-func TestSortedParameterKeys(t *testing.T) {
- dict := map[string]*openapi3.ParameterRef{
- "f": nil,
- "c": nil,
- "b": nil,
- "e": nil,
- "d": nil,
- "a": nil,
- }
-
- expected := []string{"a", "b", "c", "d", "e", "f"}
-
- assert.EqualValues(t, expected, SortedParameterKeys(dict), "Keys are not sorted properly")
-}
-
-func TestSortedRequestBodyKeys(t *testing.T) {
- dict := map[string]*openapi3.RequestBodyRef{
- "f": nil,
- "c": nil,
- "b": nil,
- "e": nil,
- "d": nil,
- "a": nil,
- }
-
- expected := []string{"a", "b", "c", "d", "e", "f"}
-
- assert.EqualValues(t, expected, SortedRequestBodyKeys(dict), "Keys are not sorted properly")
-}
-
func TestRefPathToGoType(t *testing.T) {
old := globalState.importMapping
globalState.importMapping = constructImportMapping(map[string]string{
@@ -390,6 +412,40 @@ func TestSwaggerUriToFiberUri(t *testing.T) {
assert.Equal(t, "/path/:arg/foo", SwaggerUriToFiberUri("/path/{?arg*}/foo"))
}
+func TestSwaggerUriToChiUri(t *testing.T) {
+ assert.Equal(t, "/path", SwaggerUriToChiUri("/path"))
+ assert.Equal(t, "/path/{arg}", SwaggerUriToChiUri("/path/{arg}"))
+ assert.Equal(t, "/path/{arg1}/{arg2}", SwaggerUriToChiUri("/path/{arg1}/{arg2}"))
+ assert.Equal(t, "/path/{arg1}/{arg2}/foo", SwaggerUriToChiUri("/path/{arg1}/{arg2}/foo"))
+
+ // Make sure all the exploded and alternate formats match too
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToChiUri("/path/{arg}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToChiUri("/path/{arg*}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToChiUri("/path/{.arg}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToChiUri("/path/{.arg*}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToChiUri("/path/{;arg}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToChiUri("/path/{;arg*}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToChiUri("/path/{?arg}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToChiUri("/path/{?arg*}/foo"))
+}
+
+func TestSwaggerUriToStdHttpUriUri(t *testing.T) {
+ assert.Equal(t, "/path", SwaggerUriToStdHttpUri("/path"))
+ assert.Equal(t, "/path/{arg}", SwaggerUriToStdHttpUri("/path/{arg}"))
+ assert.Equal(t, "/path/{arg1}/{arg2}", SwaggerUriToStdHttpUri("/path/{arg1}/{arg2}"))
+ assert.Equal(t, "/path/{arg1}/{arg2}/foo", SwaggerUriToStdHttpUri("/path/{arg1}/{arg2}/foo"))
+
+ // Make sure all the exploded and alternate formats match too
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToStdHttpUri("/path/{arg}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToStdHttpUri("/path/{arg*}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToStdHttpUri("/path/{.arg}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToStdHttpUri("/path/{.arg*}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToStdHttpUri("/path/{;arg}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToStdHttpUri("/path/{;arg*}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToStdHttpUri("/path/{?arg}/foo"))
+ assert.Equal(t, "/path/{arg}/foo", SwaggerUriToStdHttpUri("/path/{?arg*}/foo"))
+}
+
func TestOrderedParamsFromUri(t *testing.T) {
result := OrderedParamsFromUri("/path/{param1}/{.param2}/{;param3*}/foo")
assert.EqualValues(t, []string{"param1", "param2", "param3"}, result)
@@ -567,7 +623,38 @@ func TestRefPathToObjName(t *testing.T) {
}
}
-func Test_replaceInitialisms(t *testing.T) {
+func TestLowercaseFirstCharacters(t *testing.T) {
+ tests := []struct {
+ name string
+ in string
+ expected string
+ }{
+ {
+ name: "id",
+ expected: "id",
+ },
+ {
+ name: "CamelCase",
+ expected: "camelCase",
+ },
+ {
+ name: "ID",
+ expected: "id",
+ },
+ {
+ name: "DBTree",
+ expected: "dbTree",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ assert.Equal(t, tt.expected, LowercaseFirstCharacters(tt.name))
+ })
+ }
+}
+
+func Test_replaceInitialism(t *testing.T) {
type args struct {
s string
}
@@ -601,6 +688,16 @@ func Test_replaceInitialisms(t *testing.T) {
args: args{s: "fooIDBarAPI"},
want: "fooIDBarAPI",
},
+ {
+ name: "one initialism at start",
+ args: args{s: "idFoo"},
+ want: "idFoo",
+ },
+ {
+ name: "one initialism at start and one in middle",
+ args: args{s: "apiIdFoo"},
+ want: "apiIDFoo",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {