Working with Response Headers
1. Setting Single Header
| API | Detail |
|---|---|
res.set("X-Foo", "bar") | Express style |
res.header("X-Foo", "bar") | Alias |
res.setHeader("X-Foo", "bar") | Node native |
2. Setting Multiple Headers
Example: Object form
res.set({
"Cache-Control": "no-store",
"X-Request-Id": req.id,
"X-Frame-Options": "DENY"
});
3. Appending Headers
| Header | Multi-value reason |
|---|---|
Set-Cookie | Multiple cookies |
Vary | Multiple varying fields |
Link | HATEOAS / pagination |
WWW-Authenticate | Multiple auth schemes |
4. Getting Response Header
5. Removing Headers
Example: Strip framework fingerprint
app.disable("x-powered-by");
// Or per-response
res.removeHeader("X-Powered-By");
res.removeHeader("ETag");
| API | Notes |
|---|---|
res.removeHeader(name) | Node native; only works before res.end() |
6. Setting Content-Type
Example: type() shortcuts
res.type("json"); // application/json
res.type("html"); // text/html; charset=utf-8
res.type(".png"); // image/png
res.type("application/vnd.api+json");
7. Setting Cache-Control Headers
| Directive | Effect |
|---|---|
no-store | Never cache |
no-cache | Cache but revalidate every time |
private | Browser cache only (not CDN) |
public, max-age=N | Cache for N seconds anywhere |
s-maxage=N | CDN-only TTL |
immutable | Asset never changes (hashed filenames) |
stale-while-revalidate=N | Serve stale while refreshing |
Example: Asset vs API caching
// Hashed asset
res.set("Cache-Control", "public, max-age=31536000, immutable");
// API: no caching
res.set("Cache-Control", "no-store");
8. Setting Custom Headers
Example: Tracing
res.set({
"X-Request-Id": req.id,
"X-Response-Time": `${Date.now() - req.startTime}ms`,
"X-API-Version": "v2"
});
Note: Custom headers should be prefixed with
X- only by convention. Modern guidance (RFC 6648) discourages X- for new standardized headers but it's still common for app-specific.9. Using Location Header
Example: 201 with Location
app.post("/users", async (req, res) => {
const user = await db.users.create(req.body);
res.status(201).location(`/users/${user.id}`).json(user);
});
| Status | Location semantic |
|---|---|
| 201 Created | URL of new resource |
| 301/302/303/307/308 | Redirect target |
10. Setting Vary Header
Example: Content negotiation
res.vary("Accept-Encoding"); // gzip vs identity
res.vary("Accept-Language"); // i18n response varies by language
res.vary("Origin"); // CORS responses
| Header to Vary | When |
|---|---|
Accept | Different formats (HTML/JSON) |
Accept-Encoding | Compressed vs not |
Accept-Language | Localized content |
Origin | CORS |
Cookie | Per-user content |