Skip to content

refactor(codegen): better Swagger compression, modern naming#1909

Merged
mromaszewicz merged 18 commits into
oapi-codegen:mainfrom
gaiaz-iusipov:use-flate
May 1, 2026
Merged

refactor(codegen): better Swagger compression, modern naming#1909
mromaszewicz merged 18 commits into
oapi-codegen:mainfrom
gaiaz-iusipov:use-flate

Conversation

@gaiaz-iusipov

Copy link
Copy Markdown
Contributor

No description provided.

@gaiaz-iusipov gaiaz-iusipov requested a review from a team as a code owner February 21, 2025 19:13
@gaiaz-iusipov gaiaz-iusipov marked this pull request as draft February 21, 2025 19:19
@gaiaz-iusipov gaiaz-iusipov marked this pull request as ready for review February 21, 2025 19:38
@jamietanna

Copy link
Copy Markdown
Member

Thanks for this - is there an issue this solves? Or was this something you noticed and think it's worthwhile doing?

@kusari-inspector

kusari-inspector Bot commented Jun 15, 2025

Copy link
Copy Markdown

Kusari Inspector

Kusari Analysis Results:

Proceed with these changes

✅ No Flagged Issues Detected
All values appear to be within acceptable risk parameters.

No pinned version dependency changes, code issues or exposed secrets detected!

Note

View full detailed analysis result for more information on the output and the checks that were run.


@kusari-inspector rerun - Trigger a re-analysis of this PR
@kusari-inspector feedback [your message] - Send feedback to our AI and team
See Kusari's documentation for setup and configuration.
Commit: 7767cdf, performed at: 2025-09-28T17:35:41Z

Found this helpful? Give it a 👍 or 👎 reaction!

@gaiaz-iusipov

Copy link
Copy Markdown
Contributor Author

Thanks for this - is there an issue this solves? Or was this something you noticed and think it's worthwhile doing?

Hi! There’s no specific issue, these changes just provide a small performance boost:

  • reduce GC load (depending on the array size)
  • slightly reduce the size of the data in swaggerSpec
  • slightly speed up the decodeSpec() function

@kusari-inspector

Copy link
Copy Markdown

Kusari PR Analysis rerun based on - 7ceda90 performed at: 2025-06-15T13:56:55Z - link to updated analysis

@kusari-inspector

Copy link
Copy Markdown

Kusari PR Analysis rerun based on - 549d69f performed at: 2025-07-15T19:09:45Z - link to updated analysis

@kusari-inspector

Copy link
Copy Markdown

Kusari PR Analysis rerun based on - 65f9a84 performed at: 2025-07-17T09:44:18Z - link to updated analysis

@kusari-inspector

Copy link
Copy Markdown

Kusari PR Analysis rerun based on - 152681f performed at: 2025-07-28T17:48:33Z - link to updated analysis

@kusari-inspector

Copy link
Copy Markdown

Kusari PR Analysis rerun based on - de8869a performed at: 2025-08-29T15:40:28Z - link to updated analysis

@kusari-inspector

Copy link
Copy Markdown

Kusari PR Analysis rerun based on - 7767cdf performed at: 2025-09-28T17:35:58Z - link to updated analysis

@jamietanna

Copy link
Copy Markdown
Member

