This page is from the Fall 2013 course.
It may be replaced with an updated version later this semester. [Permalink to this version]

Problem Set 1 - zhttpto Web Server

Due: 11:59pm on Tuesday, 10 September

Purpose

The goals of this assignment are to:

Collaboration Policy. For this problem set, everyone should submit their own assignment. You should discuss the problems with others and are expected to help your classmates in ways that benefit their learning, but not provide answers thoughtlessly. You should attempt every problem on your own first before seeking help and must fully understand everything you submit as your own work.

Getting Started

Before continuing with this assignment, you should:

  1. Set up your computing environment for this course including Rust.

  2. Set up git and your github account.

  3. Set up the repository and get the starting code.

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.

Exercise 1. Create a Rust program, greete.rs, that prints out a friendly (or not-so-friendly depending on your mood) greeting. Compile and run the program.

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.)

Exercise 2. Write a Rust program, echo.rs that behaves like the Unix echo command. Your program should print out its command line arguments, separated by spaces.

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.)

Exercise 3. Write a Rust program, average.rs, that takes in a list of one or more numbers on the command line and outputs the average value of the input numbers. If any command line argument is not a valid number, your program should print out a warning about that input and skip it (but otherwise continue).

For example,

$ ./average 4 4 1 4
Average: 3.25
$ ./average 4 4 one 4
Bad input: one
Average: 4
Visit the PS1 | Exercise 3 discussion thread in the Piazza discussion board. That thread has a "the students' answer" that should reflect the consensus of the class on the best way to solve this. See if you can improve the solution posted there, and contribute to the followup discussions about interesting things you have discovered about Rust in solving this problem.

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>
Problem 1 (write your answer in answers.md, clearly marked as 1.)
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);
                                                                ^~~~~~~~~~~~~
Problem 2. (2. in answers.md)
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.

Problem 3. (modify zhttpto.rs)
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.

Warning! Setting up a server that sends any requested file on your machine to anyone on the Internet would normally be a very dangerous and reckless thing to do! This is only (hopefully) safe now since you are running the server in the VM that does not contain any sensitive files. Nevertheless, it is recommended that you don't announce your IP address or leave your server running except while you are testing it.
Problem 4. (modify zhttpto.rs)
Modify the server to respond with requested files, as described above.

Submission

Submission Form

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.

This assignment was created by David Evans and Weilin Xu for University of Virginia cs4414 Fall 2013.