Networking Interview Prep
Application Protocols

HTTP

How the Web Talks

LinkedIn Hook

You open your browser, type a URL, hit Enter. 247 milliseconds later, a webpage loads.

What just happened?

Your browser sent a tiny text message to a server somewhere in the world. The server read it, processed it, and sent back an answer. That's HTTP — and it runs every website on the internet.

But most developers don't know:

  • Why POST is NOT the right method for updates
  • The real difference between 401 and 403
  • How HTTP/2 went from "text" to "binary" and why that matters
  • Why HTTP is called "stateless" yet somehow remembers your login

Lesson 5.1 of my Networking Interview Prep series covers all of it — with raw HTTP examples, code snippets, and a cheat sheet you can screenshot.

Read the full lesson → [link]

#HTTP #WebDevelopment #NetworkingFundamentals #InterviewPrep #SoftwareEngineering #BackendDevelopment


HTTP thumbnail


What You'll Learn

  • The restaurant analogy that makes HTTP instantly understandable
  • How the HTTP request/response model works end to end
  • Every HTTP method — GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS — and when to use each
  • Status codes across all five categories (1xx through 5xx) with the ones that actually appear in interviews
  • The most important HTTP headers and what they do
  • Why HTTP is stateless and how cookies/sessions patch that gap
  • The evolution from HTTP/1.1 to HTTP/2 to HTTP/3 — binary framing, multiplexing, QUIC
  • What idempotency means and why it matters for API design
  • How to read and write raw HTTP requests and responses

The Restaurant Analogy

Before touching any technical detail, picture a restaurant.

You are the customer (the browser). The waiter is HTTP — the protocol that carries your order to the kitchen and brings back the food. The kitchen is the server — it does the actual work and produces the response.

You do not walk into the kitchen yourself. You do not know how the kitchen is organized. You place an order using a standard format the waiter understands, and you receive food in a standard format back.

That is HTTP in one paragraph.

Each order is independent. The waiter does not remember your previous orders from last week. If you want your usual dish, you have to say it every time. This is what "stateless" means, and we will come back to it.


The Request/Response Model

HTTP is a client-server protocol. Every HTTP interaction follows the same pattern:

  1. The client opens a TCP connection to the server (port 80 for HTTP, 443 for HTTPS).
  2. The client sends an HTTP request.
  3. The server processes it and sends back an HTTP response.
  4. The connection is closed (or kept alive for reuse in HTTP/1.1+).

Everything on the web — loading a page, submitting a form, fetching JSON from an API — follows this cycle.

A Raw HTTP Request

This is what your browser actually sends over the wire. No magic, just text:

GET /api/users/42 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Cache-Control: no-cache
Connection: keep-alive

Line by line:

  • GET — the HTTP method (what action to take)
  • /api/users/42 — the path (what resource to act on)
  • HTTP/1.1 — the protocol version
  • Everything below — headers (key-value metadata)
  • GET requests have no body; POST/PUT/PATCH requests do

A Raw HTTP Response

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 87
Cache-Control: max-age=3600
Set-Cookie: session_id=abc123; HttpOnly; Secure
X-Request-ID: req-7f3a2b1c

{
  "id": 42,
  "name": "Rakibul Hasan",
  "email": "mail.liilab@gmail.com"
}

Line by line:

  • HTTP/1.1 — protocol version
  • 200 OK — status line (code + reason phrase)
  • Headers follow (Content-Type, Cache-Control, etc.)
  • A blank line separates headers from the body
  • The body is the actual payload (JSON here)

HTTP Methods In Depth

HTTP methods describe the intent of the request. The server decides how to handle them, but there is a widely followed convention.

MethodPurposeIdempotentHas Body
GETFetch a resourceYesNo
POSTCreate a resourceNoYes
PUTReplace a resource fullyYesYes
PATCHUpdate a resource partiallyNo*Yes
DELETERemove a resourceYesOptional
HEADLike GET but no response bodyYesNo
OPTIONSAsk what methods are allowedYesNo

*PATCH can be designed to be idempotent, but it is not required to be by the spec.

GET — Fetch, Never Modify

// GET: retrieve user profile
// Safe to call multiple times — same result every time
fetch("https://api.example.com/users/42", {
  method: "GET",
  headers: {
    "Accept": "application/json",
    "Authorization": "Bearer <token>"
  }
})
.then(res => res.json())
.then(user => console.log(user));
// No body allowed in GET requests

POST — Create, Not Idempotent

// POST: create a new user
// Calling this twice creates TWO users — not idempotent
fetch("https://api.example.com/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",  // tells server what format we're sending
    "Authorization": "Bearer <token>"
  },
  body: JSON.stringify({
    name: "Rakibul Hasan",
    email: "mail.liilab@gmail.com"
  })
})
.then(res => {
  // Correct response for resource creation is 201 Created
  if (res.status === 201) {
    return res.json();
  }
});

