Build the mental model
This project has no new theory: it forces the URL-lifecycle lesson and the client/server mental model to run together against one concrete, messy URL — https://shop.example.com/products?category=shoes — instead of a bare domain.
- Browser (client): parses the URL into scheme, host, path, and query; checks its own caches; decides it needs an IP address.
- DNS resolver: another server whose one job is turning shop.example.com into an IP address.
- Server or CDN: everything after the TLS handshake — reading the request, deciding what /products?category=shoes means, building the response.
Query strings are not special
?category=shoes is not a separate protocol feature — it is just extra information the browser attaches to the request line for the server to read.
Naming exactly which host header goes out and exactly which query parameter the server sees is what makes the lifecycle click. For real TLS and CDN configuration beyond this course's scope, see the Cloud & Deployment tutorial.
REQUEST LIFECYCLE FOR ONE URL
-----------------------------
TRACE: https://shop.example.com/products?category=shoes
-----------------------------------------------------------
[Browser]
1. Parse URL -> host=shop.example.com path=/products
2. Check browser cache + DNS cache
|
v
[DNS Resolver]
3. Resolve shop.example.com -> IP address
|
v
[Network]
4. Open TCP connection to IP on port 443
|
v
[TLS]
5. TLS handshake (scheme is https)
|
v
[Browser]
6. Send GET /products?category=shoes
Host: shop.example.com
|
v
[Server / CDN for shop.example.com]
7. Request routed to CDN edge or origin server
8. Server responds: status + headers + HTML body
|
v
[Browser]
9. Parse HTML -> build DOM
10. Fetch CSS, JS, images referenced in the HTML
11. Render: DOM + CSSOM + JS -> pixels showing shoesConnect it to a real scenario
Work through the trace using only lessons you already have: the URL-lifecycle steps and the client/server roles.
Write the URL parts by hand
Before running any code, split shop.example.com/products?category=shoes into scheme, host, path, and query on paper.
Parse and check caches
Browser parses the URL and checks its own cache and DNS cache for shop.example.com.
DNS resolves the host
A DNS resolver translates shop.example.com into an IP address.
Open the TCP connection
Browser opens a TCP connection to that IP on port 443.
TLS handshake
Because the scheme is https, browser and server negotiate TLS before sending anything.
Send the HTTP request
Browser sends GET /products?category=shoes with a Host: shop.example.com header.
Server or CDN handles it
The request reaches the CDN edge or origin server in front of shop.example.com.
Server responds
Server returns a status code, headers, and an HTML body for /products.
Browser parses HTML
Browser builds the DOM from the response body.
Fetch subresources
Browser discovers and fetches CSS, JS, and images referenced in the HTML.
Render
DOM + CSSOM + JS produce the rendered page showing shoes.
Run traceRequest against the example URL and compare its output, line by line, against this list.
Try the working example
function traceRequest(rawUrl) {
const u = new URL(rawUrl);
const port = u.port || (u.protocol === 'https:' ? '443' : '80');
return [
`1. Parse URL - scheme=${u.protocol.replace(':', '')}, host=${u.hostname}, path=${u.pathname}, query=${u.search}`,
`2. Check caches - browser checks its cache and DNS cache for ${u.hostname}`,
`3. DNS resolution - resolve ${u.hostname} to an IP address`,
`4. TCP connect - open a TCP connection to the IP on port ${port}`,
`5. TLS handshake - ${u.protocol === 'https:' ? 'negotiate TLS because scheme is https' : 'skipped, scheme is http'}`,
`6. Send request - GET ${u.pathname}${u.search} with Host: ${u.hostname}`,
`7. Server/CDN - request reaches server or CDN in front of ${u.hostname}`,
`8. Server responds - status code, headers, and HTML body for ${u.pathname}`,
`9. Parse HTML - browser builds the DOM from the response body`,
`10. Fetch assets - browser fetches CSS, JS, images referenced in the HTML`,
`11. Render page - DOM + CSSOM + JS produce pixels for category=${u.searchParams.get('category')}`,
];
}
const result = traceRequest('https://shop.example.com/products?category=shoes');
result.forEach((line) => console.log(line));Running traceRequest('https://shop.example.com/products?category=shoes') prints these 11 steps in order:
1. Parse URL - scheme=https, host=shop.example.com, path=/products, query=?category=shoes
2. Check caches - browser checks its cache and DNS cache for shop.example.com
3. DNS resolution - resolve shop.example.com to an IP address
4. TCP connect - open a TCP connection to the IP on port 443
5. TLS handshake - negotiate TLS because scheme is https
6. Send request - GET /products?category=shoes with Host: shop.example.com
7. Server/CDN - request reaches server or CDN in front of shop.example.com
8. Server responds - status code, headers, and HTML body for /products
9. Parse HTML - browser builds the DOM from the response body
10. Fetch assets - browser fetches CSS, JS, images referenced in the HTML
11. Render page - DOM + CSSOM + JS produce pixels for category=shoes5-minute try-it
Pick a different real-looking URL (e.g. https://api.example.com/v2/users/42?include=orders) and hand-trace all 11 steps yourself before running traceRequest on it to check your work.
One important caution
Treating DNS resolution and TLS handshake as the same step — they are separate network round trips
Assuming the query string changes which protocol is used, instead of just changing what the server does with the path
MDN — URL API — How the Web Works