HTTP/HTTPS & Web Communication
📖 Concept
HTTP (HyperText Transfer Protocol) is the foundation of web communication. Every API call, webpage load, and REST request uses HTTP. Understanding its versions, methods, status codes, and headers is essential for system design.
HTTP Versions
| Version | Year | Key Feature | Connection Model |
|---|---|---|---|
| HTTP/1.0 | 1996 | Basic request-response | New connection per request |
| HTTP/1.1 | 1997 | Keep-alive, pipelining | Persistent connections |
| HTTP/2 | 2015 | Multiplexing, server push, header compression | Single connection, multiple streams |
| HTTP/3 | 2022 | QUIC (UDP-based), 0-RTT | No head-of-line blocking |
HTTP Methods
| Method | Purpose | Idempotent? | Safe? |
|---|---|---|---|
| GET | Read a resource | ✅ Yes | ✅ Yes |
| POST | Create a resource | ❌ No | ❌ No |
| PUT | Replace a resource entirely | ✅ Yes | ❌ No |
| PATCH | Partially update a resource | ❌ No | ❌ No |
| DELETE | Remove a resource | ✅ Yes | ❌ No |
Idempotent means making the same request multiple times produces the same result. This matters for retries — you can safely retry a GET or PUT, but retrying a POST might create duplicates.
Important Status Codes
| Code | Meaning | System Design Context |
|---|---|---|
| 200 | OK | Successful read/update |
| 201 | Created | Successful resource creation |
| 301 | Moved Permanently | URL redirection (cached by browsers) |
| 302 | Found (Temporary Redirect) | URL shortener redirects |
| 304 | Not Modified | Client cache is still valid |
| 400 | Bad Request | Malformed client input |
| 401 | Unauthorized | Missing/invalid authentication |
| 403 | Forbidden | Valid auth but no permission |
| 404 | Not Found | Resource doesn't exist |
| 429 | Too Many Requests | Rate limiting triggered |
| 500 | Internal Server Error | Server-side bug |
| 502 | Bad Gateway | Upstream server unreachable |
| 503 | Service Unavailable | Server overloaded or in maintenance |
| 504 | Gateway Timeout | Upstream server took too long |
HTTPS & TLS
HTTPS = HTTP + TLS encryption. The TLS handshake:
- Client sends supported cipher suites
- Server responds with chosen cipher + SSL certificate
- Client verifies certificate with Certificate Authority (CA)
- Both sides derive session keys
- All subsequent data is encrypted
System design impact: TLS adds 1-2 RTT to connection establishment. Use TLS 1.3 (1 RTT) or session resumption (0 RTT) to minimize latency. Always use HTTPS — there's no valid reason not to in production.
💻 Code Example
1// ============================================2// HTTP Communication — Essential Patterns3// ============================================45// ---------- HTTP Methods & Idempotency ----------67// ❌ BAD: Using POST for everything (not idempotent, can't cache)8app.post('/get-users', (req, res) => { /* wrong method for reads */ });9app.post('/delete-user', (req, res) => { /* should use DELETE */ });1011// ✅ GOOD: RESTful HTTP methods12app.get('/api/users', async (req, res) => {13 // GET is idempotent and cacheable14 const users = await db.query('SELECT * FROM users LIMIT 100');15 res.set('Cache-Control', 'public, max-age=60'); // Cache for 60 seconds16 res.json({ users });17});1819app.post('/api/users', async (req, res) => {20 // POST creates a new resource — NOT idempotent21 const user = await db.query(22 'INSERT INTO users (name, email) VALUES (?, ?)',23 [req.body.name, req.body.email]24 );25 res.status(201).json({ user }); // 201 = Created26});2728app.put('/api/users/:id', async (req, res) => {29 // PUT replaces the entire resource — IS idempotent30 // Calling PUT twice with the same data = same result31 await db.query(32 'UPDATE users SET name = ?, email = ? WHERE id = ?',33 [req.body.name, req.body.email, req.params.id]34 );35 res.json({ updated: true });36});3738app.delete('/api/users/:id', async (req, res) => {39 // DELETE is idempotent — deleting twice = same state (resource gone)40 await db.query('DELETE FROM users WHERE id = ?', [req.params.id]);41 res.status(204).end(); // 204 = No Content42});4344// ---------- HTTP Status Codes in Practice ----------4546// Rate limiting with 42947const rateLimit = new Map();4849function rateLimitMiddleware(req, res, next) {50 const clientIP = req.ip;51 const now = Date.now();5253 if (!rateLimit.has(clientIP)) {54 rateLimit.set(clientIP, { count: 1, windowStart: now });55 return next();56 }5758 const entry = rateLimit.get(clientIP);59 const windowMs = 60000; // 1-minute window60 const maxRequests = 100;6162 if (now - entry.windowStart > windowMs) {63 // Window expired, reset64 rateLimit.set(clientIP, { count: 1, windowStart: now });65 return next();66 }6768 if (entry.count >= maxRequests) {69 // ✅ Use 429 with Retry-After header70 const retryAfter = Math.ceil((entry.windowStart + windowMs - now) / 1000);71 res.set('Retry-After', retryAfter.toString());72 res.set('X-RateLimit-Limit', maxRequests.toString());73 res.set('X-RateLimit-Remaining', '0');74 return res.status(429).json({75 error: 'Too Many Requests',76 retryAfter,77 });78 }7980 entry.count++;81 next();82}8384// ---------- HTTP/2 Multiplexing Concept ----------8586// HTTP/1.1: Browser opens 6 parallel connections to same domain87// Each connection handles ONE request at a time88// └── Connection 1: GET /style.css ──────────────> response89// └── Connection 2: GET /app.js ────────────────> response90// └── Connection 3: GET /image1.jpg ────────────> response91// └── Connection 4: GET /image2.jpg ────────────> response92// └── Connection 5: waiting... (only 6 allowed!)93// └── Connection 6: waiting...9495// HTTP/2: Browser opens ONE connection96// Multiple requests/responses interleaved on the same connection97// └── Single Connection:98// Stream 1: GET /style.css ──> response (interleaved)99// Stream 2: GET /app.js ────> response (interleaved)100// Stream 3: GET /image1.jpg > response (interleaved)101// Stream 4: GET /image2.jpg > response (interleaved)102// Stream 5: GET /api/data ──> response (interleaved)103// ... unlimited streams!104105// ---------- Caching Headers ----------106107function serveCacheableResource(req, res) {108 // ✅ Proper cache headers for static assets109 res.set({110 'Cache-Control': 'public, max-age=31536000, immutable', // 1 year111 'ETag': 'W/"abc123"', // Weak ETag112 'Last-Modified': 'Tue, 15 Jan 2024 10:30:00 GMT',113 'Vary': 'Accept-Encoding', // Cache varies by compression114 });115 res.sendFile('/static/bundle.hash123.js');116}117118function serveAPIResponse(req, res) {119 // ✅ API responses: short cache, must revalidate120 res.set({121 'Cache-Control': 'private, max-age=0, must-revalidate',122 'ETag': `W/"\${computeHash(data)}"`,123 });124 res.json(data);125}126127console.log("HTTP examples configured correctly!");
🏋️ Practice Exercise
Status Code Quiz: For each scenario, provide the correct HTTP status code: (a) User not logged in, (b) User logged in but doesn't own the resource, (c) Request body is missing required fields, (d) Server is overloaded, (e) API version has been removed.
Caching Strategy: Design the cache-control headers for: (a) a static JS bundle with a hash in the filename, (b) a user profile API response, (c) a public blog post page, (d) an admin dashboard.
HTTP/2 Benefits: List 5 specific ways HTTP/2 improves performance over HTTP/1.1. For each, explain the underlying mechanism.
Retry Logic: Design a retry strategy for an API client that handles: (a) 429 with Retry-After header, (b) 500 errors, (c) 503 errors, (d) network timeouts. Include exponential backoff with jitter.
HTTPS Overhead: Calculate the additional latency of HTTPS over HTTP for a client with 100ms RTT to the server, comparing TLS 1.2 (2 RTT handshake) vs TLS 1.3 (1 RTT handshake). How much does session resumption save?
⚠️ Common Mistakes
Using POST for read operations — POST requests can't be cached by browsers or CDNs, and aren't idempotent. Use GET for reads to take advantage of HTTP caching.
Returning 200 with an error body instead of proper status codes — '{ status: 200, error: true, message: "Not Found" }' prevents clients, load balancers, and monitoring tools from understanding the response correctly.
Not setting proper Cache-Control headers — without cache headers, browsers and CDNs use heuristic caching which can serve stale data unexpectedly. Always set explicit cache directives.
Ignoring idempotency in retry logic — retrying a failed POST /charge-payment could charge the user twice. Use idempotency keys (unique request IDs) to make non-idempotent operations safe to retry.
💼 Interview Questions
🎤 Mock Interview
Practice a live interview for HTTP/HTTPS & Web Communication