Browser & Network
HTTP Protocol
HTTP/1.1, HTTP/2, HTTP/3, headers, caching, and modern web protocols
HTTP Protocol
HTTP (Hypertext Transfer Protocol) is the foundation of data communication on the web. Understanding HTTP is crucial for optimizing performance and debugging issues.
HTTP Versions
HTTP/1.1
HTTP/1.1 Characteristics:
├── Text-based protocol
├── One request per TCP connection (persistent with keep-alive)
├── Head-of-line blocking
├── No header compression
└── Domain sharding workaround (6 connections per origin)HTTP/2
HTTP/2 Improvements:
├── Binary protocol
├── Multiplexing (multiple requests on single connection)
├── Header compression (HPACK)
├── Server push (proactive resource delivery)
├── Stream prioritization
└── Single TCP connection per originHTTP/3 (QUIC)
HTTP/3 Improvements:
├── UDP-based (QUIC protocol)
├── No TCP head-of-line blocking
├── Faster connection establishment (0-RTT)
├── Connection migration (IP change tolerance)
├── Built-in encryption (TLS 1.3)
└── Better mobile performanceHTTP Methods
| Method | Idempotent | Safe | Cacheable | Body |
|---|---|---|---|---|
| GET | Yes | Yes | Yes | No |
| HEAD | Yes | Yes | Yes | No |
| POST | No | No | Conditional | Yes |
| PUT | Yes | No | No | Yes |
| PATCH | No | No | No | Yes |
| DELETE | Yes | No | No | Optional |
| OPTIONS | Yes | Yes | No | No |
RESTful Usage
// Resource-based URLs
GET /api/users // List users
GET /api/users/123 // Get user 123
POST /api/users // Create user
PUT /api/users/123 // Replace user 123
PATCH /api/users/123 // Update user 123
DELETE /api/users/123 // Delete user 123
// Query parameters for filtering
GET /api/users?role=admin&status=active&page=1&limit=20HTTP Status Codes
Common Status Codes
| Code | Name | Description |
|---|---|---|
| 2xx Success | ||
| 200 | OK | Request succeeded |
| 201 | Created | Resource created |
| 204 | No Content | Success, no body |
| 3xx Redirection | ||
| 301 | Moved Permanently | Permanent redirect |
| 302 | Found | Temporary redirect |
| 304 | Not Modified | Use cached version |
| 4xx Client Error | ||
| 400 | Bad Request | Invalid request |
| 401 | Unauthorized | Authentication required |
| 403 | Forbidden | Access denied |
| 404 | Not Found | Resource not found |
| 409 | Conflict | State conflict |
| 422 | Unprocessable Entity | Validation failed |
| 429 | Too Many Requests | Rate limited |
| 5xx Server Error | ||
| 500 | Internal Server Error | Server error |
| 502 | Bad Gateway | Invalid upstream |
| 503 | Service Unavailable | Server overloaded |
| 504 | Gateway Timeout | Upstream timeout |
HTTP Headers
Request Headers
GET /api/users HTTP/1.1
Host: api.example.com
Accept: application/json
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json
User-Agent: Mozilla/5.0...
Cookie: session=abc123
If-None-Match: "etag-value"
If-Modified-Since: Wed, 21 Oct 2023 07:28:00 GMTResponse Headers
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 1234
Content-Encoding: gzip
Cache-Control: public, max-age=3600
ETag: "abc123"
Last-Modified: Wed, 21 Oct 2023 07:28:00 GMT
Set-Cookie: session=xyz789; HttpOnly; Secure; SameSite=Strict
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Strict-Transport-Security: max-age=31536000; includeSubDomainsCaching
Cache-Control Directives
# Client can cache for 1 hour
Cache-Control: public, max-age=3600
# Private cache only (browser, not CDN)
Cache-Control: private, max-age=3600
# Revalidate before using cached version
Cache-Control: no-cache
# Don't store at all
Cache-Control: no-store
# Immutable (never revalidate)
Cache-Control: public, max-age=31536000, immutable
# Stale while revalidate
Cache-Control: max-age=3600, stale-while-revalidate=86400ETag Validation
# First request
GET /api/data
→ 200 OK
→ ETag: "abc123"
# Subsequent request
GET /api/data
If-None-Match: "abc123"
→ 304 Not Modified (if unchanged)
→ 200 OK + new ETag (if changed)Caching Strategy by Resource Type
| Resource | Strategy |
|---|---|
| HTML | no-cache or short max-age |
| JS/CSS with hash | immutable, max-age=31536000 |
| Images with hash | immutable, max-age=31536000 |
| API responses | no-store or short max-age |
| User-specific data | private, no-store |
CORS
Simple Requests
// Simple request (no preflight)
fetch('https://api.example.com/data', {
method: 'GET',
headers: {
'Accept': 'application/json',
},
});
// Server response
// Access-Control-Allow-Origin: https://myapp.comPreflight Requests
// Non-simple request triggers preflight
fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Custom-Header': 'value',
},
body: JSON.stringify(data),
});
// Preflight request (automatically sent by browser)
// OPTIONS /data
// Origin: https://myapp.com
// Access-Control-Request-Method: POST
// Access-Control-Request-Headers: content-type, x-custom-header
// Preflight response
// Access-Control-Allow-Origin: https://myapp.com
// Access-Control-Allow-Methods: GET, POST, PUT, DELETE
// Access-Control-Allow-Headers: content-type, x-custom-header
// Access-Control-Max-Age: 86400CORS Server Configuration
// Express.js
app.use(cors({
origin: ['https://myapp.com', 'https://staging.myapp.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
maxAge: 86400,
}));Fetch API
Basic Usage
// GET request
const response = await fetch('/api/users');
const users = await response.json();
// POST request
const response = await fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'John', email: 'john@example.com' }),
});
// With error handling
async function fetchData(url: string) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
}Advanced Options
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify(data),
credentials: 'include', // Send cookies cross-origin
mode: 'cors', // CORS mode
cache: 'no-cache', // Cache mode
redirect: 'follow', // Follow redirects
signal: controller.signal, // AbortController signal
keepalive: true, // Keep connection for sendBeacon-like
});
// Timeout with AbortController
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
try {
const response = await fetch(url, { signal: controller.signal });
clearTimeout(timeoutId);
return response.json();
} catch (error) {
if (error.name === 'AbortError') {
console.log('Request timed out');
}
throw error;
}WebSocket
// WebSocket connection
const ws = new WebSocket('wss://api.example.com/ws');
ws.onopen = () => {
console.log('Connected');
ws.send(JSON.stringify({ type: 'subscribe', channel: 'updates' }));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Received:', data);
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
ws.onclose = (event) => {
console.log('Disconnected:', event.code, event.reason);
// Implement reconnection logic
};
// Send data
ws.send(JSON.stringify({ type: 'message', content: 'Hello' }));
// Close connection
ws.close(1000, 'Normal closure');Server-Sent Events
// Server-Sent Events for one-way streaming
const eventSource = new EventSource('/api/events');
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Event:', data);
};
eventSource.addEventListener('notification', (event) => {
console.log('Notification:', event.data);
});
eventSource.onerror = () => {
console.error('SSE error');
// EventSource automatically reconnects
};
// Close connection
eventSource.close();Best Practices
HTTP Best Practices
- Use HTTP/2 or HTTP/3 when possible
- Implement proper caching strategies
- Use compression (gzip/brotli)
- Set appropriate CORS headers
- Use HTTPS everywhere
- Implement request timeouts
- Handle errors gracefully
- Use ETags for cache validation