MAD Study Hub

Home / MAD1 / Week 1

Week 1 · How the web works: clients, servers, URLs and HTTP

Official syllabus line: Basic terminologies of Web
About 90 minQuiz 1 material (see exam radar)BSCS2003 (+ project BSCS2003P) · Thejesh G N, Nitin Chandrachoodan
Before you start: Nothing. You should have seen Python functions and dictionaries in the foundation courses.

The one-minute story

Think of it like this

The web is a restaurant. You (the client, in practice your browser) sit at a table and hand over an order slip: "one plate of /menu/pizza, please". The kitchen (the server) reads the slip, cooks, and sends the plate back with a note on top: "served" (200), "we do not have that" (404), or "kitchen on fire" (500).

The roads between the table and the kitchen are the internet. The restaurant itself, with its menu pages and plates, is the web. The kitchen has an address (IP address), a phone book entry that turns the restaurant name into that address (DNS), and several doors for different kinds of visitors (ports).

The waiter has a bad memory: every time you speak, he treats you like a stranger. That is why HTTP is stateless and why websites hand you a little cookie token to prove who you are.

By the end of this week you can:

  • explain what happens between typing a URL and seeing a page;
  • split any URL into scheme, host, port, path, query string and fragment;
  • read an HTTP request and response and name the method, headers, body and status code;
  • choose the right HTTP method and status code for a situation;
  • calculate requests per second, bandwidth (Mbps) and RAM needs, which the papers love;
  • predict what a tiny Flask route returns for a given URL (200, 404, 405 or 400).

Words you need

Words you need
  • Internet - the global network of connected computers (the roads).
  • Web (WWW) - the collection of pages and apps you reach over the internet using HTTP (the shops on the roads).
  • Client - the program that asks for something (browser, mobile app, curl).
  • Server - the program (and the machine) that waits for requests and answers them.
  • IP address - the number address of a machine, like 142.250.77.46 (IPv4) or ::1 (IPv6). 127.0.0.1 means "this very computer".
  • DNS - the Domain Name System, the phone book that turns example.com into an IP address.
  • Port - a numbered door on a machine. Web uses 80 (http) and 443 (https). Flask's dev server uses 5000.
  • URL - the full address of a resource on the web.
  • HTTP - the set of rules (protocol) clients and servers use to talk. HTTPS is HTTP with encryption.
  • Request / response - one message from the client, one message back from the server.
  • Status code - a three-digit number in the response saying how it went.
  • Stateless - the server keeps no memory between two requests.
  • Cookie - a small piece of text the server asks the browser to store and send back.
  • Static / dynamic page - a ready-made file versus a page built by code on each request.
  • Bandwidth / latency - how much data per second a link carries / how long one trip takes.

Idea 1: Internet, web, clients and servers

The internet is the physical and logical network (cables, routers, IP). The web is one service that runs on it. Email and file transfer also use the internet but are not "the web".

A client starts the conversation and a server answers. These are roles, not machines: your laptop can run a Flask server and a browser at the same time, and then talk to itself.

What happens when you type http://example.com/hello and press Enter?

  1. The browser asks DNS for the IP address of example.com.
  2. It opens a connection to that IP address on the right port (80 for http, 443 for https).
  3. It sends an HTTP request: "GET /hello".
  4. The server runs some code (or reads a file) and sends an HTTP response: status, headers, body.
  5. The browser reads the HTML body, finds more files it needs (CSS, images, JavaScript), requests those too, and renders the page.
The idea

One request, one response. HTTP is request-response: the client always speaks first. The server cannot push a page to the browser unasked.

Web server versus web application. A web server (Apache, Nginx) accepts connections and serves files. A web application (your Flask code) decides what to send. Flask ships with a small development server so you can test locally; real sites put it behind a stronger one.

Static versus dynamic.

