Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion website/app/docs/deployment/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ npm run start -- --port 8080</code-block>
<li><code>Permissions-Policy: camera=(), microphone=(), geolocation=()</code></li>
<li><code>Strict-Transport-Security: max-age=63072000; includeSubDomains</code> in production over HTTPS only</li>
</ul>
<p>HSTS is gated to production AND HTTPS. WebJs detects the original scheme from <code>X-Forwarded-Proto</code> (the header the trusted edge proxy forwards after terminating TLS), honoring the same proxy-trust posture as the rest of the framework, so HSTS is never set on a plain-HTTP hop or in dev. Set <code>WEBJS_NO_TRUST_PROXY=1</code> to stop trusting forwarded headers when the container is directly exposed. It is one flag, read in one place, honored by everything that resolves the request ORIGIN: the URL rewrite, the HSTS scheme check, and the CSRF host resolution alike. It covers client-IP resolution too, so it outranks an explicit <code>rateLimit({ trustProxy: true })</code> and puts that limiter back on the stamped socket IP. Set it only when nothing trusted sits in front of the container, because on a genuinely proxied deploy it makes the legacy CSRF fallback compare <code>Origin</code> against the internal <code>Host</code> and reject a legitimate cross-host request.</p>
<p>HSTS is gated to production AND HTTPS. WebJs detects the original scheme from <code>X-Forwarded-Proto</code> (the header the trusted edge proxy forwards after terminating TLS), honoring the same proxy-trust posture as the rest of the framework, so HSTS is never set on a plain-HTTP hop or in dev. Set <code>WEBJS_NO_TRUST_PROXY=1</code> to stop trusting forwarded headers when nothing trusted sits in front of the container. It is one flag, read in one place, honored by everything that resolves the request ORIGIN: the URL rewrite, the HSTS scheme check, and the CSRF host resolution alike. It covers client-IP resolution too, so it outranks an explicit <code>rateLimit({ trustProxy: true })</code> and puts that limiter back on the stamped socket IP. On a genuinely proxied deploy setting it is a misconfiguration, and it shows up as one: the legacy CSRF fallback then compares <code>Origin</code> against the internal <code>Host</code> and rejects a legitimate cross-host request. Behind a CDN the flag is not what protects you from a forged <code>X-Forwarded-Host</code>, which Cloudflare and Railway forward rather than overwrite. Anything shared that you derive from the request origin must be keyed by that origin instead, the way the HTML response cache already keys itself.</p>
Comment thread
vivek7405 marked this conversation as resolved.
Comment thread
vivek7405 marked this conversation as resolved.
Comment thread
vivek7405 marked this conversation as resolved.
<p>A default is set only when the response does not already carry that header, so anything your middleware, a <code>route.&#123;js,ts&#125;</code> handler, or <code>expose</code> sets always wins.</p>
<h4>Per-path overrides</h4>
<p>Declare per-path header rules in <code>package.json</code> under <code>"webjs": &#123; "headers": [...] &#125;</code>, shaped like Next's. The <code>source</code> is a path pattern matched with the native URLPattern API, so <code>:param</code> and <code>:rest*</code> tokens work:</p>
Expand Down
Loading