# Important HTTP Response Headers Every Developer Should Know
Source: Dev.to
Why HTTP Headers Matter for Backend Developers
HTTP headers are metadata sent with every server response. They tell browsers how to:
- Cache resources – improve performance.
- Enforce security policies – protect your app.
- Handle content – shape the user experience.
Mis‑configured headers can lead to vulnerabilities, slow load times, or broken functionality. Let’s fix that.
1. Content-Type & Content-Disposition
Purpose – Tells the browser what type of data you’re sending and how to handle it.
| Directive | Description |
|---|---|
Content-Type | MIME type (e.g., application/json, text/html, application/pdf). |
Content-Disposition | inline (display in browser) or attachment (force download). |
Example (raw TCP server)
import { open } from "node:fs/promises";
import net from "node:net";
const server = net.createServer(async (socket) => {
const fileHandle = await open("report.pdf");
const { size } = await fileHandle.stat();
const readStream = fileHandle.createReadStream();
socket.write("HTTP/1.1 200 OK\r\n");
socket.write("Content-Type: application/pdf\r\n");
socket.write(`Content-Length: ${size}\r\n`);
socket.write('Content-Disposition: attachment; filename="report.pdf"\r\n');
socket.write("\r\n");
readStream.pipe(socket);
});
server.listen(8080);
Why it matters – Without Content-Type, browsers may misinterpret the payload. Without Content-Disposition, PDFs might open in‑browser when you intend a download.
2. Cache-Control
Purpose – Controls how and for how long browsers cache your responses.
| Directive | Effect |
|---|---|
no-store | Never cache (useful for sensitive data). |
no-cache | Cache but re‑validate on every request. |
max-age=3600 | Cache for 1 hour. |
public / private | Shared caches vs. user‑specific caches. |
Express.js Example
import express from "express";
const app = express();
app.get("/api/profile", (req, res) => {
res.set("Cache-Control", "private, no-cache");
res.json({ user: "John Doe" });
});
app.get("/static/logo.png", (req, res) => {
// Cache for 1 year
res.set("Cache-Control", "public, max-age=31536000");
res.sendFile("./logo.png");
});
app.listen(3000);
Impact – Proper caching can reduce server load by 60‑80 % and dramatically improve page‑load speed.
3. Content-Security-Policy (CSP)
Purpose – Mitigates XSS attacks by restricting where resources can be loaded from.
Common Directives
default-src 'self' // Only load from your own origin
script-src 'self' https://cdn.example.com
img-src *
Implementation (Express middleware)
app.use((req, res, next) => {
res.set(
"Content-Security-Policy",
"default-src 'self'; script-src 'self' https://trusted-cdn.com; img-src *"
);
next();
});
Security benefit – Blocks ~90 % of XSS attacks by preventing inline scripts and unauthorized resource loading.
4. Strict-Transport-Security (HSTS)
Purpose – Forces browsers to always use HTTPS, protecting against man‑in‑the‑middle attacks.
Example
app.use((req, res, next) => {
res.set(
"Strict-Transport-Security",
"max-age=31536000; includeSubDomains"
);
next();
});
max-age=31536000→ enforce HTTPS for 1 year.includeSubDomains→ apply to all subdomains.
Critical note – Once set, browsers will refuse plain‑HTTP connections to your domain for the specified duration.
5. X-Content-Type-Options
Purpose – Stops browsers from MIME‑type sniffing, which can lead to execution of malicious content.
Usage
app.use((req, res, next) => {
res.set("X-Content-Type-Options", "nosniff");
next();
});
Why it’s essential – Prevents a .txt file that contains JavaScript‑like content from being executed as a script.
6. CORS Headers (Cross‑Origin Resource Sharing)
Purpose – Controls which external origins may access your API.
Example
app.use((req, res, next) => {
res.set("Access-Control-Allow-Origin", "https://myapp.com");
res.set("Access-Control-Allow-Methods", "GET, POST, PUT");
res.set(
"Access-Control-Allow-Headers",
"Content-Type, Authorization"
);
next();
});
Real‑world scenario – Your React frontend (myapp.com) calls a Node.js API (api.myapp.com). Without these headers the browser blocks the request.
7. Set-Cookie (with security attributes)
Purpose – Sends session cookies securely.
Example
app.post("/login", (req, res) => {
res.cookie("sessionId", "abc123", {
httpOnly: true, // Prevents JavaScript access (XSS protection)
secure: true, // Sent only over HTTPS
sameSite: "strict", // CSRF protection
maxAge: 3600000 // 1 hour
});
res.json({ success: true });
});
Security Impact
| Attribute | Effect |
|---|---|
httpOnly | Blocks client‑side script access to the cookie. |
secure | Cookie is transmitted only over HTTPS. |
sameSite | Mitigates CSRF attacks (strict or lax). |
maxAge | Controls cookie lifetime. |
Practical Checklist for Production
Before you ship, verify that your Node.js app sets the following headers (or their appropriate equivalents):
- ✅
Content-Type– always present and accurate. - ✅
Content-Disposition– used where download behavior is required. - ✅
Cache-Control– tuned per endpoint (public vs. private, max‑age, no‑store). - ✅
Content-Security-Policy– defined with a whitelist‑only approach. - ✅
Strict-Transport-Security– enabled on HTTPS‑only services. - ✅
X-Content-Type-Options: nosniff. - ✅ CORS headers (
Access-Control-Allow-*) – only on routes that need cross‑origin access. - ✅ Secure
Set-Cookieattributes (httpOnly,secure,sameSite, appropriatemaxAge). - ✅
Referrer-Policy– e.g.,no-referrer-when-downgradeor stricter, to control referrer leakage. - ✅
Feature-Policy/Permissions-Policy– restrict use of powerful browser features (e.g.,geolocation,camera). - ✅
X-Frame-Options: DENYorSAMEORIGIN– prevent click‑jacking.
Tip: Automate header checks with integration tests or use a middleware library like helmet (
npm i helmet) to apply many of these defaults with a single line:
import helmet from "helmet";
app.use(helmet());
TL;DR
- Headers are not optional – they’re a core part of a production‑grade API.
- Configure them once, test them often – a small mis‑step can expose you to serious risks.
- Leverage existing middleware (Helmet, cors, compression) to avoid reinventing the wheel.
Now go ahead and make your Node.js services secure, performant, and professional!
✅ Recommended HTTP Headers
Cache-Control– Set based on content typeContent-Security-Policy– Block XSS attacksStrict-Transport-Security– Enforce HTTPSX-Content-Type-Options: nosniff– Prevent MIME‑type sniffing- CORS headers – Enable safe communication with the frontend
- Secure cookie attributes – Protect session cookies (e.g.,
HttpOnly,Secure,SameSite)
Conclusion
HTTP headers are your first line of defense and a key lever for performance optimization. The examples shown—especially the low‑level net module approach—demonstrate that headers are just strings you control. Whether you’re working with raw TCP sockets or a framework like Express.js, understanding these headers makes you a more security‑conscious and performance‑aware developer.
- Audit your current application’s headers using the browser’s DevTools (Network tab).
- Add any missing security headers today—your users’ data depends on it.
Next Steps
- Test your headers at
- Aim for an A+ rating