[Server] Gzip-compress /api/bootstrap and /api/resync responses - #171
Merged
Conversation
…140) Adds the compression middleware, mounted only under /api and excluding /api/stream so gzip's write-buffering never delays live SSE delivery. The exclusion matches on the full mounted path, not a router-relative one, since compression's filter runs lazily after Express restores request.path.
|
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.



📖 Description
/api/bootstrapand reset-mode/api/resynccan return up toserverMaxSyncLines(≤ 500) fullLogLineobjects — roughly 150–250 KB of repetitive JSON (rawLine/messageboth carry the line text, plus timestamps and logger names duplicated across rows). This log-shaped text compresses very well, so responses are now gzip-compressed via the standardcompressionmiddleware.The middleware is added as a new small module,
createApiCompression()insrc/server/apiCompression.ts, and mounted only under/api, ahead of the router./api/streamis explicitly excluded, sincecompression's write-buffering would delay or batch SSE events and defeat live delivery.One implementation detail worth calling out:
compression'sfiltercallback runs lazily on first write rather than at mount time, so by the time it runs, Express has already restoredrequest.pathto the full incoming path (/api/stream), not the router-relative path (/stream) a synchronously-invoked middleware would see at the same mount point. This was verified with a test (see below) rather than assumed, per the issue's own caution about this.🎫 Issues
Closes #140
👩💻 Reviewer Notes
compression(+@types/compressiondev dependency) — this was option 2 in the issue, the recommended implementation if compression is wanted./api/healthstays uncompressed automatically (small responses fall under compression's default 1 KB threshold).dist/clientstatic serving and/api/streamare both left untouched.GET /api/bootstrapwithAccept-Encoding: gzipand confirm aContent-Encoding: gzipresponse header;GET /api/streamand confirm noContent-Encodingheader and immediate event delivery.📑 Test Plan
src/server/apiCompression.test.ts:gzip-compresses a large /api/bootstrap response and preserves the JSON body— assertsContent-Encoding: gzipand that the JSON body round-trips correctly.never compresses /api/stream so SSE delivery is not buffered— asserts noContent-Encodingheader is set for/api/stream.npm test(157/157 passing),npm run typecheck, andnpm run buildall pass locally.✅ Checklist
General
npm testandnpm run typechecklocally and they pass.Server-specific (
src/server)src/server(tailer, parser, buffer, routes, SSE hub, config, etc.).src/server/types.tsin sync withsrc/client/state.tsfor any shared payload change (see ARCHITECTURE.md). — not applicable, no payload shape changed.⏭ Next Steps
Create release - version 2.5.0