guibranco / guibranco/logstream-server
[FEATURE] HTTP response compression (gzip)
- Dominant language
- PHP
- Stars
- 1
- Forks
- 0
- Avg merge
- 1m
- Merged PRs (30d)
- 4
Description
## Summary
Compress `GET /api/logs` and `GET /api/export` responses with gzip when the client sends `Accept-Encoding: gzip`, significantly reducing bandwidth usage for log-heavy queries.
## Motivation
Log entry JSON is highly repetitive (same field names on every entry) and compresses extremely well — typical ratios of 8:1 to 15:1. For a query returning 1000 entries (~500 KB), gzip reduces the payload to ~40–60 KB.
## Implementation
In the ReactPHP HTTP server, after building the JSON response body:
```php
if (str_contains($request->getHeaderLine('Accept-Encoding'), 'gzip')) {
$compressed = gzencode($body, 6);
return new Response(200,
array_merge($headers, [
'Content-Encoding' => 'gzip',
'Vary' => 'Accept-Encoding',
]),
$compressed,
);
}
```
Apply to: `GET /api/logs`, `GET /api/logs/{id}`, `GET /api/stats`, `GET /api/export`
Do **not** compress: POST responses, `/api/health`, `/api/info` (already tiny).
## Acceptance criteria
- [ ] Responses compressed when `Accept-Encoding: gzip` is present
- [ ] `Content-Encoding: gzip` and `Vary: Accept-Encoding` headers set correctly
- [ ] Non-gzip clients receive uncompressed responses unchanged
- [ ] Applied to `/api/logs`, `/api/logs/{id}`, `/api/stats`, `/api/export`
- [ ] Unit test verifying compressed vs uncompressed branches
- [ ] PHP `zlib` extension noted in deploy docs and Dockerfile
Contributor guide
Research direction
Start at the ReactPHP HTTP server response construction and locate the handlers for the four listed GET endpoints. Add coverage for compressed and uncompressed branches, then verify the response headers and body behavior against the acceptance criteria. Update the deploy docs and Dockerfile to note the PHP zlib requirement.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php
- Domain
- api, backend, devops, performance
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100