PUT vs PATCH — Full Replace vs Partial Update

// PUT: send the ENTIRE object — fields you omit get cleared/defaulted
// Calling PUT with the same body multiple times = same result (idempotent)
fetch("https://api.example.com/users/42", {
  method: "PUT",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    name: "Rakibul Hasan",        // required
    email: "mail.liilab@gmail.com", // required
    role: "admin"                 // required — omitting this would remove the role
  })
});

// PATCH: send only what changed — other fields are untouched
fetch("https://api.example.com/users/42", {
  method: "PATCH",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    role: "admin"   // only updating the role — name and email stay as-is
  })
});

HEAD and OPTIONS

HEAD /api/users/42 HTTP/1.1
Host: api.example.com

HEAD returns headers only — no body. Useful for checking if a resource exists, or getting its Content-Length before downloading.

OPTIONS /api/users HTTP/1.1
Host: api.example.com
Origin: https://myfrontend.com
Access-Control-Request-Method: POST

OPTIONS is the preflight request that browsers send before cross-origin (CORS) requests. The server responds with what methods and origins it allows.


Idempotency — Why It Matters

An operation is idempotent if performing it multiple times produces the same result as doing it once.

Think of a light switch (idempotent): pressing "turn off" five times leaves the light off — same as pressing it once. Now think of an ATM withdrawal (not idempotent): withdrawing $100 five times takes $500.

// Idempotent example: DELETE
// Deleting a user that doesn't exist anymore should return 404 or 204,
// NOT crash — the end state (user is gone) is the same either way

async function deleteUser(id) {
  const res = await fetch(`https://api.example.com/users/${id}`, {
    method: "DELETE"
  });

  // 204 No Content — deleted successfully
  // 404 Not Found   — already gone, which is fine
  // Both are acceptable outcomes for an idempotent DELETE
  if (res.status === 204 || res.status === 404) {
    console.log("User is gone — operation succeeded");
  }
}

// Calling deleteUser(42) ten times is safe
// The user ends up deleted regardless — no side effects accumulate

Why does idempotency matter? In distributed systems, networks fail. Clients retry. If your API is idempotent, retries are safe. If it is not (like POST create), retries create duplicates.


HTTP Status Codes

Status codes tell the client what happened. There are five categories.

1xx — Informational

Rarely seen in application code. 100 Continue tells the client to keep sending a large request body.

2xx — Success

CodeNameMeaning
200OKStandard success — body contains the result
201CreatedResource was created — usually after POST
204No ContentSuccess but nothing to return — common for DELETE/PATCH

3xx — Redirect

CodeNameMeaning
301Moved PermanentlyResource is at a new URL forever — search engines update
302FoundTemporary redirect — original URL may come back
304Not ModifiedCached version is still fresh — do not re-download

4xx — Client Error (your fault)

CodeNameMeaning
400Bad RequestMalformed request — invalid JSON, missing required field
401UnauthorizedNot authenticated — no token, or token expired
403ForbiddenAuthenticated but not allowed — you are not an admin
404Not FoundResource does not exist at this path
405Method Not AllowedYou used GET on an endpoint that only accepts POST
429Too Many RequestsRate limit hit — slow down

5xx — Server Error (their fault)

CodeNameMeaning
500Internal Server ErrorGeneric server crash — something unexpected happened
502Bad GatewayThe gateway received an invalid response from an upstream server
503Service UnavailableServer is overloaded or down for maintenance
504Gateway TimeoutThe upstream server did not respond in time

Important HTTP Headers

Headers are metadata attached to requests and responses. These are the ones you need to know cold.

Request Headers

HeaderWhat it does
Content-TypeFormat of the request body (application/json, multipart/form-data)
AcceptWhat format the client wants back (application/json, text/html)
AuthorizationCredentials — Bearer <token> for JWT, Basic <base64> for basic
Cache-ControlCaching instructions (no-cache, no-store, max-age=3600)
CookieSends stored cookies to the server
X-Request-IDCustom ID for tracing a request through distributed systems

Response Headers

HeaderWhat it does
Content-TypeFormat of the response body
Cache-ControlHow long the client should cache the response
Set-CookieInstructs the browser to store a cookie (HttpOnly, Secure flags)
LocationUsed with 201/3xx to point to the new/redirect URL
# Example: server sets a session cookie after login
HTTP/1.1 200 OK
Set-Cookie: session_id=abc123xyz; Path=/; HttpOnly; Secure; SameSite=Strict
Content-Type: application/json

{"message": "Login successful"}

# HttpOnly  — JavaScript cannot read this cookie (prevents XSS theft)
# Secure    — Only sent over HTTPS
# SameSite  — Controls cross-site sending (CSRF protection)

