# 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 `curl` to 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:**

1.  You (Client) look at the menu and decide what you want. You tell the waiter, "I want a cheeseburger" (The **Request**).
    
2.  The waiter takes the note to the chef. The chef reads the order, cooks the burger, and puts it on a plate.
    
3.  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/json` means "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`
        
*   `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 is `text/html`, the browser renders a webpage. If it is `application/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 with `Status: 301` and a `Location: https://new-url.com` header .
    
*   `Access-Control-Allow-Origin`: This is part of **CORS**. It tells the browser if it is safe to let a website from one domain (like `google.com`) access data on another domain (like `facebook.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-Origin` header is that key. If the server sends `Access-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:

```bash
curl -v https://www.google.com
```

Look at the output. You will see this exact structure:

```plaintext
> 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 Request` or 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-age` applies to the **browser's cache** (the end user client).
    
*   `s-maxage` applies 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:

```plaintext
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.

1.  **TCP Three-Way Handshake:**
    
    *   Client → Server: `SYN`
        
    *   Server → Client: `SYN-ACK`
        
    *   Client → Server: `ACK`
        
2.  **HTTP Request (over the established connection):**
    
    *   Client → Server: `PSH, ACK` (contains the HTTP request text)
        
3.  **HTTP Response:**
    
    *   Server → Client: `PSH, ACK` (contains the HTTP response text)
        
4.  **Connection Teardown (if** `Connection: close` **header is used):**
    
    *   Active close (usually server or client): `FIN` → `ACK` → `FIN` → `ACK`
        

**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 an `If-Modified-Since` or `ETag` header).
    

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

```plaintext
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)**

1.  An attacker sends a request to `https://example.com` but with the `Host: evil.com` header.
    
2.  If the server blindly uses the `Host` header to generate absolute URLs in its response (e.g., in a password reset email), it might create a link to `evil.com/reset?token=xyz`.
    
3.  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 for `POST`, `PUT`, `DELETE` methods 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:

```javascript
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:

```plaintext
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:**

1.  `Forwarded` (standard)
    
2.  `X-Real-IP` (single IP, set by trusted proxy)
    
3.  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:

```plaintext
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:**

1.  **First DELETE request** to `/users/123`:
    
    *   Server deletes user 123.
        
    *   Response: `200 OK` or `204 No Content`.
        
2.  **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):**

```json
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):**

```json
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 `Location` header.
    
    *   `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:

```json
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:**

1.  **HTTP-date** : An absolute timestamp.
    
    ```plaintext
    Retry-After: Wed, 21 Oct 2025 07:28:00 GMT
    ```
    
2.  **Delay-seconds** : A non-negative integer number of seconds.
    
    ```plaintext
    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/settings`
    
*   No `Authorization` header present
    
*   Server: "I don't know who you are. Provide credentials."
    
*   Response: `401 Unauthorized` with `WWW-Authenticate: Basic realm="Admin"`
    

**Scenario for** `403` **(Logged in, but not allowed):**

*   User requests `/admin/settings`
    
*   `Authorization` header 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`**:**

1.  Client sends headers + 1 GB of body.
    
2.  Server checks auth header → invalid.
    
3.  Server rejects with `401`.
    
4.  Client wasted 1 GB of upload bandwidth.
    

**With** `100 Continue`**:**

1.  Client sends headers only, plus `Expect: 100-continue`.
    
2.  Server checks auth header.
    
3.  If valid, server responds `100 Continue`.
    
4.  Client now sends the 1 GB body.
    
5.  If auth invalid, server responds `401` immediately. 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 Other` with `Location: /thank-you`
    
*   Browser **must** perform a `GET` to `/thank-you`
    
*   If 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):**

1.  `Connection` (controls active connection, e.g., `Connection: close`)
    
2.  `Keep-Alive`
    
3.  `Proxy-Authorization`
    
4.  `Transfer-Encoding` (e.g., `chunked`)
    
5.  `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:**

1.  **Client sends HTTP/1.1 GET request:**
    
    ```plaintext
    GET /chat HTTP/1.1
    Host: example.com
    Connection: Upgrade
    Upgrade: websocket
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
    Sec-WebSocket-Version: 13
    ```
    
2.  **Server validates and responds with HTTP 101 Switching Protocols:**
    
    ```plaintext
    HTTP/1.1 101 Switching Protocols
    Connection: Upgrade
    Upgrade: websocket
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
    ```
    
3.  **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:
    
    1.  It automatically adds the `Origin: https://my-site.com` header.
        
    2.  It looks for `Access-Control-Allow-Origin` in the response.
        
    3.  If missing or mismatched, the browser blocks the response body from JavaScript.
        
*   When Node.js (or any server) makes the same request:
    
    1.  It does **not** send an `Origin` header unless manually added.
        
    2.  It does **not** check any CORS headers in the response.
        
    3.  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 Forbidden`
    
*   Get 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.
