Skip to content

feat(rest): compress the docs surface via the existing gzip middleware#227

Merged
SyniRon merged 3 commits into
developfrom
agent/issue-218
Jun 30, 2026
Merged

feat(rest): compress the docs surface via the existing gzip middleware#227
SyniRon merged 3 commits into
developfrom
agent/issue-218

Conversation

@SyniRon

@SyniRon SyniRon commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Closes #218.

The docs handler served the embedded Scalar bundle (~3.6 MB) and the OpenAPI spec uncompressed. It sat outside the gzip negotiation the /api stack already runs, so the bundle shipped at full size on first paint.

This wraps the handler that DocsHandler returns in the existing GzipMiddleware. Docs responses now compress when the client sends Accept-Encoding: gzip, and a client that does not advertise gzip gets the bytes verbatim, exactly as before. The docs handler owns its own compression, so the public-listener split in servers/server.go stays a plain path dispatch and the /api chain is untouched (no double-wrap).

What changed

  • rest/docs.go: wrap the spec and static-asset handler in GzipMiddleware.
  • rest/docs_gzip_test.go (new): covers both modes. With Accept-Encoding: gzip the bundle and spec come back with Content-Encoding: gzip and decode byte-for-byte to the source; without it they stay verbatim. Also confirms the info.version stamping survives compression.

No changes to contract/ or openapi/openapi.yaml. The docs surface is not part of the golden corpus.

This was generated by AI

SyniRon added 3 commits June 29, 2026 21:05
The docs handler served the embedded Scalar bundle (~3.6 MB) and the
OpenAPI spec uncompressed, so they shipped full size on first paint even
though /api responses already negotiated gzip. This wraps the docs
handler in the existing GzipMiddleware, so the spec and the static assets
compress when a client sends Accept-Encoding: gzip and serve verbatim
when it does not. The handler owns its own compression, which keeps the
public-listener split a plain path dispatch and leaves the /api chain
alone.

rest/docs_gzip_test.go covers both modes: negotiated (Content-Encoding:
gzip, decodes back to the verbatim bytes, spec version stamp intact) and
not negotiated (served raw). The existing docs tests send no
Accept-Encoding and keep passing unchanged.

> *This was generated by AI*
Add a real-wire test over httptest.NewServer that fetches the Scalar
bundle with Accept-Encoding: gzip set by hand, so the transport leaves
the raw gzip stream alone. It proves the stale uncompressed
Content-Length that http.FileServer sets never reaches a length-enforcing
transport, which is acceptance criterion 4. The recorder-based tests
can't observe this, since a recorder enforces no Content-Length, so also
pin an empty Content-Length on those as a cheap regression catch.

Fix the docs.go wrap comment, which claimed this surface produces 304
conditional GETs. The embedded FS has no modtime or ETag, so
http.FileServer sends no validators and never answers a 304 here.

Replace the body-length guard in the verbatim test so a short or empty
body fails loudly instead of skipping the magic-byte check. Reword two
test comments that described the change instead of the behavior.

> *This was generated by AI*
The package-level doc still said a ResponseRecorder was enough for the
whole file and that the stale-Content-Length wire behavior lived in
gzip_test.go. Neither holds anymore: this file now has a
httptest.NewServer test that pins that behavior on a length-enforcing
transport, which a recorder can't observe. Rewrote the doc to say what
each test actually covers.

Also reworded the wire test's comment and one error message so the
direct Content-Length header assertion reads as the primary guard for
criterion 4, with the gunzip round-trip framed as byte-for-byte
integrity verification rather than the main truncation catch.

Comments and strings only, no behavioral change.

> *This was generated by AI*
@SyniRon SyniRon merged commit 99c379b into develop Jun 30, 2026
3 checks passed
@SyniRon SyniRon deleted the agent/issue-218 branch June 30, 2026 01:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Serve the docs assets gzip-compressed (3.6 MB Scalar bundle ships uncompressed)

1 participant