How the Web Works: Understanding the Request-Response Cycle & Headers

Introduction
Every Second, millions of people type words into a browser, click links, or scroll through a social media feed. What feels like magic is actually a structured conversation governed by a set of rules called HTTP (HyperText Transfer Protocol).
When you visit a website, your browser (the Client) asks a computer somewhere else (the Server) for the pictures, text, and code that make up that page. The server then sends it back. This simple back-and-forth is called the Request-Response Cycle.
In this article, we will tear open that "conversation" to see what is actually being said. We will break down the specific parts of the request and response, with a heavy focus on Headers—the metadata that controls security, caching, and authentication.
Topics Covered
The Analogy: A Restaurant Order
The Request: What the Client Asks For
The Response: What the Server Sends Back
Deep Dive: HTTP Headers (The "Fine Print")
Deep Dive: HTTP Methods (GET vs. POST)
Deep Dive: Status Codes (200, 404, 500)
Real-World Example: Using
curlto see the cycle.
1. The Analogy: A Restaurant Order
To make this technical concept stick, imagine you are eating at a restaurant.
You are the Client (Browser). You are hungry and want data (food).
The Waiter is the Internet/Network. They carry the message.
The Chef is the Server. They prepare the resource.
The Cycle:
You (Client) look at the menu and decide what you want. You tell the waiter, "I want a cheeseburger" (The Request).
The waiter takes the note to the chef. The chef reads the order, cooks the burger, and puts it on a plate.
The waiter brings the plate back to you. The plate contains the burger (The Response).
However, in web development, the "plate" comes with a receipt (Headers) that tells you what the burger is made of, how fresh it is, and who cooked it.
2. The Request: Asking for Data
When your browser wants to load https://www.example.com/home, it constructs an HTTP Request. An HTTP request is text, but it is highly structured. It consists of three parts.
A. The Request Line
This is the first line of the conversation. It tells the server what to do and which version of the rules to use . GET /home HTTP/1.1
B. The Headers (Key Metadata)
These are key-value pairs sent right after the request line. They don't contain the "body" of the data; they contain the instructions for the data. Host: www.example.com User-Agent: Mozilla/5.0
C. The Body (Optional)
This is usually empty for GET requests. It is used when you are sending data to the server, like when you submit a signup form. username=JohnDoe&password=12345
3. The Response: The Server Answers
Once the server receives the request, it processes it and sends back an HTTP Response. This also has three parts .
A. The Status Line
This tells the client if the request worked or failed. HTTP/1.1 200 OK
B. The Headers
Similar to the request, the response headers tell the browser how to handle the data it is about to receive. Content-Type: text/html (Tells the browser this is HTML text, not a PDF or an image).
C. The Body
This is the actual "burger." It is the HTML code, the CSS styling, or the image data that you wanted.
4. Deep Dive: HTTP Headers (The "Fine Print")
Headers are the most critical part of the web that most users never see. They control security, caching, and how data is interpreted. A header is simply a line of text formatted as Name: Value .
Let’s look at the most important ones.
Common Request Headers (Client -> Server)
Host: The domain name of the server. This allows one server to host multiple websites.User-Agent: This identifies the client software (e.g., Chrome, Safari, or a Python script). Developers use this to serve different versions of a site to mobile phones vs. desktops .Accept: Tells the server what format the client wants.Accept: application/jsonmeans "I want JSON data, please don't send me back HTML." .Authorization: This is the security guard. It carries the "tokens" or passwords required to prove you are allowed to see private data .- Example:
Authorization: Bearer abc123xyz
- Example:
Cookie: The browser automatically sends previously stored cookies back to the server to remind the server who you are .
Common Response Headers (Server -> Client)
Content-Type: This is crucial. It tells the browser how to display the response. If it istext/html, the browser renders a webpage. If it isapplication/pdf, the browser opens a PDF reader .Cache-Control: This controls caching (saving files locally). If a website loads a logo, the server says,Cache-Control: max-age=3600. This tells the browser, "Don't ask me for this logo again for the next hour; keep it in your back pocket." This makes the web faster .Set-Cookie: This is the only way for a server to save data on your computer. The server sends this header, and the browser saves it .Location: Used for redirection. If you ask for a page that moved, the server replies withStatus: 301and aLocation: https://new-url.comheader .Access-Control-Allow-Origin: This is part of CORS. It tells the browser if it is safe to let a website from one domain (likegoogle.com) access data on another domain (likefacebook.com) .
Simple Explanation of CORS: Imagine you live in an apartment (your browser). The Same-Origin Policy says you can only receive packages inside your living room. If Amazon sends a package, the doorman (Browser) opens it. If a stranger tries to send a package, the doorman blocks it unless the stranger has a specific key. The
Access-Control-Allow-Originheader is that key. If the server sendsAccess-Control-Allow-Origin: *, the doorman says, "Okay, anyone can send packages here." .
5. Deep Dive: HTTP Methods (Verbs)
The first word of the Request Line is the Method. It defines the intent of the request .
GET: "Give me data." This is used when you just want to look at a webpage or resource. GET requests should never change data on the server. They are like asking a librarian for a book .
POST: "Please create new data." This is used when you submit a form (e.g., creating a new user account). If you hit "Refresh" on a POST request, the browser warns you because it will try to send the data again .
PUT: "Please replace this entire thing with my new data." Usually used for updates.
DELETE: "Delete this resource."
The Concept of Idempotency
A big word for a simple idea: Safe methods. GET and PUT are idempotent. If you send the same GET request once or a hundred times, the result is the same. POST is not; sending "Create User" twice creates two users .
6. Deep Dive: HTTP Status Codes
The server uses a three-digit number in the response line to summarize the result .
You can group these into five families (like Hogwarts houses for errors):
1xx (Informational): "I heard you, give me a minute." Rarely seen by users.
2xx (Success): "Everything went perfectly."
200 OK: The standard success. "Here is your file."
201 Created: "POST request succeeded. I made a new user."
3xx (Redirection): "I don't have it, but go look over there."
301 Moved Permanently: "The page moved to a new address. Update your bookmarks."
304 Not Modified: (Uses caching) "You already have the latest version of this file. I'm not sending the body to save bandwidth." .
4xx (Client Error): "You messed up." (This is the user's fault).
400 Bad Request: "I couldn't understand what you said (usually bad grammar or missing data)."
401 Unauthorized: "I don't know who you are. Log in first."
403 Forbidden: "I know who you are, but you aren't allowed to see this (like an Admin page)." .
404 Not Found: "The URL you typed leads to nothing." The most famous error in the world.
5xx (Server Error): "I messed up." (The website's fault).
500 Internal Server Error: "The server's code crashed. This is a bug in the app."
503 Service Unavailable: "The server is too busy or down for maintenance."
7. Seeing it Live: The curl Command
You don't need fancy software to see this cycle. You can use curl (Command Line URL) in your terminal. The -v flag (verbose) shows us the raw Headers .
Open your terminal (Command Prompt, Powershell, or Bash) and type:
curl -v https://www.google.com
Look at the output. You will see this exact structure:
> GET / HTTP/2 <-- (The Request Line)
> Host: www.google.com <-- (Request Header)
> user-agent: curl/8.1.2 <-- (Request Header)
>
< HTTP/2 200 <-- (Status Line)
< content-type: text/html <-- (Response Header: It is HTML)
< cache-control: private <-- (Response Header: Don't cache this in public)
< server: gws <-- (Response Header: Google Web Server)
<
<!doctype html> ... (This is the Response Body/HTML)
The > arrows represent the request going out. The < arrows represent the response coming back.
Conclusion
You can now look at a broken website and understand why. If you see 500, you know the server code is broken. If you see 304, you know caching is working. If you notice the wrong language, check the Accept-Language header.
Understanding the Request-Response cycle turns the web from a cloud of mystery into a simple system of handshakes and paperwork. The next time you click a link, remember: you are just sending a GET request, expecting a 200 OK with a Content-Type that makes you smile.
Here are 20 advanced-level questions based strictly on the concepts from the article above. These are designed to test deep understanding, expose common misconceptions, and simulate real interview scenarios (Backend Developer, DevOps, or SRE roles).
I have categorized them by difficulty nuance, but all are considered "hard" for a junior or mid-level developer. Answers are provided immediately after each question to serve as a learning tool.
Category 1: The Request-Response Cycle (Non-obvious behavior)
Question 1
If a client sends a GET request with a body, is that strictly forbidden by the HTTP specification? What do real-world servers like Nginx or Express.js typically do?
Answer
Technically, the HTTP/1.1 specification (RFC 7231) does not explicitly forbid a body in a GET request, but it says the server should ignore it because GET has no defined semantics for a body. However, in practice:
Nginx will reject the request (return
400 Bad Requestor drop the body).Express.js (Node.js) will accept it, but the body parsing middleware will ignore it by default.
Apache will ignore the body.
Interview trick: The correct answer is "It is not forbidden by the spec, but it is semantically meaningless, and most production servers will discard it or error out."
Question 2
The article explains Cache-Control: max-age=3600. What is the difference between max-age and s-maxage, and in what deployment scenario would s-maxage ever matter?
Answer
max-ageapplies to the browser's cache (the end user client).s-maxageapplies only to shared caches (CDNs like Cloudflare, Akamai, or reverse proxies like Varnish).
Scenario: You have a dynamic homepage that changes every minute, but you want your CDN to cache it for 1 hour to reduce origin load. You set:
Cache-Control: max-age=60, s-maxage=3600
The browser will revalidate every 60 seconds.
The CDN will serve the stale copy for 1 hour without hitting your origin server.
Advanced nuance: If s-maxage is present, a shared cache MUST ignore max-age.
Question 3
Explain the exact sequence of TCP packets involved in a single HTTP/1.1 request-response cycle over a new connection (assume no TLS).
Answer
This requires knowing the TCP handshake is not part of HTTP, but happens before it.
TCP Three-Way Handshake:
Client → Server:
SYNServer → Client:
SYN-ACKClient → Server:
ACK
HTTP Request (over the established connection):
- Client → Server:
PSH, ACK(contains the HTTP request text)
- Client → Server:
HTTP Response:
- Server → Client:
PSH, ACK(contains the HTTP response text)
- Server → Client:
Connection Teardown (if
Connection: closeheader is used):- Active close (usually server or client):
FIN→ACK→FIN→ACK
- Active close (usually server or client):
Key insight: HTTP is a semantic layer on top of TCP. Until the SYN-ACK completes, no HTTP traffic flows.
Category 2: Headers (Edge Cases & Security)
Question 4
You see a response header: Cache-Control: no-store, no-cache, must-revalidate, private. Explain the difference between no-store and no-cache. Why would you use both?
Answer
no-store: The browser must not store any part of the response (memory or disk). It is for sensitive data (e.g., bank balances, session tokens).no-cache: The browser can cache the response, but must revalidate with the server before using it (send anIf-Modified-SinceorETagheader).
Why both? Because no-store is stronger. If you only send no-cache, a buggy browser might still write to disk. no-store ensures it doesn't. must-revalidate is redundant with no-cache but is kept for HTTP/1.0 compatibility.
Real example: A banking API response containing a one-time password (OTP) would send:
Cache-Control: no-store, private
It omits no-cache because the response should never be stored at all.
Question 5
What is the Host header used for technically? Explain how virtual hosting works, and then describe a security attack that exploits a missing or malformed Host header.
Answer
Technical use: The Host header allows multiple domain names to resolve to the same IP address and port. The web server inspects the Host header to decide which website's files to serve.
Attack: HTTP Host Header Injection (or Cache Poisoning)
An attacker sends a request to
https://example.combut with theHost: evil.comheader.If the server blindly uses the
Hostheader to generate absolute URLs in its response (e.g., in a password reset email), it might create a link toevil.com/reset?token=xyz.A caching reverse proxy might store the poisoned response and serve it to other users.
Mitigation: Validate the Host header against a whitelist. Never trust user input, even in headers.
Question 6
Explain the difference between Origin header and Referer header. When does the Origin header exist but Referer does NOT exist? Give a specific browser scenario.
Answer
Origin: Contains only the scheme, host, and port (e.g.,https://example.com). It is sent for CORS requests (cross-origin) and forPOST,PUT,DELETEmethods regardless of same/cross origin.Referer: Contains the full URL (including path and query string). It is sent for navigation, images, scripts, CSS, etc. It can be suppressed for privacy.
Scenario where Origin exists but Referer does NOT: When you make a fetch() request in the browser with referrerPolicy: "no-referrer" or when the request is from a secure page (HTTPS) to a non-secure page (HTTP) and the browser drops the referrer.
Example:
fetch('http://insecure-api.com/data', {
method: 'POST',
referrerPolicy: 'no-referrer',
headers: { 'Content-Type': 'application/json' }
});
The browser sends Origin: https://my-secure-site.com (for CORS) but no Referer header.
Question 7
The article mentions Authorization: Bearer abc123xyz. What is the difference between Bearer tokens and Basic authentication (Authorization: Basic base64(username:password)), and what is a practical security vulnerability of Basic auth that Bearer tokens solve?
Answer
| Feature | Basic Auth | Bearer Token |
|---|---|---|
| Format | username:password base64 encoded |
Opaque string or JWT |
| Revocation | Requires password change | Token can be revoked independently |
| Logout | Impossible (stateless) | Delete the token |
| Scope | Full account access | Fine-grained scopes (e.g., "read-only") |
Vulnerability that Bearer tokens solve: Credential Shuffling With Basic auth, if you share an API key with a third-party service, they have your actual password. To revoke access, you must change your password, which breaks all other services. With Bearer tokens, you issue a unique token to each service and revoke it individually.
Note: Bearer tokens are not inherently more secure over the wire. Both MUST be sent over HTTPS only.
Question 8
Explain the X-Forwarded-For header. Why is it dangerous to trust it blindly, and what header should you prefer when your application is behind a trusted proxy (like AWS ALB or Nginx)?
Answer
X-Forwarded-For: Contains the original client IP address when a request passes through proxies. Format:client, proxy1, proxy2.
Why it's dangerous: Any client can spoof it. An attacker can send:
X-Forwarded-For: 1.2.3.4, 127.0.0.1
If your application logs or rate-limits based on the first IP, they control it.
Solution: Use X-Forwarded-For only from trusted proxies (your load balancer's IP). Most modern proxies use the Forwarded header (RFC 7239), which is more structured and less prone to spoofing.
Preference order:
Forwarded(standard)X-Real-IP(single IP, set by trusted proxy)Last address in
X-Forwarded-For(the one set by the last trusted proxy)
Question 9
Explain the Strict-Transport-Security (HSTS) header. What happens when a browser receives max-age=0 for a domain that was previously HSTS-enabled?
Answer
Strict-Transport-Security tells the browser: "For the next max-age seconds, never connect to this domain over HTTP. Automatically convert all HTTP links to HTTPS."
Example:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
When max-age=0 is sent to an already HSTS-enabled domain: The browser immediately expires the HSTS policy for that domain. Future requests will use HTTP again (if the user explicitly types http://).
Critical nuance: If the domain is on the HSTS Preload List (hardcoded in browsers), max-age=0 has no effect—the browser will always require HTTPS regardless of headers.
Category 3: Methods & Idempotency (Deep)
Question 10
The article explains idempotency for GET and PUT. Is DELETE idempotent? Provide a concrete example where the response changes but the server state is still idempotent.
Answer
Yes, DELETE is idempotent according to the HTTP spec (RFC 7231).
Example:
First DELETE request to
/users/123:Server deletes user 123.
Response:
200 OKor204 No Content.
Second DELETE request to
/users/123:User does not exist.
Server cannot delete it again.
Response:
404 Not Found.
Why this is still idempotent: Idempotency is about server state, not response status code. After the first request, the server has no user 123. After the second request, the server still has no user 123. The final state is identical. Changing the response code from 200 to 404 is acceptable.
Question 11
Is PATCH idempotent? Justify your answer with an example of a non-idempotent PATCH and an idempotent PATCH.
Answer
No, PATCH is NOT required to be idempotent, but it can be implemented as idempotent.
Non-idempotent PATCH (JSON Patch add operation):
PATCH /users/123
[ { "op": "add", "path": "/tags/-", "value": "admin" } ]
The /- means "append to array". Each request adds another "admin" tag. Three requests → three tags. State changes with each call.
Idempotent PATCH (JSON Merge Patch):
PATCH /users/123
{ "status": "active" }
Setting status to "active" ten times changes nothing after the first request.
Spec quote: "A PATCH request is not required to be idempotent, but it can be."
Question 12
Explain the semantic difference between PUT and POST when creating a new resource on the server. Under what specific condition does PUT become non-idempotent?
Answer
POST : Client does not know the final URL. Server generates the ID and returns it in the
Locationheader.POST /articles→ Server creates/articles/123
PUT : Client does know the final URL. Client is responsible for naming the resource.
PUT /articles/123→ Client says "create or replace at this exact path"
PUT becomes non-idempotent if: The server modifies the resource based on a timestamp or counter that changes with each request, even if the request body is identical. Example:
PUT /logs/entry-1
{ "timestamp": "auto", "sequence": "auto" }
If the server fills in "timestamp": "now()" each time, two identical PUTs produce different resources. This violates idempotency and is considered bad API design.
Category 4: Status Codes (Niche Cases)
Question 13
You get a 429 Too Many Requests status code. Explain the purpose of the Retry-After header in this context. What are the allowed formats for Retry-After?
Answer
Retry-After tells the client how long to wait before making another request.
Two allowed formats:
HTTP-date : An absolute timestamp.
Retry-After: Wed, 21 Oct 2025 07:28:00 GMTDelay-seconds : A non-negative integer number of seconds.
Retry-After: 120 (wait 2 minutes)
Behavior: The client SHOULD (soft requirement) respect this header. Well-behaved clients implement exponential backoff using this value as the initial delay.
Question 14
Explain the difference between 401 Unauthorized and 403 Forbidden. Many developers get this wrong. Provide a scenario where a server returns 401 and a different scenario where it returns 403 for the same resource.
Answer
This is a famously misnamed pair. 401 is about authentication (who you are). 403 is about authorization (what you are allowed to do).
Scenario for 401 (Not logged in):
User requests
/admin/settingsNo
Authorizationheader presentServer: "I don't know who you are. Provide credentials."
Response:
401 UnauthorizedwithWWW-Authenticate: Basic realm="Admin"
Scenario for 403 (Logged in, but not allowed):
User requests
/admin/settingsAuthorizationheader contains a valid token for user "alice"Alice is a regular user, not an admin
Server: "I know you are Alice, but Alice cannot access admin settings."
Response:
403 Forbidden
Real-world gotcha: OAuth2 APIs often return 403 for invalid tokens because they interpret "invalid token" as "you are not the right person" rather than strictly "you are unknown."
Question 15
What is the 100 Continue status code? In what specific HTTP request scenario does the client send an Expect: 100-continue header, and why does this optimization exist?
Answer
100 Continue is an informational response that says: "I've received your headers. Please proceed to send the request body."
Scenario: A client wants to upload a very large file (e.g., 1 GB) to a server that may reject it based on headers (e.g., invalid authentication).
Without 100 Continue:
Client sends headers + 1 GB of body.
Server checks auth header → invalid.
Server rejects with
401.Client wasted 1 GB of upload bandwidth.
With 100 Continue:
Client sends headers only, plus
Expect: 100-continue.Server checks auth header.
If valid, server responds
100 Continue.Client now sends the 1 GB body.
If auth invalid, server responds
401immediately. Client never sends the file.
Time saved: Massive. Used by curl --expect100-timeout and AWS S3 multipart uploads.
Question 16
Explain the difference between 302 Found (HTTP/1.0) and 303 See Other (HTTP/1.1). Why was 303 introduced, and how does it affect the subsequent request method after redirection?
Answer
This is a classic HTTP ambiguity.
| Status | Original Request | Behavior after redirect (spec) |
|---|---|---|
| 302 Found | POST | MAY change to GET (but historically browsers did GET) |
| 303 See Other | Any (POST, PUT, DELETE) | MUST change to GET |
Why 303 was introduced: To solve the "Post/Redirect/Get" (PRG) pattern without ambiguity.
User submits a form (
POST /submit)Server processes it and returns
303 See OtherwithLocation: /thank-youBrowser must perform a
GETto/thank-youIf user hits refresh on the thank-you page, it does not resubmit the form.
Without 303 (using 302): Some browsers would send another POST on refresh, causing duplicate form submissions.
Category 5: Advanced Integration & WTF Scenarios
Question 17
What is "Hop-by-Hop" vs. "End-to-End" headers? Name two headers from the article that are hop-by-hop and explain what happens to them when a request passes through a proxy.
Answer
End-to-end headers : Must be transmitted to the ultimate server and preserved in the response back to the client. Most headers are end-to-end (e.g.,
Content-Type,Cache-Control,Authorization).Hop-by-hop headers : Are meaningful only for a single transport connection. A proxy must remove or modify these headers before forwarding.
Hop-by-hop headers (from HTTP/1.1 spec):
Connection(controls active connection, e.g.,Connection: close)Keep-AliveProxy-AuthorizationTransfer-Encoding(e.g.,chunked)Upgrade(used for WebSocket upgrade)
Example: Client sends: Connection: close, Transfer-Encoding: chunked Proxy strips Connection and Transfer-Encoding, then forwards. The server never sees these headers.
Question 18
Explain how HTTP/2 multiplexing changes the request-response cycle compared to HTTP/1.1. Does the concept of a single "request" followed by a single "response" still hold in HTTP/2?
Answer
In HTTP/1.1: One request at a time per TCP connection. Requiring 100 resources (images, CSS, JS) means either 100 sequential requests (slow) or 6-8 parallel TCP connections.
In HTTP/2:
Single TCP connection.
Multiple streams inside that connection.
Streams are interleaved (multiplexed) in binary frames.
Does the request-response model hold? Yes, at the logical level. Each stream still has exactly one request and one response. However, responses can be interleaved: a server can send part of response A, then part of response B, then finish response A.
Critical difference: Headers are compressed (HPACK) and sent only once per connection (via HEADERS frame, then DATA frames). The Host header is replaced by :authority pseudo-header.
Question 19
What is an HTTP Upgrade header? Describe the exact request-response sequence required to upgrade a connection from HTTP to WebSocket.
Answer
The Upgrade header tells the server: "I want to switch this connection to a different protocol."
WebSocket Upgrade Sequence:
Client sends HTTP/1.1 GET request:
GET /chat HTTP/1.1 Host: example.com Connection: Upgrade Upgrade: websocket Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Version: 13Server validates and responds with HTTP 101 Switching Protocols:
HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: websocket Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=After the response, both parties switch protocols. The same TCP socket now speaks WebSocket frames, not HTTP.
Key insight: The Connection: Upgrade header is a hop-by-hop header (see Question 17) and must be processed before forwarding.
Question 20
You are debugging a website that loads fine in Chrome but fails with "CORS error" in a custom Node.js script using axios. The response headers show Access-Control-Allow-Origin: *. What is the most likely cause, and why does the browser enforce CORS while the backend script does not?
Answer
Most likely cause: The Node.js script is not sending the Origin header, and the server is incorrectly checking for its presence.
Detailed explanation:
CORS (Cross-Origin Resource Sharing) is a browser security mechanism. It does not apply to server-to-server requests (Node.js, Python,
curl).When a browser sees a cross-origin request:
It automatically adds the
Origin: https://my-site.comheader.It looks for
Access-Control-Allow-Originin the response.If missing or mismatched, the browser blocks the response body from JavaScript.
When Node.js (or any server) makes the same request:
It does not send an
Originheader unless manually added.It does not check any CORS headers in the response.
It receives the response body normally.
Why the script fails: If the backend is misconfigured to require Origin header on all requests (or to return Access-Control-Allow-Origin only if Origin matches a whitelist), a request with no Origin header might:
Get a
403 ForbiddenGet a response missing the CORS header (irrelevant to Node.js)
Be rejected by an API gateway
Fix in Node.js: Explicitly set the Origin header to the expected value, or use a user-agent that mimics a browser (though this is hacky and not recommended for production).
Final Challenge for You
If you can answer all 20 questions without looking back at the answers, you understand the HTTP request-response cycle and headers at a senior engineer level. For interview preparation, practice explaining these concepts out loud, as if teaching a junior developer. The ability to simplify the complex answer (as done above) is what interviewers actually reward.




