HTTP/HTTPS & Web Communication

0/4 in this phase0/45 across the roadmap

📖 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:

  1. Client sends supported cipher suites
  2. Server responds with chosen cipher + SSL certificate
  3. Client verifies certificate with Certificate Authority (CA)
  4. Both sides derive session keys
  5. 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

codeTap to expand ⛶
1// ============================================
2// HTTP Communication — Essential Patterns
3// ============================================
4
5// ---------- HTTP Methods & Idempotency ----------
6
7// ❌ 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 */ });
10
11// ✅ GOOD: RESTful HTTP methods
12app.get('/api/users', async (req, res) => {
13 // GET is idempotent and cacheable
14 const users = await db.query('SELECT * FROM users LIMIT 100');
15 res.set('Cache-Control', 'public, max-age=60'); // Cache for 60 seconds
16 res.json({ users });
17});
18
19app.post('/api/users', async (req, res) => {
20 // POST creates a new resource — NOT idempotent
21 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 = Created
26});
27
28app.put('/api/users/:id', async (req, res) => {
29 // PUT replaces the entire resource — IS idempotent
30 // Calling PUT twice with the same data = same result
31 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});
37
38app.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 Content
42});
43
44// ---------- HTTP Status Codes in Practice ----------
45
46// Rate limiting with 429
47const rateLimit = new Map();
48
49function rateLimitMiddleware(req, res, next) {
50 const clientIP = req.ip;
51 const now = Date.now();
52
53 if (!rateLimit.has(clientIP)) {
54 rateLimit.set(clientIP, { count: 1, windowStart: now });
55 return next();
56 }
57
58 const entry = rateLimit.get(clientIP);
59 const windowMs = 60000; // 1-minute window
60 const maxRequests = 100;
61
62 if (now - entry.windowStart > windowMs) {
63 // Window expired, reset
64 rateLimit.set(clientIP, { count: 1, windowStart: now });
65 return next();
66 }
67
68 if (entry.count >= maxRequests) {
69 // ✅ Use 429 with Retry-After header
70 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 }
79
80 entry.count++;
81 next();
82}
83
84// ---------- HTTP/2 Multiplexing Concept ----------
85
86// HTTP/1.1: Browser opens 6 parallel connections to same domain
87// Each connection handles ONE request at a time
88// └── Connection 1: GET /style.css ──────────────> response
89// └── Connection 2: GET /app.js ────────────────> response
90// └── Connection 3: GET /image1.jpg ────────────> response
91// └── Connection 4: GET /image2.jpg ────────────> response
92// └── Connection 5: waiting... (only 6 allowed!)
93// └── Connection 6: waiting...
94
95// HTTP/2: Browser opens ONE connection
96// Multiple requests/responses interleaved on the same connection
97// └── 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!
104
105// ---------- Caching Headers ----------
106
107function serveCacheableResource(req, res) {
108 // ✅ Proper cache headers for static assets
109 res.set({
110 'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
111 'ETag': 'W/"abc123"', // Weak ETag
112 'Last-Modified': 'Tue, 15 Jan 2024 10:30:00 GMT',
113 'Vary': 'Accept-Encoding', // Cache varies by compression
114 });
115 res.sendFile('/static/bundle.hash123.js');
116}
117
118function serveAPIResponse(req, res) {
119 // ✅ API responses: short cache, must revalidate
120 res.set({
121 'Cache-Control': 'private, max-age=0, must-revalidate',
122 'ETag': `W/"\${computeHash(data)}"`,
123 });
124 res.json(data);
125}
126
127console.log("HTTP examples configured correctly!");

🏋️ Practice Exercise

  1. 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.

  2. 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.

  3. HTTP/2 Benefits: List 5 specific ways HTTP/2 improves performance over HTTP/1.1. For each, explain the underlying mechanism.

  4. 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.

  5. 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