fix(swagger-module): return reply from async route handlers#3911
Merged
kamilmysliwiec merged 1 commit intoMay 14, 2026
Merged
Conversation
The JSON, YAML and swagger-ui-init.js handlers were converted to async functions in 11.3.0 to support an async patchDocumentOnRequest hook, but the bare `res.send(...)` calls were left without a `return`. When the application registers @fastify/compress (or any module attaching an onSend hook that inspects the resolved payload), the async function resolves to `undefined` and Fastify emits an empty compressed body even though `reply.send()` was invoked manually. Returning the reply from each affected handler restores correct serialization with brotli/gzip while keeping the original behavior in all other configurations. Closes #3908
Closed
1 task
Member
|
lgtm |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
When
@fastify/compressis registered on aNestFastifyApplication, Swagger UI renders blank becauseGET /docs-json,GET /docs-yaml, andGET /docs/swagger-ui-init.jsall return HTTP 200 with an empty body as soon as the client sends anAccept-Encoding: br|gzipheader (which every modern browser does by default).In 11.3.0, the JSON, YAML and
swagger-ui-init.jsroute handlers inlib/swagger-module.tswere converted from sync toasyncto support an asyncpatchDocumentOnRequesthook, but the bareres.send(...)calls were left without areturn. The async function therefore resolves toundefined. When@fastify/compressattaches itsonSendhook to compress the response, it serializesundefinedand emits an empty compressed body — even thoughreply.send()was called manually inside the handler.The HTML page and static assets (served through
@fastify/static) are unaffected, which is why the page loads but the UI never initializes.Plain
curlrequests withoutAccept-Encodinglook fine, which made the regression invisible to the existing test suite.Closes #3908
What is the new behavior?
The 4 affected async handlers now
return res.send(...), mirroring the pattern already used in thepatchDocumentOnRequestbranches. The async function resolves to the reply, theonSendhook receives the actual payload, and compression works correctly.Affected handlers (line numbers from this PR):
swagger-module.ts:212—swagger-ui-init.js(primary route)swagger-module.ts:244—swagger-ui-init.js(trailing-slash route)swagger-module.ts:326—/docs-jsonswagger-module.ts:353—/docs-yamlThe sync HTML handler (
swaggerUiHtml, line 276) was left unchanged because it is not affected.Tests
Added a new
describe('with @fastify/compress registered', ...)block ine2e/fastify.e2e-spec.tscoveringAccept-Encoding: brandgzipagainst/apidoc-json,/apidoc-yaml, and/apidoc/swagger-ui-init.js. Verified that all 4 new tests fail on master (each asserts body length > 0 — currently 0) and pass with this fix.Added
@fastify/compressas adevDependency(already a peer of@nestjs/platform-fastifyconsumers).Full test suites green: 122 e2e passed, 368 unit passed,
tsc -p tsconfig.build.jsonclean.Does this PR introduce a breaking change?
The change preserves the existing behavior for callers not using
@fastify/compress(sincereply.send()already terminates the response) and is identical to what thepatchDocumentOnRequestbranches do today.Other information
The fix was validated end-to-end in a real project (NestJS 11.1.20 +
@nestjs/platform-fastify11.1.20 +@fastify/compress8.3.1 +fastify5.8.5) by patchingnode_moduleslocally and confirming that:curl -s -H 'Accept-Encoding: br' /api/docs-json | wc -creturns ~12 KB of brotli payload (was 0 before)