2.8. HTTP Requests
Table of Contents
Understanding HTTP Requests
When a browser or mobile app talks to a backend, it sends an HTTP request. As a backend developer, almost everything you do is about receiving, understanding, and responding to these requests.
This chapter focuses only on the request side. Responses, status codes, headers, cookies, and sessions have their own chapters. Here you will learn what exactly a request looks like and how to think about it.
The Big Picture: What Is an HTTP Request?
An HTTP request is a message sent from a client to a server that says:
- What I want to do
- Where I want to do it
- Extra details and options
- Optional data I am sending to you
You can think of it as a formal letter:
| Letter Concept | HTTP Request Part |
|---|---|
| Envelope front | Request line |
| Extra notes on envelope | Request headers |
| The actual content | Request body (optional) |
| Destination address | URL / path + host |
| Delivery method | HTTP method (GET, POST, …) |
The Structure of an HTTP Request
Every HTTP request has three main parts:
- Request line
- Headers
- Body (optional)
The full raw request (as the server sees it) looks like this:
POST /login HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Content-Type: application/json
Content-Length: 45
{"username": "alice", "password": "secret"}1. Request Line
The request line is always the very first line. It has three pieces:
METHOD PATH VERSIONExample:
GET /products?page=2 HTTP/1.1GETis the HTTP method/products?page=2is the path plus query stringHTTP/1.1is the HTTP version
The request line must be exactly:
<METHOD> <REQUEST-TARGET> <HTTP-VERSION>
separated by single spaces, one line only.
You will learn methods (GET, POST, etc.) and HTTP versions in separate chapters, so here we only care that:
- The first word tells the action (GET something, POST something, etc.)
- The second part tells which resource on the server
- The third part tells which HTTP version rules to follow
Request Target: Path and Query String
In the request line, the second part usually looks like:
/path/to/resource?key1=value1&key2=value2It has two parts:
| Part | Example | Meaning |
|---|---|---|
| Path | /products/123 | Which resource on the server |
| Query string | ?page=2&sort=price | Extra parameters to filter/sort/etc. |
Some examples:
GET / HTTP/1.1
GET /products HTTP/1.1
GET /products/123 HTTP/1.1
GET /search?q=laptop&limit=10 HTTP/1.1Headers: Extra Information About the Request
After the request line come headers: each on its own line, in the form:
Header-Name: valueHeaders are just key-value pairs that:
- Describe the request
- Describe the client
- Describe the body (if any)
- Give extra instructions
Examples:
Host: example.com
User-Agent: Mozilla/5.0
Accept: text/html
Accept-Language: en-US,en;q=0.9
Content-Type: application/json
Content-Length: 45You will learn specific important headers in the dedicated "HTTP Headers" chapter, but as a backend developer you should know:
- Headers come after the request line and before the body
- There is one blank line after the last header
- The blank line separates headers from body
Visual layout:
GET /example HTTP/1.1 ← request line
Host: example.com ← headers
Accept: text/html ← headers
User-Agent: CustomClient ← headers
← blank line (end of headers)
<no body for GET> ← body (optional)The Request Body
The body is optional. Not every request has one.
Typical rules:
GETandDELETEnormally do not have bodiesPOST,PUT,PATCHusually do have bodies
The body is where the main data lives, for example:
- Form fields from an HTML form
- JSON data from a JavaScript frontend
- File content for uploads (images, PDFs, etc.)
Example, JSON body:
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 51
{"email": "bob@example.com", "password": "123456"}
The server uses headers like Content-Type and Content-Length to know how to read and interpret the body.
Some common request body formats you will see later:
| Content-Type | Used For |
|---|---|
application/json | APIs, JavaScript frontends |
application/x-www-form-urlencoded | Simple HTML forms |
multipart/form-data | Forms with file uploads |
text/plain | Simple text payloads |
Raw HTTP Request Example in Detail
Let us carefully inspect a complete example.
POST /api/todos HTTP/1.1
Host: api.example.com
User-Agent: MyTodoApp/1.0
Accept: application/json
Content-Type: application/json
Content-Length: 68
{"title": "Finish course", "completed": false, "priority": "high"}Breakdown:
- Request line
- Method:
POST - Target:
/api/todos - Version:
HTTP/1.1 - Headers
Host: which server hostnameUser-Agent: what client is sending the requestAccept: client prefers JSON responseContent-Type: body is JSONContent-Length: 68 bytes of body- Body
JSON data with fields for the new todo item
As a backend developer (for example in FastAPI, Flask, Express, etc.) you will:
- Read the method and path to route the request to the correct handler
- Read headers to understand the context and body format
- Parse the body into a data structure (like a Python dict)
URLs vs Paths in Requests
When a browser sends a request, it already knows the full URL like:
https://api.example.com/api/users?page=2But in the request line, only the path and query appear:
GET /api/users?page=2 HTTP/1.1
Host: api.example.com
The scheme (https) and host (api.example.com) are not part of the path.
They show up in:
- TCP connection settings (server is already
api.example.comon port 443) - Host header in HTTP/1.1
- TLS layer for HTTPS (covered later)
So as a backend developer, when you see a request inside your server framework, you usually see:
path=/api/usersquery_string=page=2
Example: Comparing Several Request Types
Let us compare how different actions look at the HTTP level.
1. Simple GET Request (no body)
GET /products/42 HTTP/1.1
Host: shop.example.com
Accept: application/json- Ask for product 42
- No body, only headers
2. GET with Query Parameters
GET /products?category=books&sort=price_asc HTTP/1.1
Host: shop.example.com
Accept: application/json- Query string:
category=books&sort=price_asc - The server will parse those into parameters
3. POST with JSON Body
POST /api/orders HTTP/1.1
Host: shop.example.com
Content-Type: application/json
Content-Length: 82
{"user_id": 123, "items": [{"product_id": 42, "quantity": 2}], "payment_method": "card"}- Body contains JSON data
- Method is
POST, means "create a new order" in a REST style API
4. POST with Form Data
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
username=alice&password=secret- Body is URL encoded form data
- Typical for HTML forms
How Clients Create HTTP Requests
Different clients build HTTP requests under the hood, but the structure is always the same.
Browser Address Bar
If you type:
https://example.com/products/42The browser sends something like:
GET /products/42 HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8You did not see this raw text, but the browser created it.
`curl` Example
curl is a command line tool. When you run:
curl -X POST https://api.example.com/login \
-H "Content-Type: application/json" \
-d '{"email": "alice@example.com", "password": "secret"}'It generates an HTTP request like:
POST /login HTTP/1.1
Host: api.example.com
User-Agent: curl/8.0.1
Accept: */*
Content-Type: application/json
Content-Length: 52
{"email": "alice@example.com", "password": "secret"}JavaScript `fetch` Example
In the browser:
fetch("https://api.example.com/todos", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ title: "Learn HTTP", completed: false })
});This sends a request similar to:
POST /todos HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 45
User-Agent: Mozilla/5.0
Accept: */*
{"title": "Learn HTTP", "completed": false}How Servers See HTTP Requests
Server frameworks hide the raw HTTP text and give you a nice interface, but the underlying data is the same.
Example in Python with FastAPI
You do not need to know FastAPI yet. Look only at what you get from the request:
from fastapi import FastAPI, Request
app = FastAPI()
@app.post("/login")
async def login(request: Request):
method = request.method # "POST"
path = request.url.path # "/login"
query_params = request.query_params # e.g. {"next": "/dashboard"}
headers = request.headers # dict-like of headers
body = await request.body() # raw bytes of the body
# You would then parse JSON, forms, etc.
return {"ok": True}Everything comes from the HTTP request:
methodis the request line methodurl.pathandquery_paramscome from the request targetheaderscomes from the header linesbodyis the request body
The Lifecycle of an HTTP Request
Inside the backend, the request usually goes through steps like:
- Network stack reads raw bytes from the connection
- HTTP parser identifies:
- Request line
- Headers
- Body
- Framework converts them into objects:
request.method,request.path,request.headers, etc.- Routing decides which handler function to call
- Handler reads data from the request and produces a response
You will see these steps again in later chapters about frameworks and routing.
Common Mistakes and Gotchas
As a beginner, watch out for these issues.
Forgetting the Blank Line Before the Body
If you write raw HTTP manually:
POST /data HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 20
{"value": 123}This is incorrect because there is no blank line before the body.
Correct:
POST /data HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 20
{"value": 123}
Headers and body must be separated by a single blank line.
No blank line means the server thinks your body is part of the headers.
Incorrect Content-Type
If you send JSON but mark it as form data:
POST /api HTTP/1.1
Content-Type: application/x-www-form-urlencoded
{"name": "Alice"}
The server will try to parse {"name": "Alice"} as form data, which fails.
Correct:
Content-Type: application/jsonMismatched Content-Length
If Content-Length does not match the real body size, the server might:
- Wait forever for more data
- Truncate the body
- Return an error
Normally your HTTP client sets Content-Length correctly for you.
Practice: Read and Analyze Requests
To become comfortable, practice by reading HTTP requests and answering:
- What method is used?
- What resource is requested (path)?
- Are there query parameters? Which ones?
- Is there a body? What format?
- Which headers look important?
Example 1:
GET /search?q=backend+developer&limit=5 HTTP/1.1
Host: www.example.com
Accept: text/html- Method:
GET - Path:
/search - Query:
q=backend+developer,limit=5 - No body
- Accepts HTML
Example 2:
PATCH /api/users/42 HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer abc123
Content-Length: 27
{"email": "new@example.com"}- Method:
PATCH - Path:
/api/users/42 - Body: JSON with email field
- Auth header: probably a token
- Content-Type matches body
You will learn how to implement these endpoints in later chapters, but being able to read them correctly is the first step.
Summary
- An HTTP request is a structured message from client to server.
- It has three main parts:
- Request line: method, target, version
- Headers: key-value pairs, one per line
- Body: optional data payload
- The blank line separates headers from body.
- Methods, status codes, headers, cookies, and sessions are all connected to HTTP requests, but each has its own chapter.
- As a backend developer, you will constantly:
- Inspect
method,path,query,headers,body - Route requests based on method + path
- Parse body according to
Content-Type
In the next chapters, you will dive deeper into HTTP responses, methods, status codes, and headers, all of which build on your understanding of HTTP requests.
Views: 7
KAHIBARO