HTTP headers control critical aspects of web communication including security, caching, authentication, and content negotiation. Understanding and properly configuring headers is essential for secure and performant web applications.
Security Headers:
- Content-Security-Policy (CSP): Prevents XSS and injection attacks
- Controls which resources can be loaded (scripts, styles, images)
- Example: Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
- Directives: default-src, script-src, style-src, img-src, connect-src, etc.
- Report-only mode: Content-Security-Policy-Report-Only (testing)
- Strict-Transport-Security (HSTS): Enforces HTTPS
- Prevents protocol downgrade attacks
- Example: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
- max-age: Duration to enforce HTTPS (seconds)
- includeSubDomains: Apply to all subdomains
- preload: Submit to HSTS preload list
- X-Frame-Options: Prevents clickjacking
- Controls whether page can be embedded in iframe
- Values: DENY (no framing), SAMEORIGIN (same domain only), ALLOW-FROM uri
- Example: X-Frame-Options: DENY
- Modern alternative: CSP frame-ancestors directive
- X-Content-Type-Options: Prevents MIME sniffing
- Forces browser to respect declared Content-Type
- Example: X-Content-Type-Options: nosniff
- Prevents executing text/plain as JavaScript
- X-XSS-Protection: Legacy XSS filter (deprecated)
- Enabled built-in XSS protection in old browsers
- Example: X-XSS-Protection: 1; mode=block
- Deprecated: Use CSP instead
- Can cause vulnerabilities if misconfigured
- Referrer-Policy: Controls referrer information
- Protects user privacy
- Values: no-referrer, no-referrer-when-downgrade, origin, strict-origin, etc.
- Example: Referrer-Policy: strict-origin-when-cross-origin
- Permissions-Policy: Controls browser features
- Replaces Feature-Policy
- Example: Permissions-Policy: geolocation=(), microphone=(), camera=()
- Disables unnecessary browser features
Caching Headers:
- Cache-Control: Primary caching directive (HTTP/1.1)
- public: Can be cached by any cache (CDN, browser)
- private: Only browser cache, not CDN
- no-cache: Must revalidate before use
- no-store: Never cache (sensitive data)
- max-age=N: Cache for N seconds
- s-maxage=N: CDN cache duration (overrides max-age)
- Example: Cache-Control: public, max-age=3600, s-maxage=7200
- Expires: Absolute expiration time (HTTP/1.0, legacy)
- Example: Expires: Wed, 21 Oct 2025 07:28:00 GMT
- Superseded by Cache-Control max-age
- ETag: Resource version identifier
- Enables conditional requests (If-None-Match)
- Example: ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
- Server returns 304 Not Modified if ETag matches
- Last-Modified: Resource modification timestamp
- Enables conditional requests (If-Modified-Since)
- Example: Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT
- Less precise than ETag
- Vary: Vary cache by request headers
- Example: Vary: Accept-Encoding, User-Agent
- Creates separate cache entries per header combination
- Use cautiously (can fragment cache)
CORS Headers:
- Access-Control-Allow-Origin: Allowed origins
- Example: Access-Control-Allow-Origin: https://example.com
- Wildcard: * (public APIs, no credentials)
- Cannot use wildcard with credentials
- Access-Control-Allow-Methods: Allowed HTTP methods
- Example: Access-Control-Allow-Methods: GET, POST, PUT, DELETE
- Access-Control-Allow-Headers: Allowed request headers
- Example: Access-Control-Allow-Headers: Content-Type, Authorization
- Access-Control-Allow-Credentials: Allow cookies
- Example: Access-Control-Allow-Credentials: true
- Requires specific origin (not wildcard)
- Access-Control-Max-Age: Preflight cache duration
- Example: Access-Control-Max-Age: 86400
Other Important Headers:
- Content-Type: MIME type of response
- Example: Content-Type: text/html; charset=UTF-8
- Common types: text/html, application/json, image/png
- Content-Length: Response body size in bytes
- Content-Encoding: Compression (gzip, br, deflate)
- Server: Web server software (should hide version for security)
- Set-Cookie: Set cookies with attributes (Secure, HttpOnly, SameSite)
HTTP Status Codes:
- 2xx Success: 200 OK, 201 Created, 204 No Content
- 3xx Redirection: 301 Moved Permanently, 302 Found, 304 Not Modified
- 4xx Client Error: 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found
- 5xx Server Error: 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable
Security Best Practices:
- Implement CSP with restrictive default-src 'self'
- Enable HSTS with long max-age (1 year minimum)
- Set X-Frame-Options: DENY or use CSP frame-ancestors
- Enable X-Content-Type-Options: nosniff
- Remove or obscure Server header (hide version)
- Use Secure and HttpOnly flags on cookies
- Set SameSite=Strict or Lax on cookies
- Implement Referrer-Policy: strict-origin-when-cross-origin
Caching Best Practices:
- Use Cache-Control instead of Expires
- Set long max-age for static assets (1 year)
- Use versioned URLs or hashes for cache busting
- Set no-cache for HTML, cache assets
- Use ETag for conditional requests
- Leverage CDN with s-maxage
- Avoid no-store unless necessary (sensitive data)
Tools for Checking Headers:
- Browser DevTools: Network tab > Headers
- curl: curl -I https://example.com
- SecurityHeaders.com: Online security header scanner
- Mozilla Observatory: Comprehensive security audit
Common Mistakes:
- Using Access-Control-Allow-Origin: * with credentials
- Forgetting to set HttpOnly on session cookies
- Overly permissive CSP (unsafe-inline, unsafe-eval)
- Not setting HSTS on HTTPS sites
- Caching sensitive data (use Cache-Control: no-store)
- Exposing server version in Server header