HTTP is Stateless — And Why That's a Problem

HTTP has no memory. Every request stands alone. The server does not know if you made a request one second ago or one year ago. There is no built-in concept of a "session."

The problem: Login requires state. After you log in, the server needs to know who you are on the next request.

The solution: Cookies and session tokens

Flow:
1. POST /login  {username, password}
         |
         v
2. Server validates credentials
   Server creates a session in its database
   Server returns: Set-Cookie: session_id=abc123

3. Browser stores the cookie automatically

4. GET /dashboard
   Cookie: session_id=abc123          ← browser sends it on every request
         |
         v
5. Server looks up session_id in database
   Finds the associated user
   Returns the dashboard data for that user

Two common approaches:

Server-side sessions: Session data stored in the database or Redis. The cookie holds only a session ID. Revocation is easy — just delete the session row.

JWT (JSON Web Tokens): The token itself contains the user data (claims), signed by the server. No database lookup needed. Revocation is hard — the token is valid until it expires.


HTTP/1.1 vs HTTP/2 vs HTTP/3

HTTP/1.1 (1997)

  • Text-based protocol — requests and responses are human-readable strings
  • Persistent connections — one TCP connection can be reused for multiple requests (Connection: keep-alive)
  • Head-of-line blocking: requests on a connection are processed in order. If request #1 is slow, requests #2, #3, and #4 wait — even if the server could answer them instantly
  • Workaround: browsers open 6 parallel TCP connections per domain (wasteful)
HTTP/1.1 Connection (one at a time, blocking):

Request 1  ---->  [slow response]
                              <---- Response 1
Request 2  ---->
                  <---- Response 2
Request 3  ---->
                  <---- Response 3

HTTP/2 (2015)

  • Binary framing — requests and responses are broken into binary frames, not text
  • Multiplexing — multiple requests travel over ONE TCP connection simultaneously, interleaved as frames. Head-of-line blocking is gone at the HTTP layer
  • Header compression (HPACK) — headers are compressed and deduplicated across requests (headers like Host and Authorization do not repeat in full)
  • Server Push — server can proactively send resources the client will need (e.g., push CSS and JS before the browser asks)
  • Still runs over TCP — TCP-level head-of-line blocking remains
HTTP/2 Connection (all multiplexed on one TCP connection):

Stream 1: Request 1 frame --> ... <-- Response 1 frames
Stream 2: Request 2 frame --> ... <-- Response 2 frames   (simultaneous)
Stream 3: Request 3 frame --> ... <-- Response 3 frames   (simultaneous)

