Releases: oapi-codegen/oapi-codegen
v2.7.0: Squashing bugs, many bugs (and adding some features)
Many improvements and even more bug fixes
This v2.7.0 release of oapi-codegen contains quite a bit of internal refactoring, focused on our most historically fragile code paths, which relate to the aggregate types (allOf/anyOf/oneOf), $ref to external specs, enums, and the spec traversal logic missing quite a few leaf nodes where models should have been generated, but were skipped.
The biggest changes are explicitly described in the sections below, and the full list of commits is at the bottom.
Thank you to all contributors, we've been going through all past PR's and updating them and merging where we can, and thanks to all our users for reporting issues that you hit.
I've (@mromaszewicz) used a lot of LLM help here to scrub through old issues and do some deep internal refactoring to address common problem areas. I intend to continue doing this, since the conditional generation logic is getting quite complicated. When I originally released oapi-codegen, the use case was much simpler, all the models were under #/components/schemas, and all the references to them were in the requests, responses, etc. I never imagine how many things would be external references or unions, and how many complex OpenAPI specifications people would be generating code for. The initial design was never flexible enough to handle that, so ongoing bug fixes are getting increasingly complex due to edge cases. This version has a lot of internal changes you won't see as a user, but the way we handle type generation internally is unifying lots of copy/paste re-implementations into reusable code for consistency. Most of these changes can be done transparently, but some can't, so, onto the changes:
Code generation changes which might require some changes on your end
This release contains three changes, all very narrow in scope, which will require some manual adjustment of your own code. We've decided that these are small enough and uncommon enough not to require opt-in, which causes internal complexity. It's always a judgment call with these. If we got it wrong, we're happy to revisit it in a maintenance release.
Strict-server external response refs require strict-server generation in both packages (#2357)
If your strict-server spec uses an external $ref to a components/responses/... defined in another spec, that other
spec must also be generated with strict-server: true. Add it to the source spec's config and regenerate:
# config for the spec being $ref'd
generate:
models: true
strict-server: true # now required when imported by a strict-server specThis restores the v2.0.0 behavior that lets you cast response models across package boundaries — the standard pattern
for sharing error models (e.g. a common 400) across services. PR #1387 had silently changed the embedded type from N400JSONResponse to the bare externalRef0.N400, so the local and external response structs no longer had
matching types and casts stopped compiling.
Many more anonymous inner schemas are now hoisted into top level schemas
Inline oneOf, anyOf, and additionalProperties schemas embedded directly under an operation's request or response
body now flow through the same boilerplate-emission pipeline as components/schemas, so they get the
As* / From* / Merge* accessor methods they were previously missing. As part of that change, two older naming patterns
are replaced with one pattern, shared with all components:
GetPets_200_Data_Item → GetPets200JSONResponseBody_Data_Item
GetPets200JSONResponse_Data_Item → GetPets200JSONResponseBody_Data_Item
In practice, we think this shouldn't break anyone, because this change addresses a bug which produced pointless types
with no benefit, and you never interact with these directly, but rather you'd call an accessor on a field of a model.
Strict middleware typedefs are now inlined (#2271)
StrictHandlerFunc and StrictMiddlewareFunc in generated strict-server code are now inline type definitions instead
of aliases to github.com/oapi-codegen/runtime/strictmiddleware/<framework>. Generated servers no longer import that package.
Before (Echo example):
import strictecho "github.com/oapi-codegen/runtime/strictmiddleware/echo"
type StrictHandlerFunc = strictecho.StrictEchoHandlerFunc
type StrictMiddlewareFunc = strictecho.StrictEchoMiddlewareFuncAfter:
type StrictHandlerFunc func(ctx echo.Context, request any) (any, error)
type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFuncIf your code referenced the per-framework names directly — strictecho.StrictEchoHandlerFunc, strictgin.StrictGinHandlerFunc, strictnethttp.StrictHTTPHandlerFunc, strictiris.StrictIrisHandlerFunc, strictecho5.StrictEcho5HandlerFunc — switch to the local StrictHandlerFunc / StrictMiddlewareFunc exposed by the generated server package, or import runtime/strictmiddleware/<framework> yourself if you really want those names. The underlying signatures are unchanged, so any value satisfying the old type still satisfies the new one.
🎉 Notable changes
Go 1.24 required (#2264)
oapi-codegen itself now requires Go 1.24.4+ to build and run. The toolchain in your project's go.mod (the one used to invoke the codegen) must be ≥ 1.24.4. The code generated will still likely work on older versions. We had to update to Go 1.24 in order to update some dependencies to address vulnerabilities. Go 1.24 is no longer supported, so our next release will update to Go 1.25,
and the plan is to stay on supported Go versions. I'm not sure if 1.25 will come in v2.8.0 or v2.7.1 yet, but it's imminent. We
have a number of submodules in this repo which exist only to test Go 1.25 routers in a 1.24 module, and it allows us to
simplify.
Unfortunately, some of our transitive dependencies result in a broken build, by default, so you might have to pin these
packages to specific versions:
- github.com/speakeasy-api/jsonpath v0.6.3
- github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 (See #2015 for some discusion)
Multi-pass type name resolution (#2213)
Set output-options.resolve-type-name-collisions: true to make the codegen detect identifier collisions across schemas, parameters, request bodies, response components, and operation-derived types — and resolve them deterministically by suffixing the loser. Specs that previously failed to generate because two definitions wanted the same Go name now succeed.
Trivial example. With this spec:
components:
schemas:
Status:
type: string
enum: [active, archived]
parameters:
Status:
name: status
in: query
schema:
type: stringoutput-options.resolve-type-name-collisions: true produces:
type Status string // from components.schemas.Status
const StatusActive Status = "active"
const StatusArchived Status = "archived"
type StatusParameter = string // from components.parameters.StatusCollision resolution is opt-in. Generated identifier names depend on the current set of collisions in the spec;
adding a new schema or parameter later that collides with an existing one will rename the existing one to break the new collision.
That can silently break user code that imports the previously-stable name as the spec drifts. However, despite the drift,
more specs can now correctly generate boilerplate.
Parameter binding matrix (#2307)
The OpenAPI parameter style × explode × type matrix is now fully supported and round-trips consistently across
every server backend. Path/query/header/cookie parameters across primitive, array, and object types — including
style: form / spaceDelimited / pipeDelimited / deepObject × explode: true/false, and style: simple for headers —
generate the same binding logic on every server, and the client-side encoding is symmetric. The internal parameter test suite (internal/test/parameters/) now exercises every combination through a server round-trip per backend.
If you previously hit an unsupported style error, or saw a parameter serialization work under one backend but not another,
regenerate and the issue should be gone.
You will need to use version v1.4.0 or higher of github.com/oapi-codegen/runtime.
Optional / nullable response headers (#2301)
For strict-server responses, optional and nullable headers now generate as pointer fields (or nullable.Nullable[T]
when the nullable-types output option is set). The generated server only calls w.Header().Set(...) when the field
is non-nil, so callers can omit optional headers cleanly.
Spec:
responses:
'200':
headers:
X-Required: { required: true, schema: { type: string } }
X-Optional: { schema: { type: string } }Before:
type GetFoo200ResponseHeaders struct {
XRequired string
XOptional string // always emitted, even when empty
}After:
type GetFoo200ResponseHeaders struct {
XRequired string
XOptional *string // nil → header not sent
}To opt out of this change, set compatibility.headers-implicitly-required: true to restore the previous always-required behavior. This change breaks enough code that we flagified it.
🚀 New features
Echo v5 server support ([#2188](https://github.com/oapi-codegen/oapi-cod...
v2.6.0: 7th anniversary release 🎂
For those that aren't aware, 7 years ago to the day, oapi-codegen was born!
(Well, technically it's tonight at midnight UTC, but who's splitting hairs?)
There's nothing too special planned for today, but we thought it'd be the perfect time to cut a slice of cake a release!
🎉 Notable changes
New generated code requires oapi-codegen/runtime v1.2.0+
As part of #2256, github.com/oapi-codegen/runtime v1.2.0 is needed alongside github.com/oapi-codegen/oapi-codegen, for new generated code.
This is providing a more future-proofed means to bind parameters.
See the release notes for the runtime package, and #2256 for more information.
oapi-codegen was part of the GitHub Secure Open Source Fund
oapi-codegen was one of the projects taking part in the third GitHub Secure Open Source Fund session.
We've written up more about what we've learned, and have some more things to share with you over the coming months about lessons we've learned and improvements we've taken that we can share.
We were pretty chuffed to be selected, and it's already helped improve our security posture as a project, which is also very important for the wider ecosystem!
go directive bump in next release
Long-time users will be aware that we work very hard to try and keep our requirement for Go source compatibility, through the go directive, especially as we recommend folks use oapi-codegen as a source-tracked dependency.
For more details about this, see our Support Model docs.
In the next minor release, we'll be setting our minimum go directive to Go 1.24 (End-of-Life on 2026-02-11), as it's required for a number of dependencies of ours to be updated any higher, and a change to the module import path for Speakeasy's OpenAPI Overlay library requires us fix this centrally for our users to be able to continue updating their libraries.
Note
Nothing is changing as part of v2.6.0, this is a pre-announcement for v2.7.0.
Behind the scenes cleanup
There's also been some work behind-the-scenes to try and clean up outstanding issues (of which we know there are many!) that have been fixed, as well as Marcin's work on trying to do some more significant rework of the internals with help from Claude.
There's still, as ever, work to go with this - as we've mentioned before, sponsoring our work would be greatly appreciated, so we can continue to put in the work, considering this is a widely used and depended on project.
🚀 New features and improvements
- feat: Pass schema type/formats to runtime v1.2.0 to allow better parameter serialization (#2256) @mromaszewicz
- feat: add Valid() method to generated enum types (#2227) @mromaszewicz
- Support nullable slice elements and map values (#2185) @iamtakingiteasy
- feat: add configurable type mapping for OpenAPI primitive types (#2223) @mromaszewicz
- Support unions with multiple mappings pointing to a single underlying type (#2071) @tobio
- feat: add support for custom package alias for external ref imports (#2211) @InventivetalentDev
- feat(output-options): add
resolve-type-name-collisionsto avoid name collisions (#200) @mgurevin - Adopt fiber middleware template for updated GetReqHeaders() method signature (#1419) @getBolted
🐛 Bug fixes
- fix: qualify external ref schema types in default response codes (#2241) @mromaszewicz
- fix: add omitempty to optional nullable fields (#2221) @mromaszewicz
- fix(codegen): generate
nullable.Nullablein arrays (#2242) @jamietanna - fix: support x-oapi-codegen-extra-tags on parameter schemas (#2232) (#2235) @mromaszewicz
- fix(templates/client): correctly nil check query parameters (#2237) @jamietanna
- fix(server-urls): restore generation of constants (#2239) @jamietanna
- fix(server-urls): use URL in GoDoc if
descriptionis empty (#2226) @jamietanna - fix: set indentation to 2 when marshalling spec for overlay (#2172) @wndhydrnt
- fix: handle optional request bodies in strict server mode (#2222) @mromaszewicz
- fix(strict-server): generate correct type for
$reftext responses (#2225) @mromaszewicz - Fix schema gathering oversight (#2219) @mromaszewicz
- fix: handle duplicate path parameters in OpenAPI specs (#2220) @mromaszewicz
- fix: escape quoted media type directives (#2217) @brahmlower
- Fix Iris strict server for no content case (#1411) @ShouheiNishi
- Fixes type collision for enum values that start with _ (underscore) (#1438) @ula
📝 Documentation updates
- chore: readme update (#2209) @mromaszewicz
- docs: fix link to example (#1884) @rkosegi
- docs(extensions): correct links to examples (#1836) @yuro241
- docs(sponsors): update section (#2195) @jamietanna
- docs(sponsors): remove Elastic as a sponsor (#2083) @jamietanna
👻 Maintenance
- chore(renovate): add module path to security updates + override test-only dependencies' label (#2249) @jamietanna
- Configure Greptile code review (#2236) @mromaszewicz
- style(gofix): Apply
go fix(#2229) @gaiaz-iusipov - Run golangci-lint on a supported Go version (#2215) @mromaszewicz
- refactor(internal): move Fiber tests into their own modules (#2212) @mromaszewicz
- build: use a re-usable, single, workflow for running CI (#2205) @jamietanna
- fix(renovate): only run
make tidyafter Go module updates (#2159) @jamietanna - chore(renovate): run
make tidyafter dependency updates togo.mod(#2150) @jamietanna
📦 Dependency updates
8 changes
- chore(deps): update module github.com/golangci/golangci-lint to v2.10.1 (makefile) (#2153) @renovate[bot]
- chore(deps): update github/codeql-action action to v4.32.4 (.github/workflows) (#2157) @renovate[bot]
- chore(deps): update actions/setup-go action to v6.3.0 (.github/workflows) (#2164) @renovate[bot]
- chore(deps): update actions/checkout action to v6 (.github/workflows) - autoclosed (#2165) @renovate[bot]
- chore(deps): update release-drafter/release-drafter action to v6.2.0 (.github/workflows) (#2253) @renovate[bot]
- chore(deps): update actions/upload-artifact action to v7 (.github/workflows) (#2254) @renovate[bot]
- chore(deps): update dessant/label-actions action to v5 (.github/workflows) (#2255) @renovate[bot]
- chore(deps): update release-drafter/release-drafter action to v6.1.0 (.github/workflows) (#2132) @renovate[bot]
Sponsors
We would like to thank our sponsors for their support during this release.
v2.5.1: fix a couple of regressions from v2.5.0
🐛 Bug fixes
- fix(templates): correctly nil check arrays (#2118) @jamietanna
- fix: report formatting errors with line numbers (#2117) @jamietanna
- fix(output-options): correctly reference
x-go-type-skip-optional-pointerinallOf(#2042) @magnetikonline
📝 Documentation updates
- docs: clarify support +
godirectives (#2099) @jamietanna - docs: correct level of headers (#2095) @jamietanna
- docs(sponsors): update Speakeasy logo (#2049) @chailandau
- Fix bullet point line
prefer-skip-optional-pointer-with-omitzerotypo inREADME.md(#2028) @magnetikonline
👻 Maintenance
- build: handle additional values in
GOVERSION(#2119) @jamietanna - build: add explicit
permissionsblocks fortidy.yml(#2101) @jamietanna - build: add explicit
permissionsblocks for Actions (#2100) @jamietanna - build: add Scorecards workflow (#2098) @jamietanna
- build: capture
govulncheckresults as Code Scanning alerts (#2084) @jamietanna - build: test against Go 1.25 (#2056) @jamietanna
Renovate configuration changes
- chore(renovate): improve actionability of pending updates (#2120) @jamietanna
- chore(renovate): don't exclude
examplesandinternal/test(#2033) @jamietanna - chore(renovate): correctly create branches for top-level files (#2138) @jamietanna
📦 Dependency updates
9 changes
- fix(deps): update module github.com/getkin/kin-openapi to v0.133.0 (go.mod) (#2141) @renovate[bot]
- fix(deps): update module github.com/stretchr/testify to v1.11.1 (go.mod) (#2142) @renovate[bot]
- chore(deps): update module github.com/golangci/golangci-lint to v2.6.0 (makefile) (#2140) @renovate[bot]
- chore(deps): update ossf/scorecard-action action to v2.4.3 (.github/workflows) (#2128) @renovate[bot]
- chore(deps): update actions/upload-artifact action to v5 (.github/workflows) (#2136) @renovate[bot]
- chore(deps): update actions/setup-go action to v6 (.github/workflows) (#2135) @renovate[bot]
- chore(deps): update actions/labeler action to v6 (.github/workflows) (#2134) @renovate[bot]
- chore(deps): update actions/checkout action to v5 (.github/workflows) (#2133) @renovate[bot]
- chore(deps): update github/codeql-action action to v4 (.github/workflows) (#2137) @renovate[bot]
Sponsors
We would like to thank our sponsors for their support during this release.
v2.5.0: No more optional pointers (optionally), `omitzero`, better control over initialisms, and so much more!
v2.5.0: No more optional pointers (optionally)!
🎉 Notable changes
Begone optional pointers! (optionally)
One of the key things oapi-codegen does is to use an "optional pointer", following idiomatic Go practices, to indicate that a field/type is optional.
This can be tuned on a per-field basis, using the x-go-type-skip-optional-pointer extension, but it can be a bit repetitive, or can be more complex when using an OpenAPI Overlay.
As of oapi-codegen v2.5.0, this can be tuned in two specific ways, via the following Output Options:
prefer-skip-optional-pointer: a global default that you do not want the "optional pointer" generated. Optional fields will not have an "optional pointer", and will have anomitemptyJSON tagprefer-skip-optional-pointer-with-omitzero: when used in conjunction withprefer-skip-optional-pointer, any optional fields are generated with anomitzeroJSON tag. Requires Go 1.24+
In both cases, there is control on a per-field level to set x-go-type-skip-optional-pointer: false or x-omitzero: false to undo these to field(s).
Note
The default is not changing.
We take care to avoid breaking changes so this is, as many changes, an opt-in.
See Globally skipping the "optional pointer" for more details.
Generating omitzero JSON tags, with x-omitzero
Related to the above functionality, it is possible to define the OpenAPI extension x-omitzero on fields to generate the omitzero JSON tag, based on the (now not-so-new) Go 1.24 release.
Thanks to @lzap for the contribution 🚀
Note
oapi-codegen does not currently validate the Go version that the module it's generating code for.
This could lead to the omitzero JSON tag being generated, but not being actually usable.
Ensure that you're using a Go 1.24+ version, and that your go directive (for source compatibility) is go 1.24 or i.e. go 1.24.1
Using OpenAPI 3.1 with oapi-codegen
There's some promising behind-the-scenes discussions with may lead to OpenAPI 3.1 support (#373) coming in the not-too-distant future 👀
In the meantime, Jamie (one of the Core Maintainers) has written a blog post about how to use oapi-codegen with OpenAPI 3.1 specs (by downgrading them to OpenAPI 3.0).
Defining your own initialisms
As a means to define your own custom initialisms, it's possible to use the additional-initialisms Output Option.
Thanks @micaelmalta for the contribution 🚀
If your organisation uses a lot of TLAs (Two Letter Acronyms or Three Letter Acronyms) or any other sorts of initialisms, it's handy to be able to configure these yourself.
For instance, if you regularly use the term CSP to refer to Cloud Service Provider, you may want CSP to be used in variable names.
This makes it possible to define i.e.
# ...
output-options:
name-normalizer: ToCamelCaseWithInitialisms
additional-initialisms:
- CSPNote
This only works when the name-normaliser Output Option is set to ToCamelCaseWithInitialisms. An error will occur if you've not configured this correctly.
Minimum version of Go needed for oapi-codegen is now 1.22.5
As part of a couple of updates in #1888 and #1986, we're now requiring Go >= 1.22.5.
Similar to the bump to Go 1.21 in v2.4.0
Notable background work
Since the last oapi-codegen release (all the way in September 2024 🥲) the following big changes towards the project and its ecosystem have been:
net/httpmiddleware v1.1.0: Better error handling, allow not validatingServers(by configuration) and return an HTTP 405 Method Not Allowed where appropriate- Jamie posted a look back at the last year
- Notably also writing up explicitly how the project is currently governed
runtime: fixes formaps andx-go-type-skip-optional-pointer
🚀 New features and improvements
- feat(client): Add
Bytes()toClientWithResponsesresponses (#1780) @grongor - feat(generate): allow generating Server URL boilerplate (#2002) @jamietanna
- feat(output-options): add
prefer-skip-optional-pointer-on-container-types(#1979) @jamietanna - feat(output-options): add
prefer-skip-optional-pointerto default to skipping optional pointers (#1694) @aksdb - feat(output-options): add
yaml-tagsoption (#1798) @deitch - feat(templates): consolidate logic for whether to use an optional pointer (#1981) @jamietanna
- feat(x-deprecated-reason): add default deprecation message (#2022) @jamietanna
- feat: allow specifying
additional-initialisms(#1733) @micaelmalta
🐛 Bug fixes
- Handle leading underscores in property names (#1822) @tobio
- fix(codegen): allow exposing the input spec's
operationId(#1945) @jamietanna - fix(codegen): allow using x-go-type and x-go-type-skip-optional-pointer together (#1957) @Nivl
- fix(output-options): obey
prefer-skip-optional-pointerin reference types + add tests forpreferskipoptionalpointer(#2021) @jamietanna - fix(overlay): correctly resolve references after Overlay application (#1825) @jgraeger
- fix(stdhttp): correctly generate root paths (#1953) @jamietanna
- fix: Print the warning message to stderr instead of stdout (#1895) @ignassew
- fix: create directories if they do not exist before writing output file (#1994) @kf-pineapple
- fix: don't generate an "optional pointer" for unknown types (#610) @jens1205
📝 Documentation updates
- docs: add example for how to downgrade OpenAPI 3.1 to 3.0 (#1966) @jamietanna
- Add blog post about using oapi-codegen in a Chi project (#1791) @0xi4o
- Fix broken anchor link for validation middleware section (#2013) @Park-Jongseok
- chore(tests): add additional test case for underscore naming (#1980) @jamietanna
- docs(client): document known issue with duplicated
Responsemodels (#2025) @jamietanna - docs(extensions): correct typo to example (#1999) @i-sevostyanov
- docs(extensions): don't use
<details>blocks in<table>(#2019) @jamietanna - docs(extensions): update example code for
x-enumNames(#2000) @jamietanna - docs(middleware): clarify use of
nethttp-middlewarefor other purposes (#1951) @jamietanna - docs(sponsors): add Livepeer (#1849) @jamietanna
- docs(sponsors): update Speakeasy URL (#1970) @ndimares
- docs(std-http-server): warn when not using Go 1.22 (#1967) @jamietanna
- docs: add contributors image (#1795) @jamietanna
- docs: add example of using
go toolfor Go 1.24+ (#1908) @jamietanna - docs: fix GitHub flavoured markdown (#1934) @MarvinJWendt
- docs: fix typo in flags usage (#1796) @AlekSi
- docs: note the use of a multi-module
tools.go(#1788) @jamietanna - docs: simplify go tool example (#1910) @gaiaz-iusipov
- docs(additional-initialisms): add a usage example (#2026) @jamietanna
👻 Maintenance
- build(labels): add additional labelling (#1848) @jamietanna
- build(labels): add autolabeller for "no
mainbranch please" (#1847) @jamietanna - build: build against Go 1.24 (#1901) @jamietanna
- build: ensure separately named "Check results" steps (#1850) @jamietanna
- chore(examples): use Go 1.24 with Go 1.24 example (#1925) @jamietanna
- chore(tests): add additional test case for underscore naming (#1980) @jamietanna
- chore: don't use non-GitHub URL for tests (#1926) @jamietanna
- fix(output-options): obey
prefer-skip-optional-pointerin reference types + add tests forpreferskipoptionalpointer(#2021) @jamietanna
📦 Dependency updates
13 changes
- fix(deps): update module github.com/getkin/kin-openapi to v0.132.0 (#2024) @renovate[bot]
- fix(deps): update module github.com/getkin/kin-openapi to v0.131.0 [security] (#1986) @renovate[bot]
- chore(deps): update module github.com/golangci/golangci-lint to v2.2.2 (#2014) @renovate[bot]
- fix(deps): update module github.com/speakeasy-api/openapi-overlay to v0.10.2 (#1973) @renovate[bot]
- chore(deps): update module github.com/golangci/golangci-lint to v2 (#1940) @renovate[bot]
- chore(deps): update actions/setup-go digest to d35c59a (#1969) @renovate[bot]
- fix(deps)!: update module github.com/speakeasy-api/openapi-overlay to v0.10.1 (#1888) @renovate[bot]
- chore(deps): pin dependencies (#1948) @renovate[bot]
- chore(deps): update module github.com/golangci/golangci-lint to v1.64.5 (#1871) @renovate[bot]
- fix(deps): update module golang.org/x/text to v0.20.0 (#1792) @renovate[bot]
- fix(deps): update module github.com/stretchr/testify to v1.10.0 (#1844) @renovate[bot]
- chore(deps): update module github.com/golangci/golangci-lint to v1.62.2 (#1828) @renovate[bot]
- fix(deps): update module github.com/getkin/kin-openapi to v0.128.0 (#1794) @renovate[bot]
Sponsors
We would like to thank our sponsors for their support during this release.
v2.4.1: A couple of post-release fixes
🐛 Bug fixes
- fix(import-mapping): don't produce unused variable when one mapping (#1781) @ottaviohartman
📝 Documentation updates
- docs(sponsors): clarify Elastic's 4h/mo (#1783) @jamietanna
👻 Maintenance
- build: remove patch version pinning on
godirective (#1784) @jamietanna
Sponsors
We would like to thank our sponsors for their support during this release.
v2.4.0: OpenAPI Overlay, improved `import-mapping` functionality, and a whole host of other great things 🚀
🎉 Notable changes
Modifying the input OpenAPI Specification, without needing to modify it directly
Prior to oapi-codegen v2.4.0, users wishing to override specific configuration, for instance taking advantage of extensions such as x-go-type would need to modify the OpenAPI specification they are using.
In a lot of cases, this OpenAPI specification would be produced by a different team to the consumers (or even a different company) and so asking them to make changes like this were unreasonable.
This would lead to the API consumers needing to vendor the specification from the producer (which is our recommendation anyway) and then make any number of local changes to the specification to make it generate code that looks reasonable.
However, in the case that a consumer would update their specification, they would likely end up with a number of merge conflicts.
Now, as of oapi-codegen v2.4.0, it is now possible to make changes to the input OpenAPI specification without needing to modify it directly.
This takes advantage of the OpenAPI Overlay specification, which is a stable specification.
We're very excited for y'all to be able to take advantage of this, and to be able to manipulate complex specifications you don't have control over.
Using a single package, with multiple OpenAPI spec for a given package
Since oapi-codegen v2.4.0, it is now possible to split large OpenAPI specifications into the same Go package, using the "self" mapping (denoted by a -) when using Import Mapping.
This is an improvement on the previous model, which would require splitting files across multiple packages.
This should improve the ability to use a multi-file OpenAPI specification.
Reverting a breaking change to Strict servers using text/plain
Changes in #1132 had unintended side effects, and so we have reverted this.
This will be a breaking change to anyone who had pulled in this change, since it landed in v1.13.1.
Minimum version of Go needed for oapi-codegen is now 1.21
Does what it says on the tin.
This was required for a new dependency, and given Go 1.21 is now End-of-Life, this isn't too bad a requirement, without requiring folks unnecessarily bump their minimum supported version higher.
Starting work towards the OpenSSF Best Practices badge
As a means to better understand the compliance of oapi-codegen with OpenSSF's Best Practices guide, we've started work towards the "passing" badge.
This gives us some insight into where we have gaps, and makes it known for our users, too.
PR Builds now have required status checks
Previously, PR builds did not have a required status check.
Although as maintainers we would only merge changes after the CI checks had passed, this now gives us - and you as our users - greater confidence in the stability of the project.
Previously raised PRs - before 2024-09-20 - will need to merge in the latest changes in main before these status checks will pass.
🚀 New features and improvements
- feat: allow
import-mappingto the current package (#1774) @jamietanna @djgilcrease - feat(std-http): accept
Muxinterface instead of*http.ServeMux(#1720) @sonalys - feat: handle
<and>in property or type names (#1740) @ansoni - feat: add support for OpenAPI Overlay (#1727) @jamietanna
- feat(extension): add
x-oapi-codegen-only-honour-go-name(#1697) @jamietanna
🐛 Bug fixes
- Revert "fix(template): fix strict-interface template to make sure text response content type uses string type (#1132)" (#1773) @jamietanna
- fix: correctly generate structs and properties for
anyOfs (#1178) @daleef-rahman - fix(cookies): wrap
cookievariables in block scope (#1687) @andremarianiello - fix(extensions): use the
x-orderfrom next to$ref, if present (#1700) @paulmach - fix(oapi-codegen): add missing newline to error when swagger spec load fails (oapi-codegen#1688) (#1690) @willbuckner
📝 Documentation updates
- docs: correct wording of heading (#1776) @jamietanna
- docs: remove
deepmap/oapi-codegenreferences (#1771) @jamietanna - docs(tests): add an example of using
in: cookie(#1770) @jamietanna - docs(sponsors): add Cybozu (#1768) @jamietanna
- docs: add link to OpenSSF Best Practices badge (#1761) @jamietanna
- Update CONTRIBUTING.md (#1750) @joeriddles
- docs(overlay): improve Overlay docs (#1749) @jamietanna
- Fix usage YAML example schema path in README.md (#1748) @gren236
- Update link for DevZero (#1716) @dray92
- Update speakeasy URL on oapi-codegen (#1707) @ndimares
- docs(sponsors): add Elastic (#1667) @jamietanna
- docs(sponsors): add
FUNDING.yml(#1661) @jamietanna - docs(sponsors): add Speakeasy (#1649) @jamietanna
- docs: correct module path replacements (#1657) @jamietanna
- docs: clarify module version installations (#1653) @jamietanna
👻 Maintenance
- build: check results of matrix jobs (#1769) @jamietanna
- build: require Go 1.21 to build (#1728) @jamietanna
- build: validate against Go 1.23 (#1724) @jamietanna
- chore: make it possible to provide detailed config validation errors (#1699) @jamietanna
- chore: remove accidental compiled binary (#1698) @jamietanna
- Avoid extra http.Request allocation (stdhttp, chi, gorilla) (#1673) @gaiaz-iusipov
- chore: correct Release Drafter branch (#1654) @jamietanna
📦 Dependency updates
9 changes
- chore(deps): update module github.com/golangci/golangci-lint to v1.61.0 (#1753) @renovate
- fix(deps): update module golang.org/x/text to v0.18.0 (#1640) @renovate
- chore(deps): update module github.com/golangci/golangci-lint to v1.60.3 (#1735) @renovate
- chore(deps): update module github.com/golangci/golangci-lint to v1.60.2 (#1731) @renovate
- fix(deps): update module github.com/getkin/kin-openapi to v0.127.0 (#1711) @renovate
- chore(deps): update module github.com/golangci/golangci-lint to v1.60.1 (#1725) @renovate
- fix(deps): update module github.com/getkin/kin-openapi to v0.126.0 (#1689) @renovate
- fix(deps): update module github.com/getkin/kin-openapi to v0.125.0 (#1659) @renovate
- chore(deps): update module github.com/golangci/golangci-lint to v1.59.1 (#1658) @renovate
Sponsors
We would like to thank our sponsors for their support during this release.
Updates related to repository move
With this version, oapi-codegen consolidates all code under github.com/oapi-codegen. When you install the core tool, please use this new location, github.com/oapi-codegen/oapi-codegen/v2 starting with version v2.3.0, but continue to use github.com/deepmap/oapi-codegen/v2 with any earlier release.
This release contains changes to import paths, go.mod and the README.
What's Changed
- chore(deps): update middleware dependencies by @jamietanna in #1636
- Rename module post-move by @mromaszewicz in #1643
- Update README by @mromaszewicz in #1646
- Update readme with install instrctions by @mromaszewicz in #1652
Full Changelog: v2.2.0...v2.3.0
v2.2.0: Pure-Go 1.22+ server, documentation overhaul. JSON schema and several bug fixes
Big announcements
In case you've missed it, we've got a few big announcements as maintainers of oapi-codegen which we'd recommend you read in more depth.
oapi-codegenis moving to its own org- This is from release v2.3.0, but will be enacted likely before you get a chance to read these release notes, as we want to migrate everything to the same org ASAP
- Creating a more sustainable model for
oapi-codegenin the future- Please consider looking at sponsoring the maintenance that we do on the project.
We'd also like to thank our sponsors for this release:
🔊 Notable features
The v2.2.0 release was largely focussed on the following big changes, alongside a number of other bug fixes.
Generate a pure Go 1.22+ net/http server
With Go 1.22+'s enhanced routing, it's now easier than ever to be able to write a pure-Go HTTP service, and thanks to a contribution from @thedadams we now have a std-http-server, further documented in the Supported Servers section in the README.
Note
Not seeing this working, i.e. seeing a 404 page not found? Make sure that the go directive in your project's go.mod is updated!
In the future we're going to see if we can preemptively warn you if you're not quite set up correctly.
Documentation overhaul
A significant undertaking in this release was to rewrite pretty much every line of documentation we had, as well as introducing a number of additional examples and test cases.
We're excited to hear your feedback on the new structure of the README, the additional docs added, and whether there are any additional examples that may be of use.
JSON Schema configuration
In the spirit of documentation, we now also have a JSON schema which can be found further documented in the Usage section in the README.
This not only gives a separate definition of fields and their meaning, but it can be used with IDEs for autocompletion and validation, allowing for a much better Developer Experience.
kin-openapi upgrade
A few big upgrades have come in kin-openapi, which we use for the underlying OpenAPI parsing and validation, which included a significant breaking change that meant that consumers of oapi-codegen couldn't upgrade the kin-openapi version until we had made changes in oapi-codegen.
This has additionally been set up as an FAQ as it's one we commonly get.
🚀 New features and improvements
- feat: add ability to tweak generated names (including use of initialisms) (#1041) @wtertius
- docs: revamp README, add a CONTRIBUTING.md and add a JSON Schema for configuration files (#1485) @jamietanna
- feat: add support for Go 1.22+ net/http routing (#1475) @thedadams
🐛 Bug fixes
- Bug: using x-go-type-name results in missing types (#1397) @jamesphillpotts-fr
- fix: correctly register Fiber middleware (#1615) @jamietanna
- fix: ensure we pre-import
nullable(#1585) @jamietanna - Prefactor: Changes from #1475 (#1480) @jamietanna
- Ensure docstring comment names are set correctly (#1457) @ConorPKeegan
📝 Documentation updates
- docs(sponsors): add a Sponsors section in README (#1635) @jamietanna
- docs(examples): document how to set up authenticated middleware with a non-
echoserver (#1627) @jamietanna - docs(extensions): add missing
x-go-type-namedocs (#1616) @jamietanna - chore: log warning when using 3.1.x (#1592) @jamietanna
- docs: link to blog post for syncing vendored specs (#1580) @jamietanna
- docs: correct
std-http-serverexample (#1576) @sajjanjyothi - docs: revamp README, add a CONTRIBUTING.md and add a JSON Schema for configuration files (#1485) @jamietanna
- docs: update OpenAPI spec links to
mainbranch (#1493) @dharsanb - Add Fiber example in README (#1495) @alexandregv
- Prefactor: Changes from #1475 (#1480) @jamietanna
- docs: use relative links to files (#1471) @alexandear
👻 Maintenance
- chore: add missing test case for replaceInitialism (#1624) @alexandear
- Simplify extensions merge in
mergeOpenapiSchemas(#1424) @Juneezee - chore: log warning when using 3.1.x (#1592) @jamietanna
- refactor: extension variable instead of accessing extensions directly (#1448) @alexandear
- chore(deps): remove dependency on
golang.org/x/lint(#1588) @jamietanna - docs: revamp README, add a CONTRIBUTING.md and add a JSON Schema for configuration files (#1485) @jamietanna
- chore: add test case for
additionalPropertiesbug (#1528) @jamietanna - Prefactor: Build changes for #1475 (#1482) @jamietanna
- Prefactor: Changes from #1475 (#1480) @jamietanna
- Simplify CI build matrix + build against Go 1.22 (#1459) @jamietanna
📦 Dependency updates
16 changes
- fix(deps): update module golang.org/x/tools to v0.21.0 (#1601) @renovate
- fix(deps): update module github.com/getkin/kin-openapi to v0.124.0 (#1532) @renovate
- chore(deps): update module github.com/golangci/golangci-lint to v1.59.0 (#1625) @renovate
- chore(deps): update module github.com/golangci/golangci-lint to v1.58.2 (#1618) @renovate
- chore(deps): update module github.com/golangci/golangci-lint to v1.58.1 (#1603) @renovate
- fix(deps): update module golang.org/x/text to v0.15.0 (#1591) @renovate
- chore(deps): update module github.com/golangci/golangci-lint to v1.58.0 (#1586) @renovate
- fix(deps): update module golang.org/x/tools to v0.20.0 (#1531) @renovate
- fix(deps): update module golang.org/x/tools to v0.19.0 (#1289) @renovate
- fix(deps): update module github.com/getkin/kin-openapi to v0.123.0 (#1431) @renovate
- chore(deps): update module github.com/golangci/golangci-lint to v1.57.2 (#1466) @renovate
- fix(deps): update module github.com/stretchr/testify to v1.9.0 (#1479) @renovate
- chore(deps): update actions/checkout action to v4 (#1290) @renovate
- chore(deps): update actions/setup-go action to v5 (#1375) @renovate
- Update release-drafter/release-drafter action to v6 (#1453) @renovate
- Update module github.com/golangci/golangci-lint to v1.56.1 (#1455) @renovate
v2.1.0: Nullable, external reference improvements, x-order, and many more!
🔊 Notable features
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:
S:
type: object
properties:
Field:
type: string
nullable: true
required: []The current behaviour in oapi-codegen is to generate:
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 withS.Field == nil) - does this field have a value? (
S.Field != nil && *S.Field == "123")
Therefore, as requested in #1039, this is now possible to represent with the nullable.Nullable type from our new library, oapi-codegen/nullable.
If you configure your generator's Output Options as so:
output-options:
nullable-type: trueYou will now receive the following output:
type S struct {
Field nullable.Nullable[string] `json:"field,omitempty"`
}Note that this is opt-in only, due to it being a break in existing signatures and behaviour.
You can find out more about how this works in a blog post with further details.
External references are now handled better
A big change has come in which handling of external references (also called import mappings) is much more resilient and predictable for generated code.
This allows cases where multiple files referencing each other (for instance if you've split your API across multiple files, and join them using $refs) now correctly generate code.
There are a few cases that won't be covered, that we'll complete in #1440 but until then, it hopefully should work better.
Thank you to Ejendomstorvet for sponsoring this work.
🚀 New features and improvements
- Add support for x-order extension (#1190) @filintod
- Make arrays use concrete types, not aliases. (#1246) @jkj
- feat: filter by operation ids (#929) @johanneswuerbach
- Allow generating
nullable.Nullablefor nullable properties (#1404) @sonasingh46 - Support media type parameters for
IsMediaTypeJson(#1386) @jamietanna - Pass
.RequiredtoBindStyledParameterWithLocationandBindStyledParameter(#1315) @renom
🐛 Bug fixes
- Fix: Ensure external refs are propagated to generated code (#1389) @jamietanna
- Fix: Refer to external refs correctly in strict interfaces (#1387) @jamietanna
- refactor(cmd): Use
os.Exit(1)only frommain()(#1398) @alexandear - Fix binding for JSON body (#1299) @ShouheiNishi
- Fix: Handle code generation for all multipart content-types (#1385) @ShouheiNishi
- Pass
.RequiredtoBindStyledParameterWithLocationandBindStyledParameter(#1315) @renom
📝 Documentation updates
- Fixes confusing indentation for example code in README.md (#1414) @mtskg
- Document how to use
import-mappingwith URLs (#1428) @jamietanna - Fix typo in README.md (#1351) @eltociear
👻 Maintenance
- Fix typos in flag, tests, doc, and comments (#1287) @alexandear
- add unit tests for go type gen function (#1423) @sonasingh46
- Use non-deprecated function names for oapi-codegen/runtime (#1359) @cimitan
- Onboard to Release Drafter (#1350) @jamietanna
📦 Dependency updates
- Update module github.com/golangci/golangci-lint to v1.55.2 (#1285) @renovate
- feat: bump github.com/getkin/kin-openapi to v0.122.0 (#1364) @chrisgacsal
- Update module golang.org/x/text to v0.14.0 (#1349) @renovate
New Contributors
- @renom made their first contribution in #1315
- @eltociear made their first contribution in #1351
- @chrisgacsal made their first contribution in #1364
- @cimitan made their first contribution in #1359
- @sonasingh46 made their first contribution in #1423
- @mtskg made their first contribution in #1414
- @jkj made their first contribution in #1246
- @filintod made their first contribution in #1190
v2.0.0: Remove deprecated packages
As announced in oapi-codegen v2 is coming, this is a release to perform some cleanup, drastically reducing the dependency graph for users of the library, and migrating to multi-repo middleware and utility packages that can evolve separately to the code generator itself.
There's more details in https://www.jvt.me/posts/2023/10/23/oapi-codegen-v2-decrease/ in the exact benefits ??, but the key metrics you will be interested in seeing are:
| Before (v1.13.0) | After (v2.0.0) | |
|---|---|---|
| Vendored dependency size (MB) | 40 | 6 |
| Direct dependencies | 15 | 6 |
| Indirect dependencies | 95 | 34 |
Key changes
Full Changelog: v1.16.2...v2.0.0
As a consumer, for the most part you shouldn't have much to do, as if you've been using oapi-codegen v1.15.0 or later, you should be using the new packages.
If you use this as a library or execute it as part of go run you will need to update module import paths:
-//go:generate go run github.com/deepmap/oapi-codegen/cmd/oapi-codegen --config=config.yaml spec.yaml
+//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yamlIf you're installing the package via go install, you'll need to run the following instead:
-go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@latest
+go install github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@latestMove pkg/testutil to its own package + remove it
Similar to the below changes, we've moved pkg/testutil to its own package, and removed it from the codebase.
The changes for you as a consumer can be seen here.
This is almost a drop in replacement, the key difference is that there is no longer a RequestBuilder.Go method, as it is replaced by the RequestBuilder.GoWithHTTPHandler.
Remove deprecated packages:
For the packages:
pkg/chi-middlewarepkg/fiber-middlewarepkg/gin-middlewarepkg/middlewarepkg/runtimepkg/types
These have been deprecated because they are now hosted as individual modules at https://github.com/oapi-codegen/. Doing so allows for their dependencies to be separated from each other, so your transitive module dependencies decrease. Any code which you generate using v1.15.0 will already refer to these modules in their new location.