Web Development: HTML, CSS and JavaScript
Exit

Lesson 1 of 17 · HTML and CSS

How the web works: client, server, DNS, HTTP and browser

40 min Node.js 22 (Debian, git, npm, python3)

Objective

Understand, step by step, what happens between the moment a customer types www.riad-yasmine.ma in their browser and the moment the page appears. You will learn to read a URL, explain the role of DNS, describe an HTTP request and response, and use the browser's developer tools and curl to observe all of this.

Key points

  • The web works on a client / server model: the browser (client) asks, the server answers. The server never speaks first.
  • A URL breaks down into protocol, hostname, port, path, parameters and anchor.
  • DNS translates a name (www.riad-yasmine.ma) into an IP address (196.200.x.x), like a phone book.
  • HTTP is a text dialogue: a request (method + path + headers) and a response (status code + headers + body).
  • HTTPS = HTTP encrypted with TLS: nobody between the client and the server can read or change the exchange.
  • The developer tools (F12 key) let you see every request, the HTML, the CSS and JavaScript errors.

1. Page, site, server, search engine

Four words that people often confuse:

Term What it is Example
Web page a document displayed by the browser, at a specific address the "Our rooms" page
Website a set of linked pages under the same domain name all of riad-yasmine.ma
Web server the computer (and the software) that stores the site and answers requests a VPS in Casablanca running nginx
Search engine a site that helps you find other pages Google, Bing

A browser (Firefox, Chrome, Edge, Safari) is the client: it fetches the pages and draws them on the screen.

2. The client / server model

Picture the "Dar Atay" café in Fez. The customer (you) places an order with the waiter (the server). The waiter goes to the kitchen and comes back with mint tea… or tells you "sorry, there is none left". The web follows exactly this pattern:

 Browser (client)                             Web server
 ────────────────                             ──────────
 1. "Give me /chambres.html"       ───────▶
                                   ◀───────   2. "Here is the file (200 OK)"
 3. reads the HTML, finds style.css,
    patio.jpg, app.js
 4. "Give me /style.css"           ───────▶
                                   ◀───────   5. "Here is the CSS"
 ... one request per resource ...

A single displayed page often means dozens of requests: the HTML first, then each stylesheet, each image, each script, each font.

3. Reading a URL

https://www.riad-yasmine.ma:443/chambres/suite-atlas.html?lang=fr&nuits=3#tarifs
└─┬──┘   └───────┬─────────┘└┬┘└────────────┬─────────┘ └──────┬──────┘ └─┬──┘
protocol     hostname      port          path             parameters    anchor
Part Role
https the protocol: how to talk to the server (http or https)
www.riad-yasmine.ma the hostname: which server to contact
:443 the port; often omitted because it is implicit (80 for http, 443 for https)
/chambres/suite-atlas.html the path: which resource on this server
?lang=fr&nuits=3 the parameters (key=value pairs separated by &)
#tarifs the anchor: a location inside the page; it is never sent to the server

In JavaScript (you will see it in level 2), the URL object does this splitting for you:

const u = new URL("https://www.riad-yasmine.ma/chambres.html?lang=fr");
u.hostname;                 // "www.riad-yasmine.ma"
u.pathname;                 // "/chambres.html"
u.searchParams.get("lang"); // "fr"

4. DNS: the directory of the web

Computers find each other through IP addresses (196.200.131.10, or in IPv6 2a01:4f8::1). Humans prefer names. DNS (Domain Name System) does the translation.

When you visit www.riad-yasmine.ma for the first time:

  1. the browser looks in its cache; then the system looks at the file /etc/hosts (Linux) or C:\Windows\System32\drivers\etc\hosts (Windows);
  2. otherwise, it queries the DNS resolver of your provider (Maroc Telecom, inwi, Orange) or a public resolver;
  3. the resolver asks the root servers, which send it to the .ma servers (managed by ANRT), which send it to the DNS servers of the riad-yasmine.ma domain;
  4. these servers give the final answer: the IP address. It is kept in cache for a certain time (the TTL).

The most common DNS records:

Type Role Example
A name → IPv4 address www A 196.200.131.10
AAAA name → IPv6 address www AAAA 2a01:4f8::1
CNAME alias to another name boutique CNAME shops.exemple.com
MX mail server for the domain @ MX 10 mail.riad-yasmine.ma
TXT free text (verifications, SPF…) @ TXT "v=spf1 mx -all"

To query DNS from a terminal:

nslookup www.riad-yasmine.ma        # Windows, Linux, macOS
dig +short www.riad-yasmine.ma      # Linux (dnsutils / bind-utils package)
getent hosts localhost              # what the system sees, including /etc/hosts

5. HTTP: the request

Once the IP is known, the browser opens a connection (TCP, port 443 for https) and sends an HTTP request. It is plain text:

