HTTP Requests
Table of Contents
- HTTP Is Just Text
- The Request Line
- Methods: What You Want to Do
- Safe and Idempotent
- Headers: Extra Information
- The Body
- Sending Requests with curl
- Reading a Request in DevTools
- Try It Yourself
1. HTTP Is Just Text
The connection from chapter 4 is open. Now the browser sends its request — and here's the surprising part: an HTTP request is a few lines of plain text. Here's what your browser sends when you open your GitHub Pages site:
GET /my-site/ HTTP/1.1
Host: dara-sok.github.io
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/130.0
Accept: text/html,application/xhtml+xml
Accept-Language: km-KH,km;q=0.9,en;q=0.8
Accept-Encoding: gzip, br
Connection: keep-alive
That's the whole thing. HTTP — the HyperText Transfer Protocol — is a set of rules for what those lines must look like. Every request has the same shape:
1. Request line GET /my-site/ HTTP/1.1
2. Headers Host: …, User-Agent: …, …
3. A blank line (marks the end of the headers)
4. Body (optional) data being sent, e.g. a form
(HTTP/2 and HTTP/3 send the same information in a compact binary form
instead of text, but the meaning is identical. DevTools and curl show
it to you as text either way.)
2. The Request Line
The first line has three parts:
GET /my-site/ HTTP/1.1
│ │ └── which version of HTTP
│ └──────────── which resource: the path (+ query) from the URL
└──────────────────── the method: what you want to do with it
Notice what's not there: the scheme and host aren't in this line (the host has its own header, next to it), and the fragment from chapter 2 isn't anywhere — the browser never sends it.
3. Methods: What You Want to Do
The method is a verb. The path says which resource; the method says what to do with it. These are the ones you'll use:
| Method | Means | Example |
|---|---|---|
| GET | Give me this resource | Open a page, load an image, fetch a list of products |
| POST | Here's some new data — process it | Submit a sign-up form, create an order, upload a photo |
| PUT | Replace this resource with what I'm sending | Save a whole edited profile |
| PATCH | Change part of this resource | Update just your phone number |
| DELETE | Remove this resource | Delete a comment |
There are a few more — HEAD (like GET, but send only the headers) and OPTIONS (what am I allowed to do here?) are the ones you'll meet, the second one in chapter 10.
When you click a link or type a URL, the browser always uses GET.
When you submit a form, it usually uses POST. The others are used
mostly by JavaScript and by apps talking to APIs — you'll write them
yourself in the NestJS Crash Course, where a controller has a separate
function for @Get(), @Post(), @Patch(), and @Delete() on the
same path.
4. Safe and Idempotent
Two words describe what a method promises:
- Safe: it doesn't change anything on the server. GET and HEAD are safe — loading a page shouldn't delete your account.
- Idempotent: doing it twice has the same effect as doing it once. GET, PUT, and DELETE are idempotent. Deleting comment 7 twice still leaves comment 7 deleted.
POST is neither. Submitting an order form twice can create two orders. That's why your browser warns "Confirm form resubmission" when you refresh a page you got from a POST, and why payment APIs, like the ABA PayWay ones in this site's tutorials, take care to avoid charging someone twice.
The rule for when you build things: never use GET for something that changes data. Browsers, search engines, and link previews all feel free to send GET requests whenever they like, assuming nothing will change.
5. Headers: Extra Information
After the request line come headers: one per line, written as
Name: value. They carry everything else the server might need to
know. Header names aren't case-sensitive. The common ones:
| Header | What it tells the server |
|---|---|
| Host | Which website you want (required) |
| User-Agent | Which browser or program is asking |
| Accept | Which kinds of content you can handle — HTML, JSON, images… |
| Accept-Language | Which languages you prefer, in order |
| Accept-Encoding | Which compression formats you understand |
| Cookie | Data the server asked you to remember (chapter 8) |
| Authorization | Proof of who you are, like a token (Keycloak tutorial) |
| Content-Type | What kind of data is in the body (when there is one) |
| Referer | Which page linked you here (yes, it's spelled wrong — since 1996) |
Why is Host required? Because one server computer — one IP address
— often hosts thousands of websites. All GitHub Pages sites share
the same few IP addresses. The Host header is the only way GitHub's
server knows you want dara-sok.github.io and not someone else's site.
The q=0.9 in Accept-Language: km-KH,km;q=0.9,en;q=0.8 is a
preference weight from 0 to 1: "Khmer (Cambodia) first, then any
Khmer, then English." A site that supports several languages can use it
to pick one for you.
6. The Body
GET requests have no body — everything they need is in the URL. POST,
PUT, and PATCH usually do. The Content-Type header says how to read
it. You'll see two kinds most often.
A classic HTML form sends its fields like a query string:
POST /signup HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 38
name=Dara+Sok&email=dara%40example.com
An app or JavaScript calling an API usually sends JSON:
POST /api/orders HTTP/1.1
Host: shop.example.com
Content-Type: application/json
Content-Length: 32
{"productId": 42, "quantity": 2}
Content-Length says how many bytes the body has, so the server knows
where it ends. Notice the blank line between the headers and the body —
that's how the server knows the headers are over.
Remember from chapter 4: with HTTPS, all of this — headers and body — is encrypted. With plain HTTP, that email address is readable by everyone on the way.
7. Sending Requests with curl
curl lets you write requests by hand. Some options you'll use all the
time:
curl https://example.com # GET, print the body
curl -v https://example.com # also show request + response headers
curl -I https://example.com # HEAD: headers only
curl -X POST https://example.com/api # use a different method
curl -H "Accept-Language: km" https://example.com # add a header
curl -d "name=Dara" https://example.com/signup # send a body (implies POST)
With -v, lines starting with > are what you sent, and lines
starting with < are what came back:
> GET /my-site/ HTTP/2
> Host: dara-sok.github.io
> User-Agent: curl/8.7.1
> Accept: */*
>
< HTTP/2 200
< content-type: text/html; charset=utf-8
< …
Look how short curl's request is compared with a browser's. Accept: */* means "I'll take anything." Servers don't need all those extra
headers; browsers send them to get the best version of a page.
Practise safely: the site
https://httpbin.orgexists for exactly this. It echoes back whatever you send it, so you can try any method without breaking anything.curl https://httpbin.org/getshows you your own request, as the server saw it.
8. Reading a Request in DevTools
In the browser:
- Open DevTools → Network and reload the page.
- Click a request in the list.
- The Headers tab shows the URL, the method, and the status code at the top (under General), then Response Headers, then Request Headers.
- For a POST, the Payload tab (Chrome/Edge) or Request tab (Firefox) shows the body.
Two things worth turning on: right-click the column headers in the request list and add the Method column, and tick Preserve log at the top so the list isn't cleared when a form submission takes you to a new page.
Developers spend a lot of time here. When an app "doesn't work", the first question is almost always: what request did it actually send?
9. Try It Yourself
-
See your own request. Run
curl https://httpbin.org/headers. Then open the same address in your browser. Compare the headers. How many more does the browser send? -
Try other methods.
curl -X POST https://httpbin.org/post -d "name=Dara" curl -X DELETE https://httpbin.org/delete curl -X POST https://httpbin.org/post \ -H "Content-Type: application/json" \ -d '{"productId": 42, "quantity": 2}'In each reply, find where httpbin shows the body it received.
-
Ask for another language. Run
curl -I -H "Accept-Language: km" https://www.google.comand then again withen. Do the response headers change? -
Watch a form. On any site with a search box, open DevTools → Network, tick Preserve log, and search for something. Find the request. Was it GET or POST? Where did your search term go — the URL or the body?
The request has been sent. Next: what the server sends back, and what all those numbers like 200 and 404 mean.
Buy Me a Coffee
Found this tutorial helpful? Consider buying me a coffee to support more free content!