HTTP and REST in Brief
20 min · Intermediate
Need help? Ask a tutor on WhatsApp (opens in a new tab)Every web app and phone app talks to a server in the same way. The app sends a request and the server sends back a response. This lesson shows what travels in each, so the backend code in the next lessons makes sense.
A request and a response
HTTP is the set of rules a client and a server follow to talk. The client sends a request with a method, a path and headers. The server sends back a status code, headers and usually a body.
The client asks and the server answers. Both are plain text sent over HTTP. A request names what the client wants; a response says how it went and carries the data.
GET /products/7 HTTP/1.1Host: shop.example.comAccept: application/jsonHTTP/1.1 200 OKContent-Type: application/json{"id": 7, "name": "Notebook"}Example 1 · Taking a URL apart
from urllib.parse import parse_qs, urlsplit
url = "https://shop.example.com/products?max_price=100&limit=5"parts = urlsplit(url)print(parts.scheme)print(parts.netloc)print(parts.path)print(parse_qs(parts.query))https
shop.example.com
/products
{'max_price': ['100'], 'limit': ['5']}What this code does
urlsplitcuts a URL into scheme, host, path and query.parse_qsturns the query text into a dictionary. Every value is a list of strings, even a single one.- A server sees the same parts. Your route reads the path and the query to decide what to do.
Example 2 · Reading a raw request
request = """POST /orders HTTP/1.1Host: shop.example.comContent-Type: application/json
{"product_id": 7, "quantity": 2}"""
head, body = request.split("\n\n")request_line, *header_lines = head.splitlines()method, path, version = request_line.split()headers = dict(line.split(": ") for line in header_lines)
print(method, path)print(headers["Content-Type"])print(body)POST /orders
application/json
{"product_id": 7, "quantity": 2}What this code does
- A request is plain text. A blank line separates the head from the body.
- The first line holds the method, the path and the HTTP version. Each header is a
name: valuepair. request_line, *header_lines = ...splits the head into its first line and all the rest.
The first three lines are the request: a method (GET), a path (/products/7) and headers. The rest is the response: a status (200 OK), headers and a body.
Methods say what to do
A status code is a three-digit number in every response that says how the request went. 2xx means success, 4xx means the caller made a mistake, and 5xx means the server failed.
The method is the verb of the request. Four of them cover almost every project: read, create, replace or change, and delete. The status code in the reply says whether it worked.
METHODS = { "GET": "read data", "POST": "create something new", "PUT": "replace something", "PATCH": "change part of something", "DELETE": "remove something",}for method, meaning in METHODS.items(): print(method, "->", meaning)Example 3 · Status codes by family
FAMILIES = {2: "success", 3: "redirect", 4: "client error", 5: "server error"}MEANINGS = {200: "OK", 201: "Created", 404: "Not Found", 422: "Invalid input"}
for code in (200, 201, 404, 422, 500): family = FAMILIES[code // 100] print(code, MEANINGS.get(code, "Internal Server Error"), "-", family)200 OK - success 201 Created - success 404 Not Found - client error 422 Invalid input - client error 500 Internal Server Error - server error
What this code does
- The first digit tells the family: 2 means it worked, 4 means the caller made a mistake, 5 means the server failed.
code // 100keeps only that first digit.MEANINGS.get(code, default)gives a fallback text for a code that is not in the dictionary.
GET never changes data, so it is safe to repeat. POST usually creates a new record each time it is sent.
REST: nouns in the URL, verbs in the method
A REST API is a web service whose URLs name things, such as /products/7, and whose HTTP methods say what to do with them. It sends and receives data as JSON.
REST is a habit for naming URLs. The path names a thing, such as /products. The method says what to do with it. So you never need paths like /getProduct or /deleteOrder.
GET /products list productsPOST /products create a productGET /products/7 read product 7PATCH /products/7 change product 7DELETE /products/7 delete product 7Example 4 · A real request with curl
Runs in: Your terminal
curl -i http://127.0.0.1:8000/products/7curl -i -X POST http://127.0.0.1:8000/products/7HTTP/1.1 200 OK
content-length: 26
content-type: application/json
{"id":7,"name":"Notebook"}
HTTP/1.1 405 Method Not Allowed
allow: GET
content-length: 31
content-type: application/json
{"detail":"Method Not Allowed"}What this code does
curlis a terminal tool that sends one request.-ialso shows the status line and the headers.- The first call asks for a product and gets
200with JSON. The second uses the wrong method, so the server answers405. - The address works once an API is running on your machine. The next lesson builds it.
One path with different methods gives you the full set of actions. Use plural nouns, and put the id at the end of the path.
Data travels as JSON
Request and response bodies are almost always JSON. A path says which thing; a query string such as ?limit=5 narrows a list; a body carries the data to create or change.
POST /orders HTTP/1.1Content-Type: application/json{"product_id": 7, "quantity": 2}HTTP/1.1 201 Created{"id": 31, "product_id": 7, "quantity": 2}The header Content-Type: application/json tells the server how to read the body. 201 Created tells the client a new record exists.
Next step
Check your understanding
10 quick questions