GET /chambres.html HTTP/1.1
Host: www.riad-yasmine.ma
User-Agent: Mozilla/5.0 (Windows NT 10.0) Firefox/131.0
Accept: text/html
Accept-Language: fr-MA,fr;q=0.9,ar;q=0.8
  • the request line: the method, the path, the version;
  • the headers: one piece of information per line, Name: value. Host is mandatory in HTTP/1.1, because one server often hosts several sites;
  • an empty line, then optionally a body (to send a form, for example).

The main methods:

Method Use Example
GET read a resource display the list of rooms
POST create / send data submit the booking form
PUT / PATCH replace / modify change the dates of a booking
DELETE delete cancel a booking
HEAD like GET, but without the body check that a page exists

6. HTTP: the response and status codes

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 5120
Cache-Control: max-age=600

<!doctype html>
<html lang="fr"> ...

The status code (3 digits) summarizes the result. The first digit gives the family:

Family Meaning Codes to know
2xx success 200 OK, 201 Created, 204 No Content
3xx redirection 301 Moved Permanently, 302 Found, 304 Not Modified
4xx client error 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found
5xx server error 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable

Remember the rule: 4xx = the request is the problem (wrong address, no permission), 5xx = the server crashed. When the handicraft shop shows a blank page with a 500, there is no point checking the address: you must read the server logs.

The Content-Type header indicates the type of the body: text/html, text/css, application/javascript, image/webp, application/json… The browser uses it to know what to do with the content.

7. HTTPS: the padlock