HTTP/3 (2022)

  • Replaces TCP with QUIC (a protocol built on top of UDP)
  • Built-in TLS 1.3 encryption — security is part of the protocol, not layered on top
  • 0-RTT handshake — for returning clients, the connection can be established with zero round trips (QUIC merges the transport and crypto handshakes)
  • True multiplexing — QUIC handles streams independently at the transport layer, so packet loss on one stream does not block others (solves TCP's head-of-line blocking)
  • Connection migration — if you switch from WiFi to mobile data, the QUIC connection survives (identified by a connection ID, not IP/port)
Handshake comparison for HTTPS:

HTTP/1.1 + TLS 1.2:
  TCP SYN, SYN-ACK, ACK  (1 RTT)
  TLS ClientHello ...    (2 RTT)
  First request          (3 RTT)

HTTP/2 + TLS 1.3:
  TCP + TLS combined     (1 RTT)
  First request          (2 RTT)

HTTP/3 + QUIC:
  QUIC + TLS 1.3 combined (1 RTT, or 0 RTT for returning clients)
  First request           (1 RTT or 0 RTT)

Common Mistakes

  • Using POST for updates instead of PUT or PATCH. POST is for creation. Using it for updates violates REST conventions, breaks idempotency (retries create duplicates), and confuses other developers. Use PUT for full replacement, PATCH for partial updates.

  • Confusing 401 Unauthorized with 403 Forbidden. Despite its name, 401 means "not authenticated" — the server does not know who you are (missing or invalid credentials). 403 means "authenticated but not authorized" — the server knows who you are, but you do not have permission. A logged-in user hitting an admin endpoint gets 403, not 401.

  • Assuming HTTP/2 requires HTTPS. The HTTP/2 specification (RFC 7540) does not mandate TLS. However, every major browser only implements HTTP/2 over TLS (h2), and no browser supports HTTP/2 in cleartext (h2c). In practice, HTTP/2 without HTTPS does not work in any browser — but technically the spec allows it.


Interview Questions

Q: What is the difference between PUT and PATCH?

PUT replaces the entire resource. If you send a PUT with a partial object, the fields you omit are removed or reset to defaults. PATCH applies a partial update — only the fields you include are changed, and the rest stay as they are. Both methods target a specific resource URL (e.g., /users/42). PUT is required by the spec to be idempotent; PATCH is not, though it can be designed that way. Use PUT when you have the full representation of the resource; use PATCH when you only want to change specific fields.


Q: What does idempotent mean and which HTTP methods are idempotent?

An operation is idempotent if calling it multiple times produces the same result as calling it once. The end state of the system is identical regardless of how many times you apply the operation. Idempotent HTTP methods: GET, HEAD, PUT, DELETE, OPTIONS. Non-idempotent: POST (creates a new resource each time), and PATCH by default (though it can be made idempotent). Idempotency matters for safety in distributed systems — if a network failure causes a client to retry a request, idempotent operations are safe to retry without side effects.


Q: What is the difference between 401 and 403?

401 Unauthorized means the request lacks valid authentication credentials. The client is not identified — the token is missing, expired, or invalid. The solution is to log in or refresh the token. Despite its name "Unauthorized," it really means "unauthenticated."

403 Forbidden means the client is authenticated (the server knows who you are) but does not have permission to access the resource. You are logged in as a regular user trying to hit an admin endpoint. No amount of re-authenticating will fix a 403 — you need higher privileges.

Memory trick: 401 = "Who are you?", 403 = "I know who you are, but no."


Q: How does HTTP/2 solve the head-of-line blocking problem of HTTP/1.1?

In HTTP/1.1, requests on a single connection are processed sequentially — if request #1 takes 500ms, requests #2 and #3 wait even if they could be answered in 5ms. The workaround was opening 6 parallel TCP connections per domain, which is wasteful.

HTTP/2 introduces binary framing and multiplexing. Requests and responses are broken into small binary frames, each tagged with a stream ID. Multiple streams (independent request/response pairs) are interleaved over a single TCP connection. The server can respond to requests #2 and #3 before finishing #1, and the client reassembles responses by stream ID. This eliminates HTTP-layer head-of-line blocking. Note: TCP-level head-of-line blocking still exists in HTTP/2, which HTTP/3 (QUIC over UDP) solves completely.


Q: Why is HTTP stateless and how do sessions work?

HTTP is stateless because each request is completely independent. The server has no built-in memory of previous requests — it processes every request in isolation. This was a deliberate design choice that makes HTTP servers simple, scalable, and cacheable.

The problem is that real applications need state (login sessions, shopping carts, preferences). The solution is to store state somewhere and send a reference with each request.

Sessions work like this: when a user logs in, the server creates a session record (in a database or Redis), generates a unique session ID, and sends it to the browser via Set-Cookie. The browser stores the cookie and sends it back automatically on every subsequent request via the Cookie header. The server reads the session ID, looks up the session, and knows who the user is — simulating statefulness on top of a stateless protocol. JWTs work similarly but encode the state in the token itself rather than a server-side store.


Quick Reference — Cheat Sheet

HTTP Methods

MethodPurposeIdempotentHas BodySuccess Code
GETFetch resourceYesNo200
POSTCreate resourceNoYes201
PUTReplace resource (full)YesYes200 / 204
PATCHUpdate resource (partial)No*Yes200 / 204
DELETERemove resourceYesOptional204
HEADFetch headers onlyYesNo200
OPTIONSQuery allowed methods/CORSYesNo200 / 204

*PATCH can be designed to be idempotent, but the spec does not require it.

HTTP Status Codes by Category

RangeCategoryKey Codes
1xxInformational100 Continue
2xxSuccess200 OK, 201 Created, 204 No Content
3xxRedirect301 Moved Permanently, 302 Found, 304 Not Modified
4xxClient Error400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 405 Method Not Allowed, 429 Too Many Requests
5xxServer Error500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout

HTTP Version Comparison

FeatureHTTP/1.1HTTP/2HTTP/3
Protocol formatTextBinary framesBinary (QUIC)
TransportTCPTCPUDP (QUIC)
MultiplexingNo (workaround)YesYes (true)
Header compressionNoYes (HPACK)Yes (QPACK)
TLSOptionalRequired in browsersBuilt-in (always)
Head-of-line blockingHTTP levelTCP level onlyNone
0-RTT connectionNoNoYes (returning)

Raw HTTP at a Glance

REQUEST                              RESPONSE
-------                              --------
METHOD /path HTTP/version            HTTP/version STATUS_CODE Reason
Header: value                        Header: value
Header: value                        Header: value
                                     (blank line)
(blank line)                         Body (JSON, HTML, etc.)
Body (for POST/PUT/PATCH)

Previous: Lesson 4.4 — Ports & Sockets (../ch04-tcp-udp/04-ports-and-sockets.md) Next: Lesson 5.2 — HTTPS (02-https.md)


This is Lesson 5.1 of the Networking Interview Prep Course — 8 chapters, 32 lessons.

On this page