2.12. HTTP Headers
Table of Contents
Understanding HTTP Headers
HTTP headers are small pieces of information that travel along with every HTTP request and response. They are like labels on a package that tell the server or browser how to handle the content, how to cache it, how to authenticate, and much more.
This chapter focuses on what headers are and how you, as a backend developer, use them. Other chapters explain HTTP requests, responses, status codes, cookies, sessions, and security in more depth. Here we focus on headers as a general concept and the most important examples.
What Is an HTTP Header?
Every HTTP message has three parts:
- Start line
- Request:
GET /path HTTP/1.1 - Response:
HTTP/1.1 200 OK - Headers
- Key-value pairs, one per line, like:
Content-Type: application/json - Optional body
- The actual data, like HTML, JSON, an image, etc.
Headers are simple text lines in the format:
Header-Name: value
For example, a complete raw HTTP request might look like:
GET /products?page=2 HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: text/html
Accept-Language: en-US
Cookie: session_id=abc123And a response:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 1024
Cache-Control: max-age=60
Set-Cookie: session_id=abc123; HttpOnly; Path=/
Server: my-backend/1.0
<html>...</html>Everything between the first line and the blank line is headers.
Rule: Every header line is Name: value and headers end at the first blank line. The body, if any, starts after that blank line.
Why Headers Matter for Backend Developers
As a backend developer you will:
- Read headers from requests
For example: - Identify the user agent or device
- Get authentication tokens
- Read custom application headers
- Inspect content type to parse the body correctly
- Set headers on responses
For example: - Set content type (HTML, JSON, image, etc.)
- Control caching behavior
- Set cookies
- Configure security rules
- Enable or restrict cross-origin requests
Even if your framework hides the raw HTTP, you still choose which headers to read and which to send.
Header Naming and Case Sensitivity
Header names are case-insensitive. These are all treated the same:
content-typeContent-TypeCONTENT-TYPE
In practice, you should follow the common style: Title-Case-With-Dashes.
Header values may be case-sensitive depending on the specific header. For example, Bearer in Authorization: Bearer token is usually case-sensitive for the scheme name.
Common Request Headers
Host
Identifies which domain name the client is trying to reach:
Host: example.comThis is important when multiple websites share the same IP address.
User-Agent
Describes the client software:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...You might use this to:
- Log client types
- Apply simple workarounds for specific clients
You should not rely on it for security, since it is easy to fake.
Accept
Tells the server what media types the client can understand:
Accept: text/html
Accept: application/json
Accept: text/html,application/xhtml+xml,application/xml;q=0.9In APIs, you often respond with JSON if:
Accept: application/jsonAccept-Language
Preferred human languages of the user:
Accept-Language: en-US,en;q=0.9,fr;q=0.8You might select error messages or UI language based on this.
Content-Type (on requests)
When a request has a body (POST, PUT, PATCH), Content-Type tells the server how to parse it:
Examples:
| Content-Type | Meaning | Typical Use |
|---|---|---|
application/json | JSON data | JSON API requests |
application/x-www-form-urlencoded | URL encoded form data | Classic HTML forms |
multipart/form-data | Multipart body with boundaries | Forms with file uploads |
text/plain | Plain text | Simple webhooks, debug requests |
Example POST with JSON:
POST /api/items HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 35
{"name": "Pen", "price": 3.5}As a backend developer, you must:
- Check
Content-Type - Choose the correct parser (JSON, form, etc.)
Content-Length
Number of bytes in the body:
Content-Length: 35In practice, your framework or server manages this for you.
Authorization
Carries credentials for authentication:
Authorization: Basic dXNlcjpwYXNz
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...You will handle this in authentication logic.
Cookie
The browser sends cookies back to the server in this header:
Cookie: session_id=abc123; theme=dark
You read cookies from this header. You set them in responses with Set-Cookie (explained later).
Common Response Headers
Content-Type (on responses)
Tells the client how to interpret the response body:
Content-Type: text/html; charset=utf-8
Content-Type: application/json; charset=utf-8
Content-Type: image/pngYour backend should always set this correctly. For an API returning JSON, you usually send:
Content-Type: application/json; charset=utf-8Content-Length
Size of the response body in bytes:
Content-Length: 2048Often handled automatically by your web server or framework.
Cache-Control
Controls caching by browsers and proxies:
Cache-Control: no-store
Cache-Control: no-cache
Cache-Control: max-age=60
Cache-Control: public, max-age=3600
Cache-Control: private, max-age=0, no-cacheSome common directives:
| Directive | Meaning |
|---|---|
max-age=60 | Response can be cached for 60 seconds |
no-cache | Must revalidate with server before reuse |
no-store | Must not store this response at all (good for sensitive data) |
public | Can be cached by any cache (browser, proxies, CDNs) |
private | Only the end user’s browser can cache it, not shared caches |
As a backend developer, you choose caching rules for:
- Static assets like images, CSS, JS (long cache)
- Dynamic or sensitive data like user profiles (short or no cache)
Location
Used mainly with redirects or newly created resources:
HTTP/1.1 302 Found
Location: https://example.com/login
HTTP/1.1 201 Created
Location: /api/items/123Set-Cookie
Instructs the browser to store a cookie:
Set-Cookie: session_id=abc123; HttpOnly; Path=/; Secure; SameSite=LaxImportant attributes:
| Attribute | Purpose |
|---|---|
HttpOnly | Not accessible from JavaScript |
Secure | Only sent over HTTPS |
SameSite | Controls cross-site cookie sending behavior |
Path | Limits which paths will send the cookie |
Domain | Limits which domains will send the cookie |
Expires / Max-Age | Controls cookie lifetime |
Set-Cookie is covered in more detail in the Cookies chapter. Here you just need to know it is a response header that creates or updates cookies.
Server
Identifies the software handling the request:
Server: nginx/1.25.0
Server: my-backend/1.0For security reasons, you should not expose too much detail.
Headers for Content Negotiation
Content negotiation is how the client and server agree on the best representation of a resource.
Common request headers:
AcceptAccept-LanguageAccept-Encoding(for compression, for examplegzip)
Common response headers:
Content-TypeContent-LanguageContent-Encoding
Example:
GET /article/42 HTTP/1.1
Host: example.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9
Accept-Language: fr-FR,fr;q=0.9,en;q=0.8
Accept-Encoding: gzip, deflate, brServer response:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Language: fr-FR
Content-Encoding: gzipThe server chose French HTML, and gzip compressed it.
Caching and Conditional Requests
Headers are heavily used for caching. A simple example:
HTTP/1.1 200 OK
ETag: "abc123"
Cache-Control: max-age=60
Last-Modified: Wed, 21 Aug 2024 10:00:00 GMTNext time the client requests this resource, it may send:
GET /resource HTTP/1.1
If-None-Match: "abc123"
If-Modified-Since: Wed, 21 Aug 2024 10:00:00 GMTIf the resource did not change, the server can respond:
HTTP/1.1 304 Not ModifiedNo body is needed. The client reuses its cached copy.
Key headers in this area:
ETagLast-ModifiedIf-None-MatchIf-Modified-Since
Handling these correctly can greatly reduce bandwidth and improve performance.
Security Related Headers
Some security controls are done with headers. They are discussed in detail in the Backend Security chapter, but here is a quick overview.
Examples:
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: no-referrerRough purposes:
| Header | Purpose |
|---|---|
Strict-Transport-Security | Force HTTPS in browsers |
Content-Security-Policy | Limit where scripts and resources can load |
X-Content-Type-Options | Prevent MIME type sniffing |
X-Frame-Options | Control if page can be shown in an iframe |
Referrer-Policy | Control Referer header details sent by browser |
As a backend developer, you usually configure these globally in your server or framework middleware.
CORS Related Headers
Cross-Origin Resource Sharing (CORS) uses headers to allow or block browser requests from other domains.
Server side example:
Access-Control-Allow-Origin: https://frontend.example.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: trueThese headers are explained deeply in the CORS section, but from a headers point of view:
- They are response headers
- They tell the browser if it can share the response with JavaScript running on another origin
Custom Headers
You can define your own headers for application specific needs. By convention, custom headers often start with X-, although modern practice is to just use a clear name.
Examples:
X-Request-ID: 9a8f7e2c
X-User-Id: 42
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1692619200
Request-ID: 9a8f7e2c
Correlation-ID: order-123Use cases:
- Trace a request across multiple services
- Send rate limiting information
- Pass internal metadata between services
Rule: Avoid putting sensitive data (like passwords or full tokens) into custom headers unless absolutely necessary, and always use HTTPS.
Examples in a Typical Backend Scenario
Example 1: JSON API with Authentication
Client request:
GET /api/me HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Server response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Cache-Control: no-store
X-Request-ID: d1c3e4
{"id": 1, "email": "user@example.com"}Key points:
- Client uses
Acceptfor JSON andAuthorizationfor credentials - Server sets
Content-Type, disables caching withCache-Control: no-store, and addsX-Request-IDfor logging
Example 2: HTML Page with Session Cookie
Client initial request (no cookie yet):
GET /login HTTP/1.1
Host: example.com
Accept: text/htmlServer response sets a cookie:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Set-Cookie: session_id=abc123; HttpOnly; Path=/; Secure; SameSite=Lax
<html>...</html>Next request from the browser:
GET /dashboard HTTP/1.1
Host: example.com
Accept: text/html
Cookie: session_id=abc123
The session mechanism depends on Set-Cookie and Cookie headers.
How Frameworks Expose Headers
In real code, your framework gives you simple ways to work with headers.
Reading Headers (Python / FastAPI example)
from fastapi import FastAPI, Request
app = FastAPI()
@app.get("/info")
async def info(request: Request):
user_agent = request.headers.get("user-agent")
accept = request.headers.get("accept")
return {"user_agent": user_agent, "accept": accept}Setting Headers
from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/hello")
def hello():
response = Response(
content='{"message": "Hello"}',
media_type="application/json", # sets Content-Type
)
response.headers["X-Request-ID"] = "123abc"
response.headers["Cache-Control"] = "no-store"
return responseEven though you do not type raw HTTP, understanding the underlying headers helps you configure and debug behavior correctly.
Summary
- HTTP headers are key-value pairs that travel with every request and response.
- You use request headers to know what the client wants and who they are.
- You use response headers to describe the content, control caching, set cookies, and apply security.
- Many important web features like cookies, caching, CORS, and security rely heavily on specific headers.
- Frameworks wrap headers in objects or dictionaries, but the underlying concept is always
Name: valuelines before the body.
In later chapters on cookies, sessions, security, and CORS, you will revisit many of these headers in more detail.
Views: 7
KAHIBARO