In this assignment you will build the foundation of the server that you will develop throughout the semester. All homework assignments will continue to add features to the same web app. A front end of the app is provided for you, which you can clone using the link below.
GitHub Repository link: https://github.com/CSE-312/CSE312-Server
This front end is designed to send requests to your server for most of the homework objectives throughout the semester and your goal will be to implement the corresponding endpoints on the back end. This front end is offered to make it easier to complete, and test, your server. You are also free to modify this front end in any way you'd like, or design and build your own, as long as the features for each objective are clear and accessible when visiting your front end.
In addition to modifying the front end, or building your own, you are free to deviate from the specific details of each objective as long as you still implement the features for each objective. This offers you flexibility to implement your app the way you'd like, while still learning the concepts required for each objective. There is no limit to the amount you are allowed to deviate as long as the concepts are still covered.
If you choose to deviate from the stated objectives, you must justify how this deviation still covers the concepts required for the objective.
Goals:
Concepts Covered:
If this objective, you will build the foundation of your server by hosting all the static files needed to load your homepage.
In the provided front end, this involves hosting every file in the public directory with the proper MIME type, and rending
2 HTML templates.
You are required to have some thoughtful organization of your server code. As with all objectives, you may deviate from the structure below as long as your architecture is clear and maintainable. If you deviate from this structure and it is not clear, it will be more difficult for the course staff to help you if you need assistance with your code and you may not be able to get the help you need later in the semester (In addition to losing credit for this objective).
Create a class that will parse HTTP requests and set appropriate instance variables. This class should take a raw request as bytes and set instance variables containing the request information. These instance variables must include:
Tips:
Create a class that will build HTTP responses with methods to populate the data of the response. This class must include ways to:
Tips:
Create a class that will route different requests to the appropriate function. This class must include ways to:
Tips:
This is the first task where you'll start adding functionality to your server (The three classes you've written will make it easier for you develop your server throughout the semester). Add a route to your router that will host all files in the public directory.
To accomplish this task, you should add a route that will match any path starting with "/public", then extract the file path from the rest of the path and serve that files contents in the response. For example, if you receive a request for the path "/public/imgs/dog.jpg", you should read the file "/public/imgs/dog.jpg" and send it in the body of a response. You must use the three support classes you've created to accomplish this.
All files must be served with the correct MIME type. You may use the file extensions to determine these MIME types. For this HW, you only need to handle the file extensions that appear in the provided public directory. (Note: .ico is an image with MIME type "image/x-icon").
In addition to hosting all the files in the public directory, you will add paths for each of the pages of
the app. For each of these pages, you will need to render an HTML template (Don't panic, this comes down to
reading 2 files and doing 1 find and replace). There is an HTML template in "public/layout/layout.html".
This template contains all the structure of the app including menus, navigation, metadata, imports, etc.
This template has one placeholder that is exactly the string
Add the following special paths that require rendering HTML using layout.html as described above:
At this point, you can run your server and visit "http://localhost:<your_port_number>" in your browser to see the provided front end.
Security: The X-Content-Type-Options: nosniff header must be set on all responses (Please double/triple check this header for the exact spelling and syntax. If you are off by 1 character, the browser will not disable MIME type sniffing which renders your header useless and can be a security issue). It is recommended that you add this header in your Response class so you'll never forget it
UTF-8: Some files contain emojis that will be displayed when the page loads. These characters must display properly.
404: If a request is received for any path that should not serve content, return a 404 response with a message saying that the content was not found. This can be a plain text message.
Goals:
Concepts Covered:
The front end contains a chat feature that will send specific requests to your server. To enable this feature, implement the following end points. Note that you will need to use a database to complete these end points. All functionality must persist through a server restart, and you must use a PostgreSQL database.
To test your app with a database, you can either install and run PostgreSQL on your device, or setup Docker to run a PostgreSQL container (Which is the next objective so you have to do this anyway).
Creates a new chat message. The frontend will send a POST request to your backend at the route `/api/chats`. Listed below is the format expected. The entirety of the body of the request will be a JSON string
Request (JSON): {"content": string}
Response: 200 OK with a message of your choosing. A simple text response of "message sent" is fine
You may assume the request is properly formatted
When a message is sent, you should create a unique id for the message and store it in your database along with the author of the post. See the spec for the GET request to see the expected format of a chat message.
Retrieves all chat messages. The frontend will send a GET request to your backend at the route `/api/chats`. Listed below is the format expected.
Response (JSON): {"messages": [{"author": string, "id": string, "content": string, "updated": boolean}, ...]}
The `updated` parameter that is sent back in the list of messages represents if the message has ever been updated. If it has it must be set to true. When a message is first created, this should be set to false.
If the same user creates multiple posts, all posts must have the same author. This should be tracked using a cookie that is set and tracked by your server. This cookie must be set when they send their first message
Since we don't have user accounts yet, you can choose random author names for users for now. The names must be different for different users, but can be randomly generated. You are allowed to use a package to generate ids and tokens if you'd like.
Updates an existing message with new content. The frontend will send a PATCH request to your backend at the route `/api/chats/{id}`. Listed below is the format expected.
Request (JSON): {"content": string}
Errors:
After a message has been updated using this endpoint, its "updated" field must be set to true
Deletes an existing message from chat history. The frontend will send a DELETE request to your backend at the route `/api/chats/{id}`
Errors:
After a message is deleted by its author, it must never be sent by the GET endpoint again.
Security: You must escape any HTML in the users' messages. Since your users can submit any text they want, a malicious user could submit HTML tags that attack other users. You cannot allow this. You must escape any submitted HTML so it displays as plain text instead of being rendered by the browser.
Goals:
Concepts Covered:
Setup your app to run in a docker container such that running "docker compose up" from the root directory of your project will start your server and database in separate containers with your app available on localhost port 8080. To accomplish this, you will need to write a Dockerfile that will both compile and run your server code. You will also need a docker-compose.yml file that will start your server and database in separate containers.
Tips:
Goals:
Concepts Covered:
Implement Keep-Alive support for your server such that a client is able to send multiple requests, and receive multiple responses, over the same TCP connection. You must properly handle these multiple requests, especially requests that are received in quick succession.
Goals:
Concepts Covered:
The goal for this objective is to set the appropriate headers to add caching support to your server. Note that you will not cache anything, but you are setting headers that will inform the browser how to cache your responses.
You must implement both ETag and timeouts to cache responses. For timeouts you may choose to use Max-Age or Last-Modified. In either case, you should set a very short timeout (e.g. 10 seconds). This will make testing much faster and simpler. If a request is received for content that is cached, you should return a 304 Not Modified response.
All of you static content must be cached. This includes every file in the public directory, and the rendered HTML templates.
Submit all files for your server to Autolab in a .zip file
Complete the homework submission form after submitting your zip file to Autolab: Homework Submission Form
If you do not both submit your zip file to Autolab and complete the homework submission form before the due date, your submission will not be graded. Do not be one of the students who will get a 0 for not submitting the form after completing the assignment.
Each objective will be scored on a 0-3 scale as follows:
| 3 (Complete) | Clearly correct |
| 2 (Complete) | Mostly correct, but with some minor issues |
| 1 (Incomplete) | Not all features outlined in this document are functional, but an attempt was made to complete the objective |
| 0 (Incomplete) | No attempt to complete the objective or violation of the assignment (Ex. Using an HTTP library) |
| 0 (Security Risk) | If any security risk is found while testing, all objectives will be scored 0 unless a proper security essay is submitted |
Note that for your final grade there is no difference between a 2 and 3, or a 0 and a 1.
| 3 | Objective Complete |
| 2 | Objective Complete |
| 1 | Objective Not Complete |
| 0 | Objective Not Complete |
If a security risk is found in your submission, you will be assigned a 0 for all 5 objectives. However, you will still have an opportunity to earn credit for the objectives by submitting an essay about the security issue you exposed. These essays must:
If your submission contains multiple security risks, you may have to write multiple essays to recover your homework grade
Any submission that does not meet all these criteria will be rejected and your objective will remain incomplete.
Due Date: Security essays are due 1-week after grades are released.
Any essay may be subject to an interview with the course staff to verify that you understand the importance of the security issue that you exposed. If an interview is required, you will be contacted by the course staff for scheduling. Decisions of whether or not an interview is required will be made at the discretion of the course staff.