## Summary
- Defer `AsyncLocalStorage` creation when
`v8.startupSnapshot.isBuildingSnapshot()` is true, making Koa compatible
with Node.js startup snapshots
- Register a `v8.startupSnapshot.addDeserializeCallback` to properly
initialize `ctxStorage` after snapshot restoration
- Extract `getAsyncLocalStorage()` helper to consolidate creation logic
## Test plan
- [x] All 429 existing tests pass with 0 failures
- [x] `currentContext` tests verify both `asyncLocalStorage: true` and
custom `AsyncLocalStorage` instance paths work correctly
- [x] Normal (non-snapshot) code path is unchanged —
`v8.startupSnapshot?.isBuildingSnapshot?.()` returns `undefined` in
regular execution
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a malformed Host header containing @ symbol (e.g., "evil.com:fake@legitimate.com")
is received, use URL parser to correctly extract the actual host portion instead of
naively splitting by colon which would return attacker-controlled value.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Description
- closes#1834
- closes#1882
- closes#1889
## Checklist
- [x] I have ensured my pull request is not behind the main or master
branch of the original repository.
- [x] I have rebased all commits where necessary so that reviewing this
pull request can be done without having to merge it first.
- [x] I have written a commit message that passes commitlint linting.
- [x] I have ensured that my code changes pass linting tests.
- [x] I have ensured that my code changes pass unit tests.
- [x] I have described my pull request and the reasons for code changes
along with context if necessary.
## Checklist for 1834 (before re-pinging team)
- [x] Update stackblitz - [stackblitz demostrating error and
fix](https://stackblitz.com/edit/koa-patch-starter-pwupm4kr?file=README.md,index.js,patch%2Fkoa%2Flib%2Fapplication.js,vendor%2Fkoa%2Flib%2Fapplication.js)
- [x] Address comments
- [x] Re-review after merging 2 issues together
## Checklist
Added security-focused tests to verify:
1. Content-Type is preserved when already set
2. Content-Type is still set when not previously defined (backwards
compatibility)
3. The fix prevents XSS vulnerabilities with HTML and SVG files
credit "Luca Carettoni of Doyensec LLC" as [requested in the
advisory](https://github.com/koajs/koa/security/advisories/GHSA-c5vw-j4hf-j526).
## Checklist
- [x] I have ensured my pull request is not behind the main or master
branch of the original repository.
- [x] I have rebased all commits where necessary so that reviewing this
pull request can be done without having to merge it first.
- [x] I have written a commit message that passes commitlint linting.
- [x] I have ensured that my code changes pass linting tests.
- [x] I have ensured that my code changes pass unit tests.
- [x] I have described my pull request and the reasons for code changes
along with context if necessary.
## Checklist
- [x] I have ensured my pull request is not behind the main or master
branch of the original repository.
- [x] I have rebased all commits where necessary so that reviewing this
pull request can be done without having to merge it first.
- [x] I have written a commit message that passes commitlint linting.
- [x] I have ensured that my code changes pass linting tests.
- [x] I have ensured that my code changes pass unit tests.
- [x] I have described my pull request and the reasons for code changes
along with context if necessary.
This is a huge breaking change as it breaks `fs.createReadStream`
support. Instead, you'll have to make sure you'll handle the stream's
errors before it reaches the koa response logic. This is good as you'd
want to do this for all streams anyways. You can have an upstream
middleware like:
```js
app.use(async (ctx, next) {
await next()
// check if the object is a stream
if (ctx.body?.readable && typeof ctx.body?.pipe === 'function') {
await new Promise((resolve, reject) => { // wait for it to be either readable or throw an error
ctx.body.on('readable', () => resolve())
ctx.body.on('error', (err) => reject(err)) // TODO handle errors
})
}
})
```
closes#1420
jsdoc of options.asyncLocalStorage
## Checklist
- [x] I have ensured my pull request is not behind the main or master
branch of the original repository.
- [x] I have rebased all commits where necessary so that reviewing this
pull request can be done without having to merge it first.
- [x] I have written a commit message that passes commitlint linting.
- [x] I have ensured that my code changes pass linting tests.
- [x] I have ensured that my code changes pass unit tests.
- [x] I have described my pull request and the reasons for code changes
along with context if necessary.
## Checklist
use `node --test` instead of `jest`
See: https://github.com/koajs/koa/issues/1837#issuecomment-2323002820
- [X] I have ensured my pull request is not behind the main or master
branch of the original repository.
- [X] I have rebased all commits where necessary so that reviewing this
pull request can be done without having to merge it first.
- [X] I have written a commit message that passes commitlint linting.
- [X] I have ensured that my code changes pass linting tests.
- [X] I have ensured that my code changes pass unit tests.
- [X] I have described my pull request and the reasons for code changes
along with context if necessary.
The simple solution to drop special-cased `'back'` in
`response.redirect`.
I can't label but should be labeled as version-major.
This PR **does not** make use of Symbol as purposed in #904.
**Edit**
If this solution is acceptable, a deprecation should be added to Koa 2
on `'back'` use.
---------
Co-authored-by: Kevin Peno <kjpeno@outlook.com>
Fix#1570 Replace node querystring with URLSearchParams it mimics the
way that querystring works
## Checklist
- [x] I have ensured my pull request is not behind the main or master
branch of the original repository.
- [x] I have rebased all commits where necessary so that reviewing this
pull request can be done without having to merge it first.
- [x] I have written a commit message that passes commitlint linting.
- [x] I have ensured that my code changes pass linting tests.
- [x] I have ensured that my code changes pass unit tests.
- [x] I have described my pull request and the reasons for code changes
along with context if necessary.