Static pageDynamic page
ContentA fixed file on diskBuilt by code on every request
Same for all users?YesCan differ (your name, today's date, database rows)
Exampleabout.htmlYour marks page
Needs a program?No, only a file serverYes (Flask, a database)

You can serve static files with one command in a folder that has index.html:

python -m http.server 8000

Now open http://localhost:8000/ in the browser. Python sends index.html for /, and any other file by its path. Press Ctrl+C to stop. The server prints one line per request, for example "GET /index.html HTTP/1.1" 200 -.

Your turn: 1. Roles

You run python app.py (a Flask app on port 5000) and then open http://127.0.0.1:5000 in Chrome on the same laptop. Who is the client, who is the server, and which IP address is used?

Need a hint?

Think about who sends the request.

Show the full solution

Chrome is the client, the Flask program is the server. They share one machine, so the address 127.0.0.1 (the loopback address, "this computer") is used.

Idea 2: Anatomy of a URL

Take this URL:

https://shop.example.com:8443/books/list?genre=sci-fi&page=2#reviews
PartValueMeaning
SchemehttpsThe protocol to use
Hostshop.example.comWhich machine (a domain name or an IP)
Port8443Which door. Omitted means the default (80 for http, 443 for https)
Path/books/listWhich resource on that server
Query stringgenre=sci-fi&page=2Extra name=value pairs, joined by &, after ?
FragmentreviewsA spot inside the page, handled by the browser only
The idea

The fragment (after #) is never sent to the server. The browser uses it to scroll to an element with that id. Everything else reaches the server.

Python can split a URL for you, which is a safe way to check your answer:

from urllib.parse import urlparse, parse_qs

u = urlparse("https://shop.example.com:8443/books/list?genre=sci-fi&page=2#reviews")
print(u.scheme, u.hostname, u.port)
print(u.path)
print(parse_qs(u.query))
print(u.fragment)

Output:

https shop.example.com 8443
/books/list
{'genre': ['sci-fi'], 'page': ['2']}
reviews

Notice that every query value is a string ('2', not 2), and a key can repeat (?tag=a&tag=b), so parse_qs gives lists.

Path parameter versus query parameter. These are two different ways to send a value, and the exam tests the difference constantly. In Flask:

from flask import Flask, request
app = Flask(__name__)

@app.route("/greet/<name>")          # value lives in the PATH
def greet(name):
    return f"Hi {name}"

@app.route("/search")                # value lives in the QUERY STRING
def search():
    return "q=" + request.args.get("q", "nothing")

I ran this app. The results:

URLResult
/greet/RiaHi Ria (200)
/greet/Not Found (404): the path variable is missing
/greet?name=RiaNot Found (404): wrong place, it is not a query route
/searchq=nothing
/search?q=flaskq=flask
/search?qq= (the key is present with an empty value, so the default is NOT used)
Watch out - real exam trap
  • <name> in the route is a path value; request.args reads the query string. They never replace each other.
  • /greet/ with nothing after the slash does not match /greet/<name>. Result: 404, not "Hi None".
  • request.args.get("q", "default") returns the default only when the key is missing; for ?q the key exists with value "".
  • <int:number> accepts only whole numbers. /validate/abc for <int:number> is a 404, not a 400.

Idea 3: HTTP request and response

An HTTP message is plain text. A request has a start line, headers, an empty line, and an optional body:

POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Cookie: session=abc123

uname=ria&pwd=secret

A response looks similar, with a status line first:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Set-Cookie: theme=dark; Path=/
Content-Length: 31

<h1>Welcome, ria</h1>
PieceRequestResponse
First linemethod, path, versionversion, status code, reason
HeadersHost, Content-Type, Cookie, Accept, User-AgentContent-Type, Set-Cookie, Location, Content-Length
Bodyform data or JSON (POST/PUT/PATCH)the HTML, JSON or file

Content-Type is the label on the parcel. text/html means "show it as a page"; application/json means "this is data". Flask's jsonify(...) returns status 200 and the mimetype application/json, which is a favourite exam fact.

Try it with curl, a command-line client (-i shows the headers, -X picks the method, -H adds a header, -d sends a body):

curl -i http://127.0.0.1:5000/api/courses
curl -X POST http://127.0.0.1:5000/api/course -H "Content-Type: application/json" -d '{"id": "CS1001"}'

HTTP methods

MethodMeaningHas a body?Safe (does not change data)?Typical use
GETRead a resourceNoYesOpen a page, fetch a list
POSTCreate something / submit a formYesNoSign up, add a row
PUTReplace a whole resourceYesNoOverwrite a record
PATCHChange part of a resourceYesNoUpdate one field
DELETERemove a resourceUsually noNoDelete a record
HEADLike GET but headers onlyNoYesCheck if a file exists
Watch out - real exam trap
  • GET is not the same as HEAD. GET returns headers and body; HEAD returns the headers only.
  • A browser address bar always sends GET. You cannot send POST by typing a URL.
  • Putting secrets in a GET query string is bad: URLs are stored in history and logs.
  • GET responses may be cached by the browser; POST responses are not cached by default. "Browsers cache all GET and POST requests" is false.

Status code families

FamilyMeaningCodes you must know
1xxInformational100 Continue
2xxSuccess200 OK, 201 Created, 204 No Content
3xxRedirection301 Moved Permanently, 302 Found (temporary), 304 Not Modified
4xxClient error (your request is wrong)400 Bad Request, 401 Unauthorized (not logged in), 403 Forbidden (logged in but not allowed), 404 Not Found, 405 Method Not Allowed
5xxServer error (the server's code failed)500 Internal Server Error, 503 Service Unavailable

I checked these in Flask: redirect(url_for("home")) gives 302 with a Location: / header; abort(403) gives 403; a missing route gives 404; calling a POST-only route with GET gives 405; returning "saved", 201 gives 201.

Solved example: 1. Predict the status and the page

Question. Flask app, running on http://127.0.0.1:5000:

from flask import Flask, abort

app = Flask(__name__)
users = ["admin", "user_1"]

@app.route("/home/<username>", methods=["POST"])
def home(username):
    if username in users:
        return f"Hello {username}"
    abort(407)

@app.errorhandler(404)
def nf(e):
    return "The user you are looking for is invalid."

@app.errorhandler(405)
def bad_method(e):
    return "Please check the web request."

What does the browser show for http://127.0.0.1:5000/home/user_4?

Solution.

  1. The URL matches the pattern /home/<username>, so it is not a 404.
  2. The address bar sends GET, but the route allows only POST. Flask answers 405 before the function runs.
  3. The 405 error handler returns its text.

Answer: Please check the web request. (If you had guessed "invalid user" you ignored the method; the function body never ran, so abort(407) is never reached.)

abort and errorhandler. abort(400, "message") stops the function and sends that error. @app.errorhandler(404) replaces the default error page for that code. When the argument is missing, Flask raises 400 for request.args["uid"] (dictionary-style access) but returns None for request.args.get("uid").

Solved example: 2. A login check that fails for the second user

Question. What does /signin?uid=professor&pwd=54321 print?

from flask import Flask, request
valid = [{"uid": "student", "pwd": "12345"},
         {"uid": "professor", "pwd": "54321"}]
app = Flask(__name__)

@app.route("/signin")
def login():
    args = request.args
    for vu in valid:
        if vu["uid"] == args["uid"] and vu["pwd"] == args["pwd"]:
            return "You are authorized!!"
        else:
            return "You are unauthorized!!"

Solution. return ends the function at the first loop pass. The first user is student, which does not match professor, so the else runs and returns You are unauthorized!! The second user is never checked. (I ran this: it prints exactly that.) Without the query string at all, args["uid"] fails and the browser shows 400 Bad Request.

In your project

Your project must use the right status codes: 200 for a normal page, 404 when an id does not exist (use abort(404)), 400 or 403 for bad or forbidden actions. In the viva, expect "what does your app return for an unknown id?" and "why POST for this form and not GET?".

Idea 4: Stateless HTTP and cookies

Each request is independent: the server does not remember that you logged in one second ago. To fake memory, the server sends a cookie in a Set-Cookie response header. The browser stores it and sends it back in a Cookie header on every later request to that site. The cookie usually holds a short session id, and the real data stays on the server.

from flask import Flask, make_response, request
app = Flask(__name__)

@app.route("/set")
def set_it():
    r = make_response("ok")
    r.set_cookie("theme", "dark")
    return r

@app.route("/get")
def get_it():
    return request.cookies.get("theme", "none")

The first route sends Set-Cookie: theme=dark; Path=/. After the browser has that cookie, /get shows dark; in a fresh browser it shows none.

The idea

Stateless means the protocol has no memory. Cookies (and server-side sessions) are the add-on that gives websites memory. Never store a password in a cookie.

Idea 5: How a browser renders and what developer tools show

After the HTML arrives the browser parses it into a tree called the DOM (Document Object Model), applies the CSS to each node, works out the layout and paints the pixels. Each new file it discovers (image, stylesheet, script) is another request.

Press F12 (or right-click, Inspect) to open the developer tools:

  • Elements tab: the live DOM and the CSS applied to the selected element. You can edit text and styles to experiment; the change lives only in your browser and vanishes on reload.
  • Network tab: one row per request, with method, URL, status code, type, size and time. Click a row to see request and response headers. This is where you check that your form sent POST and what status came back.
  • Console tab: JavaScript messages and errors.

View Source (Ctrl+U) shows the HTML the server sent; Elements shows the page after the browser and JavaScript have worked on it.

Server-side versus client-side rendering. With Jinja2 (week 3) the server builds the full HTML and the browser just shows it. That gives a fast first view and works well with search engines. In client-side rendering the server sends data (JSON) and JavaScript builds the page in the browser (that is the MAD2 way, with Vue). Jinja2 server-side rendering does not remove the need for later fetches when the user interacts; it just makes the first load simple.

Idea 6: Bandwidth, latency and counting requests

Papers set small arithmetic problems. Memorise these facts and units.

The idea
  • Bandwidth = bits per second (Mbps = million bits/s, Gbps = 1000 Mbps). 1 byte = 8 bits.
  • Latency = time for one round trip (milliseconds), mostly set by distance and the number of steps.
  • Transfer time = size in bits divided by bandwidth in bits per second.
  • Throughput needed = requests per second times size of one response.
  • Capacity = (requests one worker handles per second) times (number of workers). Requests per second = 1 divided by the time per request in seconds.
Solved example: 3. Throughput

Question. An app serves 10,000 requests per second, each response is 50 KB. How much network speed is needed? A 10 Gbps link: enough?

Solution. Total data per second = 10,000 x 50 KB = 500,000 KB = 500 MB per second. In bits: 500 MB x 8 = 4,000 Mb = 4 Gbps. A 10 Gbps link is enough. Because the link and the CPU are not the problem, this single server only needs a modest upgrade: the exam answer is scale up (a bigger machine), not scale out (more machines).

Solved example: 4. Requests per second and download time

Question. (a) One worker takes 20 ms per request. How many requests per second can 4 workers handle? (b) A 25 MB file is downloaded on a 100 Mbps line. How long does it take?

Solution. (a) One worker: 1 / 0.020 = 50 requests per second. Four workers: 200 per second. (b) 25 MB = 25 x 8 = 200 Mb. Time = 200 / 100 = 2 seconds (plus latency).

Memory and concurrency. If each connected viewer needs 3 GB and at most 1,900 viewers are online at the busiest minute, the server must hold 3 GB x 1,900 = 5,700 GB = 5.7 TB (the real paper reads the peak from a graph and asks exactly this; use the highest point, not the average, because everyone may be there at once). Watch the unit: 1,900 x 3 GB is in GB, so convert before choosing GB or TB.

Scale up versus scale out. Scale up (vertical) means a stronger machine. Scale out (horizontal) means more machines behind a load balancer. Scale out when one machine's CPU, memory or network is the bottleneck; scale up when one machine has room and a bigger one is simpler. Caching (keeping a copy of a response near the client) reduces load and latency; it never "degrades service quality".

Cloud service models (a small recurring question): IaaS gives you raw machines and networks; PaaS gives a ready platform (language runtime, web server, database) so you only bring your code; SaaS gives a finished application (Gmail). A developer who wants a ready environment without managing servers wants PaaS.

Idea 7: MVC in one page

Most web apps split their code in three, so each part has one job:

PartJobIn this course
ModelThe data and rules (tables, queries)SQLAlchemy classes (later weeks)
ViewWhat the user seesHTML templates with Jinja2 (week 3)
ControllerReceives the request, uses the model, picks the viewFlask route functions

A request flows: browser, controller (route), model (data), back to the controller, view (template), response. Keep SQL out of templates and HTML out of models.

Your turn: 2. Split the URL

For http://localhost:5000/user/42/orders?sort=date&page=3#top: name the scheme, host, port, path, query string and fragment. Which of these does the server never see?

Need a hint?

Look for ://, :, /, ?, and #.

Show the full solution

Scheme http, host localhost, port 5000, path /user/42/orders, query string sort=date&page=3, fragment top. The server never sees the fragment top.

Your turn: 3. Pick the status code

Which status code fits: (a) a new student record was created, (b) the student id in the URL does not exist, (c) the user is logged in but is not an admin, (d) the server crashed because of a bug, (e) the page has moved for good to a new URL?

Need a hint?

201 / 404 / 403 / 500 / 301 are the candidates. Match them.

Show the full solution

(a) 201 Created. (b) 404 Not Found. (c) 403 Forbidden (401 would mean "not logged in"). (d) 500 Internal Server Error. (e) 301 Moved Permanently.

Your turn: 4. Bandwidth

A page needs 600 requests per second and each response is 250 KB. What link speed in Mbps is the minimum?

Need a hint?

Total KB per second, then bytes, then bits.

Show the full solution

600 x 250 KB = 150,000 KB per second = 150 MB per second = 150 x 8 = 1,200 Mbps = 1.2 Gbps.

Your turn: 5. Which Flask URL?

@app.route("/course/<name>") with request.args.get("id") inside. Which URL works: /course/MAD1?id=CS2003, /course?name=MAD1&id=CS2003, /MAD1?id=CS2003?

Need a hint?

Name goes in the path, id in the query.

Show the full solution

Only /course/MAD1?id=CS2003. The other two do not match the pattern and give 404.

Exam radar

Exam radar

The graded questions are mostly Quiz 1 and Quiz 2, and for this first week the keyword match (about 235 of 692 Quiz 1, about 252 of 624 Quiz 2, about 477 of 1600 End Term questions) is broad, because almost every Flask question touches URLs, requests and status codes. What the real papers actually ask:

  • Predict what the browser shows for a URL against a small Flask app: path variable versus query string, a missing value (404), abort(400) for a bad value, a custom errorhandler. These repeat across several years.
  • Method and status code facts: "GET is the same as HEAD" (false), which method can be cached, 404 versus 405 versus 400, the mimetype and status of jsonify.
  • Back-of-envelope calculations: requests per second times response size gives Gbps (the 10,000 x 50 KB = 4 Gbps one); viewers x memory gives peak RAM (the 3 GB video question); scale up versus scale out.
  • Cloud and rendering concepts: PaaS versus IaaS versus SaaS; why server-side rendering gives a faster first load.
  • curl commands for a JSON API: -X POST, -H 'Content-Type: application/json', -d '{...}'. Without the JSON header, the request is not read as JSON.
Watch out - real exam trap
  • A browser address bar is always GET. A POST-only route visited in the browser gives 405, not the function's output.
  • <int:x> routes: a non-number is 404; a number is accepted.
  • /route/ with a missing path variable is 404; ?uname with no value gives an empty string, not the default.
  • return inside a loop ends the function at the first pass.
  • 401 means not logged in, 403 means not allowed; 4xx is the client's fault, 5xx the server's.
  • Bits versus bytes: network speed is in bits, file sizes are in bytes. Multiply by 8.

Quick quiz

Quick quiz

A user types http://127.0.0.1:5000/home/user_1 in the browser, where /home/<username> allows only POST. What status does the server return?

  • 200
  • 404
  • 405
  • 500
The path matches, but the browser sends GET, which the route does not allow, so the answer is 405 Method Not Allowed.

Which part of a URL is NOT sent to the server?

  • the path
  • the query string
  • the fragment
  • the port
The fragment (after #) is used only by the browser to jump inside the page.

For @app.route("/greet/<name>"), what does http://127.0.0.1:5000/greet/ return?

  • Hi None
  • Hi (blank name)
  • 400 Bad Request
  • 404 Not Found
The path variable is missing, so the URL matches no route.

Select all TRUE statements. (select all that apply)

  • HTTP is stateless; cookies are used to remember a user.
  • A 5xx status code means the server had a problem.
  • GET and HEAD return exactly the same response.
  • POST requests are cached by browsers by default.
HEAD returns only headers, and POST responses are not cached by default.

A service handles 10,000 requests per second, each response 50 KB. The network speed needed is about...

  • 0.5 Gbps
  • 40 Gbps
  • 4 Gbps
  • 400 Mbps
10,000 x 50 KB = 500 MB per second = 4,000 Mb per second = 4 Gbps.

A developer wants a ready runtime, web server and database, and only wants to deploy code. Which cloud model?

  • SaaS
  • PaaS
  • IaaS
  • DNS
PaaS provides the platform; IaaS gives raw machines, SaaS a finished app.

Viva: say it out loud

Viva: say it out loud
What happens when you type a URL in a browser?

The browser asks DNS for the IP address, opens a connection to the right port, and sends an HTTP request. The server runs its code and returns a response with a status code and a body. The browser renders the HTML and makes more requests for CSS, images and scripts.

What is the difference between GET and POST, and which does your form use?

GET reads data and puts parameters in the URL, so it is safe and cacheable. POST sends data in the body and is used to change something on the server, such as adding a record. My add-form uses POST because it creates data and I do not want the values in the URL.

Why do websites need cookies if HTTP already works?

HTTP is stateless: the server forgets the client after each response. A cookie holds a small id that the browser sends back every time, so the server can recognise the same user across requests.

Explain 401, 403 and 404.

401 means the user is not authenticated (not logged in). 403 means they are logged in but are not allowed to do this. 404 means the resource does not exist at that URL.

Which of your routes return which status codes?

Normal pages return 200, a new record returns 201 or a redirect (302) after POST, an unknown id calls abort(404), and a bad form value returns 400. A bug in my code would show 500, which I try to avoid.

What is MVC and where is it in your project?

Model, View, Controller separates data, display and logic. My SQLAlchemy classes are the model, the Jinja2 templates are the view, and my Flask route functions are the controllers.

How would you check what your browser actually sent?

Open developer tools and go to the Network tab, click the request, and read the method, headers, status and body. I can also repeat it with curl -i.

Recap

Remember this
  • The internet is the network; the web is HTTP pages on it. Clients ask, servers answer, one request gets one response.
  • A URL has scheme, host, port, path, query string and fragment. The fragment stays in the browser.
  • A request has method, headers and maybe a body; a response has a status line, headers and a body.
  • Methods: GET read, POST create, PUT replace, PATCH change part, DELETE remove, HEAD headers only.
  • Status families: 2xx fine, 3xx redirect, 4xx your fault, 5xx server's fault.
  • HTTP is stateless; cookies carry a session id to give memory.
  • Bandwidth is in bits (x 8 from bytes). Capacity is workers times requests per second. Use the peak for memory.
  • MVC: model = data, view = template, controller = route function.
Code and facts to keep
  • Requests per second = 1 / (seconds per request); with n workers multiply by n
  • Bits = bytes x 8; Gbps = 1000 Mbps; throughput = (requests per second) x (response size)
  • Download time = size in megabits / speed in Mbps
  • Defaults: http port 80, https 443, Flask 5000, python -m http.server 8000
  • Flask: request.args.get("k") (query), <int:id> (path), abort(404), jsonify(x) gives 200 and application/json
  • Status: 200 OK, 201 Created, 301/302 redirect, 400 Bad Request, 401 not logged in, 403 forbidden, 404 not found, 405 wrong method, 500 server error
  • curl: curl -i URL, curl -X POST URL -H "Content-Type: application/json" -d '{"a": 1}'
Connected weeks (learn them together)

Practise with real exam questions

These come straight from past papers (with the real figures and the official answer key). Open 60 real questions on this week   All Quiz 1 papers