- Docs
- Rules
Header Rules
Add, change or remove HTTP headers on the request to your server and the response to your visitors.
On this page
A header rule edits HTTP headers at the edge: on the request to your server, the response to your visitor, or both — say Content-Security-Policy, X-Frame-Options, or a shared secret proving traffic came through nsin.
The two directions
| Applied | Your server sees it | The visitor sees it | |
|---|---|---|---|
| Request | Before nsin calls your server | Yes | No |
| Response | Before the answer leaves the edge | No | Yes |
Response edits happen after the cache: a cached page still gets today's headers, no purge needed.
The operations
A rule is an ordered list of operations: direction, action, header and (for set/add) a value.
| Action | What it does |
|---|---|
| Set | Replace whatever is there with your value. |
| Add | Append your value, keeping anything already sent. |
| Remove | Delete the header entirely. Takes no value. |
Operations run in list order — later wins over earlier on the same header.
A remove may end in *: X-Debug-* deletes every header starting with X-Debug- (set/add need an exact name). The reserved list still applies to every match, so a wildcard can't strip a header nsin owns.
Rules add up
The one rule type where every matching rule runs — elsewhere, the first match wins. Same header, two rules: the lower one wins; drag to reorder.
Scope
Narrow by records, hostname and path — see Rules Overview.
Two limits are specific here:
- Visitor IP scope only works on response-only rules. A request header changes what nsin fetches without changing the cache key — one visitor's copy would reach everyone.
- Gateway records are not eligible. One gateway hostname fronts many customers' upstreams; a credential header there reaches someone else's traffic.
Dry run
A header rule can be saved in dry run: it matches and records, but passes through untouched.
Limits
| Limit | Value |
|---|---|
| Operations per rule | 16 |
| Length of one value | 4 KB |
| Total added per rule | 8 KB (name + value of every set/add) |
All three are checked at save time; an oversized rule fails clearly instead of a 431 later.
A request's total sums across all matching rules; the edge caps that combined total at 8 KB per direction too, dropping overflow. Removals never count toward the cap.
Headers you can't change, and why
nsin refuses a small set of names the edge computes itself — refusals return 400 naming the header and reason.
| Direction | Header | Why |
|---|---|---|
| Request | Host |
Picks the TLS name and cache slot; override on the record, origin route, or pool. |
| Request | Content-Length |
Recomputed from bytes forwarded; a wrong value can store a truncated page. |
| Request | Transfer-Encoding, Connection, Upgrade, Keep-Alive, Proxy-Connection, TE, Trailer |
Hop-by-hop; never travel past the edge. |
| Request | X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Port, X-Real-IP, True-Client-IP, Forwarded |
Filled from the real connection; a fixed value fakes the visitor. |
| Request | CDN-Loop |
Loop counter other CDNs read; a foreign marker earns a 502 from CDN-fronted origins. |
| Request | Cache-Control, If-None-Match, If-Modified-Since, If-Match, If-Unmodified-Since, If-Range, Range, Accept-Encoding |
Rewritten per fetch path by the edge. |
| Request | Sec-WebSocket-* |
A rule-set handshake key would defeat the tunnel detection reading it. |
| Request | Nsn-*, X-Nsin-*, X-Mafar-* |
nsin's own namespace; writing one by rule would be a forgery. |
| Response | Content-Length |
Recomputed from bytes actually written. |
| Response | Transfer-Encoding, Connection, Upgrade, Keep-Alive |
Hop-by-hop again. |
| Response | Content-Encoding |
Owned by the edge's compressor; stored content stays uncompressed. |
| Response | Vary |
Not cache-keyed — a false variance risks one visitor's page reaching another. |
| Response | Server |
Stamped last, deliberately, as the final change before leaving. |
| Response | Strict-Transport-Security |
Can't be undone once seen; belongs to the ramp on Security → HSTS, raising the duration one step per save. See Security Headers. |
| Response | Nsn-* |
nsin's own analytics and diagnostics surface. |
The exception: you may remove them
Three request headers are refused for set/add but allowed for remove: Cookie, Authorization, Nsn-Connecting-IP. nsin strips credentials before refreshing a cached page, so only remove agrees with that strip — drop Cookie before your server for a cacheable page, or Nsn-Connecting-IP before a third-party origin to keep visitor addresses private.
Headers nsin manages for you
X-Content-Type-Options,Referrer-Policy, the fingerprint strip: per-domain toggles — see Security Headers.Strict-Transport-Securityand minimum TLS version: live on Security → HSTS.- Headers nsin always adds, like
Nsn-Connecting-IP: listed in Proxy Headers.
What a header rule cannot reach
- Your own rules. Header rules run last, after the WAF, bot detection, fingerprinting and rewrites.
- WebSocket upgrades. A
101handshake never reaches response headers; request operations still do. - nsin's own pages. Error, challenge, basic-auth and block responses come from the edge, not your server.
Examples
Security headers for the whole site
- Response · set ·
X-Frame-Options·SAMEORIGIN- Response · set ·
X-XSS-Protection·0- Response · set ·
Permissions-Policy·camera=(), microphone=()
Prove to your server that traffic came through nsin
- Request · set ·
X-Edge-Secret·a-long-random-stringHave your server refuse anything without it — see trusting nsin's proxy headers.
Make a marketing page cacheable
- Path:
/landing/*- Request · remove ·
CookieThe server stops seeing a session, so the page can be cached.
Stop leaking your framework
- Response · remove ·
X-Powered-By- Response · remove ·
X-AspNet-*
Common questions
I added a response header but I don't see it. Check the record is proxied and the rule isn't in dry run — error/challenge pages come from nsin, not your server.
Do I have to purge the cache after changing a response header? No — it applies after the cache, live on the next request.
Two rules set the same header. Which wins? The one lower in the list. See the order of rules.
Can I use the visitor's country or the ray id as a value? Not yet. Values are fixed text today.
Can a header rule replace my origin's CORS or CSP setup? It can add or override those headers; if your app computes them per response, leave it to the app.