Static Web Server
Static Web Server
Requirements
Please start by downloading the HW1 package from http://cis5550.net/hw1.zip. This contains a README file with a short questionnaire, an Eclipse project definition (which you can ignore if you are not using Eclipse), and a small test suite. Your solution must meet the following requirements:
Invoking the server: The main class of your server should be cis5550.webserver.Server. This class should have a main() method that should accept two parameters: 1) a port number, and 2) the name of a directory that contains the files the server will return. It should be possible to run your server from the command line like this: java cis5550.webserver.Server 8000 foo/bar. If the server is not invoked with the correct number of arguments, it should print your full name (e.g., Written by Benjamin Franklin) and exit.
Basic operation: When the server receives a GET request, it should append the URL to the directory that was given on the command line, and return the file with that name if it exists. For instance, if the directory 1 is foo/bar and the request is GET index.html HTTP/1.1, your server should return the contents of foo/bar/index.html. When the server receives a HEAD request, it should handle it just like a GET request, except that it should not send a message body. The headers (including Content-Length) should be the same as if the request were a GET.
Error handling: Your server should send the following error codes:
• 400 Bad Request if the method, URL, protocol, or Host: header are missing from the request;
• 403 Forbidden if the requested file exists but is not readable;
• 404 Not Found if the requested file does not exist;
• 405 Not Allowed if the method is POST or PUT.
• 501 Not Implemented if the method is something other than GET, HEAD, POST, or PUT; and
• 505 HTTP Version Not Supported if the protocol is anything other than HTTP/1.1.
Headers: Your server should be able to handle persistent connections – that is, if a request has a Content-Length header to indicate that it contains a body, the server should use this header to determine where the current request ends and the next one begins. In its response, the server should include at least the Content-Length, Server, and Content-Type headers; the content type should be set to image/jpeg if the requested file has the extension .jpg or .jpeg; text/plain if it has the extension .txt; text/html if the extension is .html; and application/octet-stream otherwise.
Concurrency: Your server should be able to handle multiple requests concurrently. You can accomplish this by launching a fresh thread whenever the main thread has accepted a new connection, and by doing all the protocol logic in this new thread, while the main thread goes back and waits for the next connection. Security: As a basic security feature, your server should return a 403 error code if the requested URL contains the string .. (two dots), to prevent clients from downloading files outside the specified directory.
Miscellaneous: Your server should be able to handle any number of headers, in any order; keep in mind that header names are not case sensitive. It should be able to correctly return files of any size and type, including binary files. You should not assume that requests will arrive in any particular granularity, especially not all at once; they could arrive one byte at a time. Keep in mind that the line separator in HTTP is CRLF (a carriage return, followed by a line feed); your server should correctly parse requests that use this separator, and it should use the separator correctly in the responses. When your server is idle and there are no requests, it should not consume any CPU resources; please do not use “busy waiting” anywhere in your code. And finally, the server should have reasonable perfomance: with 1kB files, it should be able to handle individual requests in one second or less, and it should be able to handle at least ten requests per second. For any details that are not specified here, please see the HTTP/1.1 specification in RFC 2616.
Packaging: Your solution should be in a directory called HW1, which should contain
- the README file from the HW1 package, with all the fields filled in, and
- a subdirectory called src with all of your source code, in the directory structure Java expects (with subdirectories for packages). Your solution must compile without errors if you run javac --source-path src src/cis5550/webserver/Server.java fom within the HW1 folder. Please do try this before you submit! Submissions that fail this basic check will receive a zero.
Extra credit
If you like, you can implement the following additional features for some extra credit. If you do, please indicate this in the README file you submit!
Thread pool (+5 points):
Refactor your server to use a thread pool, instead of just starting a new thread for each request. There should be one thread that accepts new connections and puts them into a BlockingQueue, as well as a fixed number of worker threads that pull connections out of this queue and handle them. The number of worker threads should be based on a constant called NUM_WORKERS in your Server class, which should be set to 100 in the solution you submit. Note: We will give credit only if you implement your own thread pool – simply using one of Java’s built-in mechanisms, like ThreadPoolExecutor, is not enough!
Conditional requests (+5 points):
Add support for the If-Modified-Since header. You can find a description of this header in Section 14.25 of RFC 2616. You only need to support the rfc1123 date format.
Range requests (+5 points):
Add support for the Range header. You can find a description of this header in RFC 7233. You only need to support a single bytes range – that is, a header of the form Range: bytes=XX, where XX is either a closed range, such as 12-50, or an open range, such as 50- or -5. There is no need to support the If-Range: header, the 416 response, or multi-part responses.
Suggested approach
We suggest that you use the steps below to solve this assignment; however, feel free to use a different approach, or to ignore this section entirely. We will give credit for your solution, as long as it meets the requirements above.