With plain HTTP, everything travels in clear text: on a café's Wi-Fi, a malicious neighbour could read the password typed on your site or modify the page. HTTPS adds an encryption layer (TLS):

  • the server presents a certificate that proves its identity (issued by an authority, for example Let's Encrypt, which is free);
  • the browser and the server agree on a secret key;
  • the rest of the exchange is encrypted.

Today, browsers mark a site without HTTPS as "Not secure". It ranks lower in search engines, and some features (geolocation, notifications…) are blocked on it. Every site must use HTTPS, even a simple showcase site.

8. What the browser does with the response

Receiving the HTML is only the beginning. The browser:

  1. parses the HTML and builds a tree of objects, the DOM (Document Object Model);
  2. discovers the linked resources (<link>, <img>, <script>) and requests them;
  3. parses the CSS and computes the style of each element;
  4. computes the layout (position and size of each box);
  5. paints the pixels on the screen;
  6. runs the JavaScript, which can modify the DOM… and trigger a new layout calculation.

This is why the order and the size of files matter: a large script placed at the top of the page blocks rendering (lesson 4.2).

9. The browser's developer tools

Press F12 (or right-click → "Inspect") in Firefox, Chrome or Edge. The essential tabs:

Tab What it is for
Elements / Inspector see the DOM and the applied CSS, edit them live
Console read JavaScript errors, type JS code
Network see every request: method, status, size, duration, headers
Application / Storage cookies, localStorage (lesson 3.3)
Lighthouse performance and accessibility audit (lesson 4.2)

Exercise to do on your computer: open a Moroccan website you know, go to the Network tab and reload (Ctrl+F5). Find the first request (the HTML), its status code and its Content-Type, then count the images. Tick "Disable cache" and choose a "3G" throttling profile: you will see what customers experience on a slow mobile network.

10. Observing HTTP on the command line with curl

curl is the web developer's Swiss Army knife: it sends HTTP requests from the terminal.

curl http://127.0.0.1:8080/                 # shows the body (the HTML)
curl -i http://127.0.0.1:8080/              # -i: headers + body
curl -I http://127.0.0.1:8080/              # -I: HEAD request, headers only
curl -v http://127.0.0.1:8080/              # -v: the whole dialogue (> sent, < received)
curl -L http://127.0.0.1:8080/promo         # -L: follow redirects
curl -X POST -d "nom=Amina" http://127.0.0.1:8080/reserver   # send data

With -v, lines starting with > are what you send, and lines starting with < are what the server answers. This is exactly what the browser's Network tab shows.

11. A mini web server in Node.js

During development, you run a server on your own machine. It listens on the address 127.0.0.1 (or localhost), which always means "myself". Here is the core of the server provided in the lab:

const http = require("http");
const serveur = http.createServer((req, res) => {
  if (req.url === "/") {
    res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
    res.end("<h1>Bienvenue au Riad Yasmine</h1>");
  } else {
    res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
    res.end("Page introuvable");
  }
});
serveur.listen(8080, "127.0.0.1");

You do not need to understand every line yet. Remember that a web server receives a request (req), chooses a status code and headers, then sends a body (res.end). Nginx, Apache or Express do the same thing, with many more features.

node serveur.js &                  # start the server in the background
curl -i http://127.0.0.1:8080/     # test it
kill %1                            # stop it (or: kill PID)

Common pitfalls

  • Confusing 4xx and 5xx: a 404 comes from a wrong address or a missing file; a 500 comes from an error in the server code.
  • Forgetting that the cache exists: after a change, the browser may show the old version. Reload with Ctrl+F5 or tick "Disable cache" in the Network tab.
  • Thinking the anchor (#tarifs) is sent to the server: it stays in the browser.
  • Changing a DNS record and expecting an immediate effect: old answers stay in cache for the TTL (sometimes several hours).

Lab

A minimal web server for Riad Yasmine is ready in /root/web/serveur.js. You will:

  1. write an HTTP request by hand in a file, to learn its format well;
  2. start the server in the background and save the headers of its response with curl -I;
  3. observe a 301 redirect and its Location header;
  4. trigger a 404 error and save the full response.

Tip: when the server runs in the background, it prints each request it receives in the terminal. Stop it with kill %1 when you are done.

Quiz

  1. What are the parts of the URL https://boutique-fes.ma/tapis?couleur=rouge#avis?
  2. What is DNS used for?
  3. What do the codes 301, 404 and 500 mean?
  4. Why is the Host header essential in an HTTP/1.1 request?
  5. Which developer tools tab do you use to find out why an image is not displayed?
Answers
  1. Protocol https, hostname boutique-fes.ma, path /tapis, parameter couleur=rouge, anchor avis (port 443 is implicit).
  2. To translate a domain name into an IP address, so that the browser knows which server to contact.
  3. 301: the resource has moved permanently (the Location header gives the new address); 404: resource not found; 500: internal server error.
  4. Because one IP address often hosts several sites: Host tells the server which one you are requesting.
  5. The Network tab: it shows the image request, its status code (404?) and its exact address. The console also often reports the error.

Reference sources: MDN Web Docs in French (CC BY-SA 2.5 license). Original MasterLinux text.

Practical exercises

To do on Node.js 22 (Debian, git, npm, python3)

The online terminal is coming soon. Meanwhile, do these tasks on your own Linux machine, a virtual machine or WSL.

  1. Write in /root/web/requete.txt the HTTP request that a browser would send to get the page /chambres.html from the site www.riad-yasmine.ma: first the request line (GET method, path, HTTP/1.1 version), then the Host header on the next line.
    Show a hintprintf '%s\n' 'GET /chambres.html HTTP/1.1' 'Host: www.riad-yasmine.ma' > /root/web/requete.txt
    Show the solution
    printf "%s\n" "GET /chambres.html HTTP/1.1" "Host: www.riad-yasmine.ma" "Accept: text/html" > /root/web/requete.txt

    Check : grep -q "^GET /chambres.html HTTP/1.1" /root/web/requete.txt && grep -qi "^host: *www.riad-yasmine.ma" /root/web/requete.txt

  2. Start the provided server in the background (node /root/web/serveur.js &), then save in /root/web/entetes.txt the status line and the response headers for the home page http://127.0.0.1:8080/.
    Show a hintcurl -I (or curl -i) shows the status line and the headers: curl -sI http://127.0.0.1:8080/ > /root/web/entetes.txt
    Show the solution
    node /root/web/serveur.js >/dev/null 2>&1 & p=$!; sleep 1; curl -sI http://127.0.0.1:8080/ > /root/web/entetes.txt; kill $p

    Check : grep -q "^HTTP/1.1 200" /root/web/entetes.txt && grep -qi "^content-type: *text/html" /root/web/entetes.txt

  3. The old page /promo-ramadan has moved. Save in /root/web/redirection.txt the server response for this address (status and headers): it must show the redirect code and the Location header.
    Show a hintDo not follow the redirect: use curl -sI without the -L option.
    Show the solution
    node /root/web/serveur.js >/dev/null 2>&1 & p=$!; sleep 1; curl -sI http://127.0.0.1:8080/promo-ramadan > /root/web/redirection.txt; kill $p

    Check : grep -q "^HTTP/1.1 301" /root/web/redirection.txt && grep -qi "^location: */offres.html" /root/web/redirection.txt

  4. Save in /root/web/introuvable.txt the full server response (headers AND body) for the address http://127.0.0.1:8080/chambre-inexistante.
    Show a hintcurl -si shows the headers, then the response body.
    Show the solution
    node /root/web/serveur.js >/dev/null 2>&1 & p=$!; sleep 1; curl -si http://127.0.0.1:8080/chambre-inexistante > /root/web/introuvable.txt; kill $p

    Check : grep -q "^HTTP/1.1 404" /root/web/introuvable.txt && grep -q "Page introuvable" /root/web/introuvable.txt

Official references consulted: Comment fonctionne le Web — https://developer.mozilla.org/fr/docs/Learn_web_development/Getting_started/Web_standards/How_the_web_works ; Comment les navigateurs chargent les sites web — https://developer.mozilla.org/fr/docs/Learn_web_development/Getting_started/Web_standards/How_browsers_load_websites ; Naviguer sur le Web — https://developer.mozilla.org/fr/docs/Learn_web_development/Getting_started/Environment_setup/Browsing_the_web ; Installation des outils de base — https://developer.mozilla.org/fr/docs/Learn_web_development/Getting_started/Environment_setup/Installing_software. Original MasterLinux text.