Project 3 - Web Server
In this project, you will be implementing a simple web server in the Python3 programming language. In doing so, you will gain:
- Hands-on experience with the Hyper Text Transfer Protocol (HTTP)
- Hands-on experience with TCP sockets
- Hands-on experience with Python programming, including details such as file I/O, string parsing, and command-line argument parsing.
To support these objectives, you are not allowed to use any pre-built HTTP, URL-parsing, or socket management libraries.
Description
The HTTP 1.1 protocol is extremely detailed and complex. You could spend a week reading RFC 2616 which formally describes the protocol. Fortunately, there is no need to do so for this project, as we are only going to be implementing a tiny subset of the standard. Your high-level goal is the following:
Implement a sufficient part of the HTTP 1.1 protocol in your web server such that a user could download the official "Project demo website" (described in Testing, below) using any of the following web browsers: Chrome, Firefox, Safari, and Edge. Your server should faithfully transmit any file requested by the web browser when downloading the demo website, which may include HTML, CSS, Javascript, or images. Once rendered by the browser, the website hosted by your web server should be indistinguishable when compared to the site hosted on the original web server. Any broken images, missing text, JavaScript warnings, etc... will be taken as an indication that your server is corrupting the files it transmits. (Obviously, if the web server is corrupting files, then we cannot expect the web browser to be able to display a perfect-looking website)
Requirements
- You must use the Python 3 programming language.
- Your assignments will be graded on a Ubuntu 20.04 LTS machine and must work correctly in that environment.
- You must support web browsers sending requests using version 1.1 of the HTTP protocol, and accept connections (and deliver responses) via TCP.
- You must support the GET request method from clients. Any other request that is not GET should produce a 501 "Not Implemented" error response. This is preferable to silently failing.
- You must support HTTP status codes
200
(OK),404
(Not found), and501
(Request method not implemented) as possible responses by your server. - A single-threaded solution that handles requests sequentially is acceptable this project for full credit. (Note, however, that the subsequent project will involve converting your web server into a design that can handle concurrent requests, so a bit of advanced planning here may simplify work later...)
- It is acceptable, in this solution, for your web server to close the connection upon completing a single request. In fact, if you only have a single-threaded web server, this simplification is necessary. (Note, however, that the HTTP/1.1 standard allows a web browser to send multiple sequential requests in a single connection, so we will be implementing this functionality in a later project.)
- Your web server should be runnable from a file called
server.py
. You can import additional Python files (so that your entire project is not in a single file), but the user should not invoke these helper files directly. - Listening on port 80 requires root-level access. Because I don't want to run your programs with root-level permissions while grading, you should instead listen on port
8080
, which does not require root access. In your web browser, access your server by specifying the port number in the URL, e.g.http://localhost:8080/file.html
. - The following command-line arguments should be supported:
--help
: This argument will print out a helpful message describing what arguments the program takes--base=/path/to/directory
: This argument allows you to specify the base directory where the website is stored on the server--port=####
: This argument allows you to specify the port number the web server listens on
- You should use the argparse Python library instead of parsing the arguments yourself. Argparse will provide the
--help
and--version
arguments for "free".
Example invocations:
$ ./server.py --help
usage: server.py [-h] [--version] [--base BASE_DIR] [--port PORT]
Web Server for COMP/ECPE 177
Optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
--base BASE_DIR Base dir containing website
--port PORT Port number to listen on
$ ./server.py --base=/home/shafer/website/html --port=8080
## Server runs and starts listening on port 8080
Restrictions
You cannot use the following Python built-in modules in this course. Zero points will be awarded for an assignment that uses:
- http.client - FORBIDDEN!
- http.server - FORBIDDEN!
- socketserver - FORBIDDEN!
- urllib - FORBIDDEN!
In addition to the list above, you cannot use pre-written HTTP server, URL parsing, or socket management libraries obtained from other online sources.
This assignment is to be completed individually. You can discuss problems and potential solutions with other students, but you cannot share completed programs or significant pieces of completed code. The MOSS (Measure of Software Similarity) system may be used to compare submissions in an automated fashion.
Testing
The official "Project Demo Website" is a five page design template. It looks good, and provides all the types of files a real website would have, including:
- HTML files containing the page content
- Cascading Style Sheets (CSS) that specify format for the page content
- JavaScript programs that enable animation, drop-down menus, and other glitz
- Images in a variety of formats
To test, follow this process:
- Download the Demo Website. It should be called
website.zip
. - Unzip the website archive. Remember where you put it. (You can browse it to get a sense of the files and directory structure. The "html" subdirectory has the important files.)
- Open the
index.html
file directly with your web browser. Browse the website and remember how it looks. When you access the same files, using the same web browser, but delivered through your web server, you want the result to look the same! - Run your web server. Specify on the command line the root directory of your website in this demo site. For example:
./server.py --base=/home/myusername/website/html --port=8080
- Run your web browser and access the following URLs for testing. Be sure to browse the site after it appears, to ensure the links work!
http://127.0.0.1:8080/index.html
http://localhost:8080/index.html
http://localhost:8080/ (No file name is specified here. What should your server do?)
Tip: It is unlikely that your web server will work perfectly on the first attempt. I suggest identifying and accessing individual CSS files, JavaScript files, images, and HTML files. Load one at a time. Once you are convinced that each type of resource is being served correctly, then go and test the entire site.
Resources
See the main resource page for links that helped me when developing my solution, including demo code and Python documentation.
Getting Started
- Step 1:
- Server accepts request from client and displays text request to screen
- Server uses argparse for command-line arguments, including port number.
- Step 2:
- Server can successfully decode one HTTP request from a client and send a single reply file given a controlled test environment.
Deliverables
Submit the single Python script or collection of scripts that implements your web server to the Canvas CMS Project 3 assignment.
If using PyCharm, do not submit your venv environment. Before submitting, test to ensure you can run your program outside of PyCharm on the command line.
Do not submit the demo website. Your instructor already has a copy of it.