Repository navigation
feat: hand the hot token over without requiring it - #2486
Conversation
`hot.token` also takes `{ value, required }`. With `required: false` the
token is minted (or `value` used) and given to the injected client, but the
endpoint lets a client without it through, so a server with policy of its
own can compare it in `onConnect`. `hot.tokenRequired` says which applies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
🦋 Changeset detectedLatest commit: bff00a8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
WalkthroughThe Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to
|
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
93d10270-b439-4198-b7e8-7c0ac217a556
📒 Files selected for processing: 12
.changeset/hot-token-not-required.mdREADME.mdsrc/hot.jssrc/index.jssrc/options.check.jssrc/options.jsonsrc/utils.jstest/hot.test.jstest/inject-client.test.jstypes/hot.d.tstypes/index.d.tstypes/utils.d.ts
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2486 +/- ##
==========================================
+ Coverage 96.55% 96.59% +0.04%
==========================================
Files 24 24
Lines 2640 2644 +4
==========================================
+ Hits 2549 2554 +5
+ Misses 91 90 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
…th allowedOrigins
8.5.0 takes `hot.token: { required: false }` (webpack/webpack-dev-middleware#2486),
so the check for it, the tests' stand-in token and the README notes on older
versions go, as their TODOs said. The token is handed to the injected client
only once `allowedOrigins` is set: under "auto" the socket's url and who it
lets in stay exactly as before, with a TODO to always hand it over in the
next major release.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
…th allowedOrigins
8.5.0 takes `hot.token: { required: false }` (webpack/webpack-dev-middleware#2486),
so the check for it, the tests' stand-in token and the README notes on older
versions go, as their TODOs said. The token is handed to the injected client
only once `allowedOrigins` is set: under "auto" the socket's url and who it
lets in stay exactly as before, with a TODO to always hand it over in the
next major release.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
* fix: separate origin authorization from allowed hosts * test: clarify origin configuration coverage * fix: support HMR on a separate port * feat: keep "auto" origins as they were, deny secrets in static, accept the hot token `allowedOrigins: "auto"` (the default) now keeps the origin rules derived from `allowedHosts` exactly, so nothing changes until the option is set; `allowedHosts: "all"` and an `Access-Control-Allow-Origin: *` header still open every origin under it, with a deprecation warning. A list allows the page's own hostname plus the listed origins, answers them with CORS headers and allows a plain script they load by its `Referer`; "all" allows every origin and keeps the `Host` check. One rule now serves ordinary requests, proxied WebSocket upgrades, hot clients and the internal endpoints. The injected hot client is handed a per-run token the endpoint does not require (webpack-dev-middleware#2486), and a client carrying it may connect from an origin the server does not know; skipped with an older middleware. `static.deny` refuses secrets (`.env*`, keys and certificates, `.npmrc`, `.yarnrc.yml`, `.git`) or patterns of your own in a static directory, and hides them from listings; off by default until the next major. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA * chore: note what the next major release removes from the origin rules Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA * fix: keep the CommonJS build's injected require usable in hotOptions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA * chore: regenerate types Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA * docs: describe a list's hostname rule and the token's middleware requirement Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA * feat: answer an allowed origin's preflight and credentialed requests With allowedOrigins set, a listed origin gets Access-Control-Allow-Credentials, and an allowed origin's preflight gets the method, headers and Private Network Access it asks for, so a fetch with custom headers, another method or cookies works from it. "auto" is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA * test: cover the token, static.deny's edge cases and the list without a Host The hot-token tests now give the middleware a token when it has none, so this server's own check runs on any webpack-dev-middleware rather than being skipped; the optional-token detection takes a schema and is tested on its own. static.deny gets the `?` glob, an undecodable path and the Windows rules. The allowedOrigins entry check the schema already makes is gone, and the token is read off the query without a try that cannot fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA * fix: give credentials to listed origins only A list also allows the page's own hostname on any port, and cookies do not tell ports apart, so Access-Control-Allow-Credentials went to any other local page with it. It now goes only to an origin listed by name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA * chore: say in the TODOs to bump webpack-dev-middleware for the optional token Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA * feat: require webpack-dev-middleware 8.5.0 and hand the token over with allowedOrigins 8.5.0 takes `hot.token: { required: false }` (webpack/webpack-dev-middleware#2486), so the check for it, the tests' stand-in token and the README notes on older versions go, as their TODOs said. The token is handed to the injected client only once `allowedOrigins` is set: under "auto" the socket's url and who it lets in stay exactly as before, with a TODO to always hand it over in the next major release. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA --------- Co-authored-by: alexander-akait <4567934+alexander-akait@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
hot.tokenalso takes{ value, required }.With
required: false, the token is minted (orvalueis used) and handed to the injected client exactly astoken: truedoes. The endpoint, however, lets a client without it through. That is for a server with policy of its own: it readsinstance.tokenand compares it inonConnect, next to whatever else it knows, and closes a client that has neither.webpack-dev-server needs this (webpack/webpack-dev-server#5770). It already allows the page's own origin, and it can now also accept the token, so HMR works behind a proxy or under a hostname the origin check does not know, with no list of origins. Requiring the token outright would refuse clients the middleware did not inject, which is why the default stays
false.HotInstance.tokenRequiredsays which mode applies;tokenis still the value the client is given.{}and{ value: true }behave liketrue;{ value: false }likefalse.hot.token, with anonConnectexample) and a minor changeset.Tests:
test/hot.test.js(WebSocket and Server-Sent Events: handed over, not required,onConnectsees the carried token, object defaults) andtest/inject-client.test.js(no warning when not required). Unit suite: 7385 passed; the 2 failures are the root-onlywriteToDiskEACCES cases that fail onmaintoo.Generated by Claude Code
Summary by CodeRabbit