(Feel free to not keep this branch updated, when I come back to this PR, I'll get it updated / address any conflicts if needed)

@mromaszewicz

Copy link
Copy Markdown
Member

@greptileai

@mromaszewicz mromaszewicz added this to the v2.7.0 milestone Apr 26, 2026
@greptile-apps

greptile-apps Bot commented Apr 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces gzip with raw deflate (compress/flate) for embedding the OpenAPI spec in generated files, and introduces GetSpec() as the primary function (with GetSwagger() kept as a deprecated backward-compatible wrapper) plus a new GetSpecJSON() helper. All 90 generated fixture files are consistently regenerated, and call sites in examples and tests are updated to the new API. The deflate-only format sheds the gzip header/checksum overhead for slightly smaller embedded blobs, and the inline comment now explains why var []string{} is preferred over a chained const string.

Confidence Score: 5/5

Safe to merge; the only finding is a P2 shared-slice concern on the new GetSpecJSON helper

All changes are consistent across every backend and fixture file; GetSwagger() is retained as a deprecated wrapper preserving backward compatibility; the compression switch is symmetric between inline.go and inline.tmpl; no exported symbols are removed. The single P2 finding (GetSpecJSON returning a mutable reference to the cached slice) does not block merge.

pkg/codegen/templates/inline.tmpl — GetSpecJSON returns the raw cached slice without copying

Important Files Changed

Filename Overview
pkg/codegen/inline.go Switches compression from gzip to raw deflate (flate); error handling style improved; symmetric with template change
pkg/codegen/templates/inline.tmpl Renames GetSwagger→GetSpec (with deprecated wrapper), adds GetSpec and GetSpecJSON; GetSpecJSON returns the cached byte slice directly without copying, which is a shared-state risk
pkg/codegen/templates/imports.tmpl Swaps compress/gzip import for compress/flate to match inline.tmpl change
internal/test/compatibility/preserve-original-operation-id-casing-in-embedded-spec/spec_test.go Updates GetSwagger() call site to GetSpec(); correct and consistent with the deprecation
examples/petstore-expanded/echo/api/petstore-server.gen.go Generated file: compression format and API functions updated consistently with template changes

Reviews (2): Last reviewed commit: "Add GetSpec/GetSpecJSON; revert const-co..." | Re-trigger Greptile

Comment thread pkg/codegen/templates/inline.tmpl Outdated
@mromaszewicz

Copy link
Copy Markdown
Member

I'm going to build on top of your PR. It's good to use flate, we don't need the gzip headers, this will make a tiny difference, but I will retain the old behavior of breaking the compressed blob into individual array elements. Concatenating these is a negligible cost.

I will also take the opportunity to rename "GetSwagger" to "GetSpec", and expose the raw JSON via GetSpecJSON, this way, we can use other OpenApi middleware.

# Conflicts:
#	internal/test/externalref/packageA/externalref.gen.go
#	internal/test/externalref/packageB/externalref.gen.go
#	internal/test/issues/issue-1378/common/common.gen.go
#	internal/test/strict-server/chi/server.gen.go
#	internal/test/strict-server/echo/server.gen.go
#	internal/test/strict-server/fiber/server.gen.go
#	internal/test/strict-server/gin/server.gen.go
#	internal/test/strict-server/gorilla/server.gen.go
#	internal/test/strict-server/iris/server.gen.go
#	internal/test/strict-server/stdhttp/server.gen.go
@mromaszewicz mromaszewicz changed the title refactor(codegen): better Swagger compression refactor(codegen): better Swagger compression, modern naming May 1, 2026
Three follow-ups to PR #1909, all in `pkg/codegen/templates/inline.tmpl`
(plus the regenerated `*.gen.go` files and migrated callers):

1. Revert the embedded spec back to `var swaggerSpec = []string{...}`.

PR #1909 replaced the historical slice-of-chunks form with a single
`const swaggerSpec = "" + "chunk" + "chunk" + ...`. With thousands of
80-char chunks (large APIs produce them) the Go compiler folds the
chained `+` at compile time, and that fold is materially slower than
parsing a slice literal. `decodeSpec` now joins the slice via
`strings.Join` before base64-decoding; flate compression, base64
encoding, the 80-char chunk size, the lazy `decodeSpecCached` /
`rawSpec` pipeline, and `PathToRawSpec` all stay exactly as PR #1909
landed them.

2. Add `GetSpec() (*openapi3.T, error)` as the canonical accessor, and
demote `GetSwagger()` to a `// Deprecated:` thin wrapper.

The kin-openapi spec type was renamed from `openapi3.Swagger` to
`openapi3.T` years ago; `GetSwagger`'s name is a stale relic. `GetSpec`
carries the body that `GetSwagger` had, and `GetSwagger` becomes a
one-line `return GetSpec()` retained for backwards compatibility.
External callers still upgrading to a newer version of oapi-codegen
will see the `// Deprecated:` hint surfaced by gopls/godoc; in-tree
callers across `examples/` and `internal/test/` are migrated to
`GetSpec()` because the repo's lint rule rejects calls into deprecated
functions and would otherwise block CI.

3. Add `GetSpecJSON() ([]byte, error)` returning the embedded JSON.

Decompressed, base64-decoded, but not unmarshaled into `*openapi3.T`.
A one-line wrapper around the existing `rawSpec()` cache, so repeated
calls don't re-decompress. This fills a long-standing gap: callers who
want to operate on the raw OpenAPI document (re-marshal to YAML, hand
to a different parser, run an overlay, dump to disk) previously had to
either invoke `openapi3.T.MarshalJSON` after `GetSpec` or hand-roll
base64+flate decode.

Migrated callers (mechanical; no logic changes):

- 7 user-side example files under `examples/` (petstore variants for
  each framework, authenticated-api echo + stdhttp).
- 12 test files under `examples/petstore-expanded/*/petstore_test.go`,
  `internal/test/externalref/imports_test.go`,
  `internal/test/issues/issue1825/overlay_test.go`,
  `internal/test/compatibility/preserve-original-operation-id-casing-in-embedded-spec/spec_test.go`.

New test:

- `examples/petstore-expanded/chi/petstore_test.go::TestSpecAccess`
  covers `GetSpec` and `GetSpecJSON` end-to-end (asserts the bytes are
  valid JSON and the parsed spec has a non-empty `OpenAPI` version
  field). `GetSwagger` is intentionally not exercised — its body is
  `return GetSpec()` and the lint rule blocks an in-tree call. If we
  later want regression coverage for the wrapper specifically, one
  test annotated with `//nolint:staticcheck // SA1019` would do it.

Verification:

- `make generate` is idempotent; spot-checking
  `examples/petstore-expanded/chi/api/petstore.gen.go` confirms the
  slice form, the three new accessors, and the `// Deprecated:` marker
  on `GetSwagger`.
- `make test` passes (exit 0) across the root module and all eight
  child modules.
- `make lint` reports `0 issues.` across the same nine modules — no
  remaining in-tree calls into the deprecated wrapper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mromaszewicz

Copy link
Copy Markdown
Member

@greptileai rereview, comments addressed.

@mromaszewicz mromaszewicz merged commit b363ca5 into oapi-codegen:main May 1, 2026
18 checks passed
@jamietanna jamietanna added the chore Any maintenance tasks that are regular, not as important to call out in the changelog label May 1, 2026
@gaiaz-iusipov gaiaz-iusipov deleted the use-flate branch May 1, 2026 18:48
@gaiaz-iusipov

Copy link
Copy Markdown
Contributor Author

Hello, thank you. I would note that the original idea was to use the same approach that is used in protobuf code generation starting from version v1.36.6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore Any maintenance tasks that are regular, not as important to call out in the changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants