Skip to content

[lts-active] Automatically compress route handler responses if not already compressed - #101280

Merged
eps1lon merged 2 commits into
releases/lts/activefrom
sebbie/backport-101220-to-releases-lts-active
Nov 6, 2026
Merged

eps1lon merged 2 commits into
releases/lts/activefrom
sebbie/backport-101220-to-releases-lts-active

Conversation

@eps1lon

@eps1lon eps1lon commented Nov 6, 2026 •

Copy link
Copy Markdown
Member

Backports #101220 to releases/lts/active.

…sed (#101220)

Route handler responses were never compressed when self-hosted.

`NodeNextResponse.appendHeader` stored every header value as an array,
even a single value. The compression middleware checks `Content-Type`
with the `compressible` package, which only accepts strings, so any
response sent through `sendResponse` (all app route handlers, including
prerendered ones served from the cache) failed the content-type filter
and skipped compression. `appendHeader` now keeps a single value as a
plain string, matching Node's own `appendHeader` semantics.

Fixes #101120
Closes #101201
We must strip CE and CL headers from `Response` returned from route
handlers due to
GHSA-pc58-hwjq-p385.
A `Response` from `fech()` is indistinguishable from a synthetic one.
Any provenance can get lost via `clone` or manual reconstruction based
on headers and body.
Instead, the responses from route handlers should be returned
uncompressed and be compressed by the outgoing server: now `next start`
or your hosting provider e.g. Vercel.

Route handlers should not return a `fetch()` without processing the body
as this needlessly adds CPU overhead due to `fetch()`'s automatic
decompression. Use a dedicated proxy library for that instead.

## test plan

- moved dev-only compression test to e2e and extended with small/large
and dynamic/static routes

<!-- NEXT_JS_LLM -->

---------

Co-authored-by: Claude Code (kimi-k3) <noreply@anthropic.com>
(cherry picked from commit 8fbd739)
@github-actions

github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Tests Passed

Commit: f0a433f
View workflow run

@eps1lon
eps1lon marked this pull request as ready for review November 6, 2026 10:59
@eps1lon
eps1lon enabled auto-merge (squash) November 6, 2026 15:15
lukesandberg added a commit that referenced this pull request Nov 6, 2026
, #101176) (#101307)

Backports these two fixes to `releases/lts/active`:
- [Pin Tailwind to 4.3.3 in create-next-app
(#101061)](#101061)
- [Pin Tailwind to 4.3.3 in no-double-tailwind-execution test
(#101176)](#101176)

Both cherry-pick cleanly (`-x`).

### Why

CI on `releases/lts/active` PRs (e.g. #101280) currently fails for the
same reasons canary did:

- **`no-double-tailwind-execution`** fails with `ERR_REQUIRE_ESM`.
`@tailwindcss/node@4.3.4` `require()`s the ESM-only
`magic-string@1.4.5`, which Node.js 20.9.0 can't load.
- **The create-next-app Tailwind tests** (`templates/app.test.ts`,
`matrix-pages-*`) fail with the same error, or with `npm ERR! notarget
No matching version found for @tailwindcss/oxide@4.3.5`.

Pinning `tailwindcss` and its bundler plugin to `4.3.3` fixes both, as
it did on canary.

### Verification

- The diff is identical to the upstream patches (same `git patch-id`).
- Prettier and ESLint are clean on the touched files.
- CI on this PR runs the affected tests.

<!-- NEXT_JS_LLM -->


<!-- fleet 91f3474f-6748-4c06-8329-d8d3673533dd -->

---------

Co-authored-by: vercel-fleet-prod[bot] <318278635+vercel-fleet-prod[bot]@users.noreply.github.com>
Co-authored-by: Jamiboy Mohammad <jamiboym@gmail.com>
Co-authored-by: Luke Sandberg <210140+lukesandberg@users.noreply.github.com>
@eps1lon
eps1lon merged commit 7d0dc76 into releases/lts/active Nov 6, 2026
222 of 224 checks passed
@eps1lon
eps1lon deleted the sebbie/backport-101220-to-releases-lts-active branch November 6, 2026 23:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants