Problem Set 1 - zhttpto Web Server
Purpose
The goals of this assignment are to:
-
Get everyone in the class set up with the main tools we will use in this course including rust and using github to manage your code and submit your assignments.
-
Introduce the Rust programming language and get some experience writing code in Rust.
-
Preview several of the main concepts we will cover in this class including: processes, threats, memory management, and network protocols. You are not expected to understand everything we use in this assignment, but we hope this exposure will get you to start considering more deeply what is going on in computer systems.
Getting Started
Before continuing with this assignment, you should:
After finishing these steps, you should have a ps1
directory that
contains
Background
A web server is a program that responds to HTTP requests. HTTP (Hypertext Transfer Protocol) is the protocol that specifies how web clients and servers should communicate with each other.
A simple web server can just open a socket to listen for requests, and send back a response when a request arrives. Tim Berners-Lee led the development of the first web server, starting in 1990.
The most popular web server today (and since 1996) is Apache, which is about 2.2 million lines of (mostly C) code. Your web server will provide some of the same functionalities as Apache, but will be much simpler!
Warm-up
Before working on the web server code, let's get started programming in Rust with some warm-up exercises.
Make sure you have set up the repository and starting
code correctly.
For these problems, you should work in the (initially empty) warmup
subdirectory in your ps1
repository, and put all the code
in files in that directory.
Note that these exercises may require you to learn aspects of Rust that were not covered in class or in the notes. You should be resourceful in searching for helpful documentation, but if you are stuck, use the class IRC channel and/or discussion board to get help.
For the next exercise, you'll need to read arguments from the command
line. You can use the
os::args()
function to obtain vector of strings containing the command line
arguments:
use std::{os, uint};
fn main() {
let args: ~[~str] = os::args();
...
}
(The ~str
type means a pointer to a string that is owned by this
reference. We will cover the different pointer types in Rust in class
later, but if you are understandably curious now see the Rust
documentation.)
For example,
$ ./echo hello
hello
$ ./echo 10 9 8 7 6 5 4 3 2 1 Blastoff!
10 9 8 7 6 5 4 3 2 1 Blastoff!
(Note that the zeroth element of the array returned by os::args()
is
the name of the executed command, in this case ./echo
, which should
not be echoed.)
For example,
$ ./average 4 4 1 4
Average: 3.25
$ ./average 4 4 one 4
Bad input: one
Average: 4
Remember to add these files to your github repository, commit the changes, and push them to the main repository. (You can check that everything worked as expected by visiting the repository through the github website.)
Making the Zhttpto Web Server
For this assignment, we have provided starting code for a miniscule web
server in zhttpto.rs
(pronounced "zepto"). Its so small, it doesn't
yet even understand HTTP and responds to every request with the same web
page response. For this assignment, you will modify the web server code
to serve simple static pages.
Compile (rustc zhttpto.rs
) and run (./zhttpto
on Unix) the server.
The server is listening on port 4414. Open a web browser to
http://localhost:4414
. If the server is running correctly, you should
see a welcoming response page. (We will got more into how network
sockets work and the design of network protocols like HTTP later in the
class.)
In the shell that is running the server, you should see text output showing the messages received by the server. The most interesting line is the User-Agent, which is what your web browser is telling the server. Typical User-Agent strings incorporate a history of web browser development. For example, the request from my Firefox browser includes: User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:22.0) Gecko/20100101 Firefox/22.0.
For the short answer (prose) questions, you should create a file
answers.md
in your ps1
repository. The .md
suffix is for
Markdown, a convenient
way of generating HTML content. It is not necessary to do any fancy
formatting, though, you can just use plain text for your answers unless
more is necessary for clarity. The first lines of your answers.md
file should be:
Title: Problem Set 1 Answers
Author: <your name>
Copy the User-Agent string reported by your browser. Explain as many of the things in that string as you can.
Code Walkthrough
In class on September 3, I will go through the provided code and answer any questions about it. You should look at the code yourself before then, and try and understand it on your own.
Living Dangerously!
For the next problem, your goal is to add a counter to the server that increments with each request.
If you do this in a straightforward way, by declaring a mutable static variable you are likely to encounter a compile-time errors like this:
zhttpto.rs:50:27: 50:40 error: use of mutable static requires unsafe function or block
zhttpto.rs:50 visitor_count += 1;
^~~~~~~~~~~~~
zhttpto.rs:59:50: 59:63 error: use of mutable static requires unsafe function or block
zhttpto.rs:59 </body></html>\r\n", visitor_count);
^~~~~~~~~~~~~
Speculate on why Rust thinks it is unsafe to modify a global variable like this.
One of the major themes of this course is how to use concurrency safely, and we will study some of the potential problems caused by mutable shared memory as well as different strategies for solving them. For now, you can just live dangerously and use an unsafe block around the dangerous code.
Modify the server so it maintains a count of the number of requests, and adds a message to the response that includes a count of the number of requests. You should see the number increase each time your reload the page.
Serving Files
Even with the counter, our web server is not very useful! For the rest of this assignment, your goal is to modify the web server to serve requested static pages.
If the first line of the incoming request matches GET /<path> HTTP/1.1
where <path>
is a non-empty file system path. Your server should
respond by sending the contents of the file <cwd>/<path>
where <cwd>
is the current working directory (where you started the web server) in
the response.
If the incoming request contains an empty path, your server should respond as it did in the previous problem.
Modify the server to respond with requested files, as described above.
Submission
Once you decide to submit your project for grading after commiting some code and documents, you should add a tag on your code repository with a version number, and submit your assignment by providing the corresponding URL using the form.
Teaser
We will return to the web server in Problem Set 3, where you'll learn more about network protocols, threads, and managing resources to improve the functionality and performance of your web server.