Basic Concepts
There are two parts to a web-based system: a client application that issues requests, and a server that handles those requests, issuing responses to the client.
Web Clients
The typical web client is a standard web browser such as Chrome, Microsoft Edge or Safari. It is also common to have mobile apps act as web clients. In this case, the mobile app provides the UI and some front-end logic, whereas the server side delivers data to the app over HTTP, as well as dealing with things like authentication and data persistence.
Note that any piece of software can act as a web client, provided that it has the ability to establish a secure TCP connection to a web server, issue an HTTP request over that connection, and handle the resulting HTTP response.
You encountered this idea last year in COMP1850, where you wrote Python code to interact with the Pokemon API over HTTP.
Here’s a simple example of a Python web client:
import httpx
response = httpx.get("https://example.com/")
print(response.text)
This code uses the httpx library to issue a request for the home page
of the web server with domain name example.com. It prints the content of
the response obtained from the server, assuming it to have a text rather than
binary format.
A Simple Web Server
At its most basic, a web server
- Listens on a particular TCP port for incoming HTTP requests
- Handles each request in an appropriate manner, depending on its associated URL
- Delivers an HTTP response back to the client
If the URL references a specific HTML document, handling the request can be as simple as reading that document from disk and sending the contents back to the client1. This is known as a static response, because repeated requests will give rise to the same content being delivered every time (at least, until the document is changed on disk). A dynamic response, which can vary between requests, is also possible. Dynamic responses are common in database-driven applications.
Task 3.1
-
Create a file
test.htmlcontaining the following:<!DOCTYPE html> <html lang="en"> <head> <title>Test Document</title> </head> <body> <h1>Test Document</h1> <p>Hello World!</p> </body> </html> -
Open a terminal, move to the directory containing
test.html, and run the web server provided in the Python standard library, like this2:python -m http.server -
In a browser, try visiting this URL:
http://0.0.0.0:8000/test.htmlYou should see the test document rendered in the browser window.
-
Look at the message log displayed in the terminal window. You should see a GET request logged for
test.html. -
Terminate the server using
Ctrl+C.
This is a toy server, suitable for experimentation but not for production use!
It is not secure and has none of the features that would make it appropriate to use in a real web application.
Real Web Applications
A web server can run as a single process, dealing with all aspects of request handling itself, but in practice the server side of a web application often has a more complicated architecture.
For example, some web applications will use a standard web server such as Apache or Nginx to serve requests for static resources such as HTML, CSS and images, whilst using a separate application server to provide dynamic responses. There are standards for how web servers and application servers communicate—e.g., WSGI in Python.
Heavily-used web applications may need to provide a server farm consisting of several replica web servers. In such a system, requests go first to a load balancer which distributes requests amongst the replicas, to ensure that none of them get too overloaded.
Many web applications are database-driven, so a database server will often feature as a key element of the server-side architecture. These applications may also employ a separate caching server such as memcached or Redis to cache the results of potentially expensive queries.
-
Note that an HTML document will most likely reference additional resources such as stylesheets and images. If the client is a browser then further requests will need to be made for these resources before the document can be rendered fully. ↩
-
If this doesn’t work, you might need to use the command
python3instead. If that doesn’t work, check that Python 3 is accessible on the system that you are using. ↩