Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 8

Anatomy of HTTP Requests and Responses

Recommended resources

Hello! Welcome to the second module of our course, "The HTTP Protocol Inside Out."

In our last lesson, we finished our deep dive into networking fundamentals by using Wireshark to capture raw network packets. We even peeked into a TCP stream and saw a human-readable conversation between a web browser and a server. That conversation used the Hypertext Transfer Protocol, or HTTP.

Today, we will learn to decipher that conversation. We're moving up the networking stack from the Transport Layer (TCP) to the Application Layer, where HTTP lives.

Today's Goal: By the end of this lesson, you will be able to break down the structure of an HTTP request and response, including the start-line, headers, and body. This is the fundamental grammar of the web, and understanding it is crucial for any backend developer.

The Anatomy of an HTTP/1.1 Message

At its core, HTTP/1.1 is a text-based protocol. This means the messages exchanged between a client (like your browser) and a server are just streams of text, which is why we could read them in Wireshark. These messages come in two types: requests (from client to server) and responses (from server to client).

Both share a common, four-part structure:

  1. Start-Line: The very first line, which defines the request's intent or the response's status.
  2. Headers: A series of key-value pairs that provide metadata about the message.
  3. Blank Line: A single, empty line (\r\n) that critically separates the headers from the body.
  4. Body (Optional): The actual data or content being sent, like a JSON payload or an HTML document.

This diagram provides a great visual summary of the structure for both requests and responses.

HTTP Request and Response Anatomy
A visual breakdown of an HTTP request (left) and an HTTP response (right), showing the start-line, headers, and body for each.

Let's dissect each part, starting with the request.


Dissecting the HTTP Request

The request is the message your application's client (a browser, a mobile app, or another backend service) sends to your server to ask it to perform an action. We'll use a detailed article to walk through its structure line by line.

Dissecting the HTTP Request — Line by Line

The article 'Dissecting the HTTP Request — Line by Line' provides an excellent, deep breakdown of what constitutes a valid HTTP request. We'll start with the bare minimum required to make a request work.

Please read from the beginning of the article down to the end of the section 'The Simplest Request That Works'. Focus on understanding the three components of the Request Line (Method, Request Target, HTTP Version) and the critical importance of the mandatory Host header and the Blank Line.

As you just read, a minimal valid HTTP/1.1 request is surprisingly simple. For example:

GET / HTTP/1.1
Host: example.com

Let's quickly summarize the key parts:

  • Request Line: GET / HTTP/1.1
    • GET: The method, telling the server we want to retrieve a resource.
    • /: The request target, specifying which resource (in this case, the root document).
    • HTTP/1.1: The protocol version.
  • Headers: Host: example.com
    • The Host header is mandatory in HTTP/1.1. Since a single server IP address can host multiple websites (e.g., api.myapp.com and blog.myapp.com), this header tells the server which one you're trying to reach. This is known as virtual hosting.
  • Blank Line: The request ends with a blank line (\r\n). This is the signal to the server that the header section is complete. If a body were to follow, it would start after this line.

Real-World Requests: Headers and Body

While the minimal request works, real-world clients send more information. They also send data to the server, not just request data from it. This is done using a request body.

Let's continue with the same article to see how this works.

Dissecting the HTTP Request — Line by Line

Now let's look at the other parts of a more complex request, including common headers and the request body, which is essential for sending data.

Read the sections 'Adding Real-World Headers' and 'Requests with a Body: POST and Beyond'. Pay close attention to: The purpose of User-Agent and Accept headers. The two crucial headers required when sending a body: Content-Type and Content-Length.

To summarize, when a request includes a body (e.g., a POST request with JSON data), two headers become essential:

  • Content-Type: Tells the server how to interpret the body. Is it application/json, application/x-www-form-urlencoded, or something else? Your Django backend uses this to know how to parse request.data.
  • Content-Length: Tells the server exactly how many bytes to read for the body. Without this, the server wouldn't know where the body ends and the next request begins on the same connection.

Seeing It Live: Building a Raw HTTP Request

Reading about the protocol is one thing; seeing it in action at the lowest level is another. The following video demonstrates how to send raw HTTP requests over a plain TCP connection, perfectly illustrating the concepts we've just discussed.

What exactly is the HTTP protocol and how to write a new one from scratch?

In this video, 'What exactly is the HTTP protocol and how to write a new one from scratch?', the presenter manually constructs HTTP requests. This will give you a root-level view of what's happening under the hood of tools like curl or your browser.

Watch from 01:32 to 09:50. Observe how: A simple GET request fails without a Host header (03:04). A POST request initially fails because the server doesn't know to wait for a body (07:05). Adding the Content-Length header tells the server to read a specific number of bytes from the TCP stream as the request body (08:15). The Content-Type header informs the server's application logic (like Express or Django) how to parse that body (10:03).

This hands-on demonstration really solidifies why these headers aren't just arbitrary text but are fundamental to the protocol's mechanics.


Dissecting the HTTP Response

Once the server processes the request, it sends back a response. The response follows the same start-line -> headers -> blank line -> body structure, but the details are different.

HTTP messages - MDN Web Docs

The MDN Web Docs provide a clear and authoritative guide to the structure of all HTTP messages. We'll use it to understand the response.

Read the section titled 'HTTP responses'. Focus on the three parts of the Status Line (Protocol Version, Status Code, Reason Phrase) and see the examples of response headers and a response body.

Here's a quick breakdown of a typical response:

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 1256

<!DOCTYPE html>
<html>
<head>
  <title>An Example Page</title>
</head>
<body>
  <p>Hello World, this is a very simple HTML document.</p>
</body>
</html>
  • Status Line: HTTP/1.1 200 OK
    • HTTP/1.1: The protocol version.
    • 200: The status code. This is the most important part, telling the client the result of the request. 200 means success. Others, like 404 (Not Found) or 500 (Internal Server Error), indicate problems.
    • OK: The reason phrase, a human-friendly description of the status code.
  • Headers: Just like requests, response headers provide metadata.
    • Content-Type: Tells the client (e.g., your browser) how to render the body. In this case, as an HTML document.
    • Content-Length: Tells the client how many bytes to expect in the response body.
  • Body: The actual content the client requested. Here, it's the HTML source code for a web page. Note that some responses, like a 204 No Content, will have no body.

Conclusion

Today you've peeled back the first layer of the HTTP protocol. By treating HTTP messages as simple, structured text, you can understand and debug a huge range of backend issues.

Key Takeaways:

  • HTTP/1.1 is a text-based protocol with two message types: requests and responses.
  • Both messages share a structure: a start-line, a block of headers, a blank line separator, and an optional body.
  • The request-line contains the Method, Request-Target, and HTTP-Version.
  • The Host header is mandatory for all HTTP/1.1 requests to support virtual hosting.
  • Requests with a body (like POST) must include Content-Type (to describe the body's format) and Content-Length (to specify its size).
  • The status-line of a response contains the HTTP-Version, a numeric Status-Code, and a textual Reason-Phrase.

Preview of the Next Lesson:

We've seen that the Method (e.g., GET, POST) is a key part of the request line. But what do all the different methods mean? In our next lesson, we will dive deep into the semantics of common HTTP methods, explaining the precise role of GET, POST, PUT, PATCH, and DELETE, and when to use each one correctly in your API design.