Link Search Menu Expand Document

Assignment 2

This assignment will be done in teams, to which you have been assigned as shown in this sheet. You should familiarize yourself with the class protocol, and make sure your team has settled on a TL for this assignment.

This is your first team assignment and it covers a full development lifecycle. Your team will build a simple HTTP Echo Server, package it into a Docker container, and deploy it to the Google Cloud platform, making it live on the public internet. This is a substantial assignment; start early and work closely with your team.

Each student should submit this assignment by 11:59PM on October 14, 2025 into the submission form.


Table of contents

  1. Team resource setup
    1. Gerrit
    2. Cloud
  2. Add initial skeleton code
  3. Write an echoing web server
  4. Create a Docker container
  5. Deploy your web server to Google Cloud
  6. Grading criteria
  7. Submit your assignment

Team resource setup

Before starting code on this assignment, your team will need to set up a team repository in Gerrit and set up a project in the cs130.org organization on Google Cloud. The TL should complete this portion of the assignment.

Gerrit

First, choose a creative name for your team. Make it unique, maybe a bit fun, maybe a bit clever. Choose a name that meets the following rules:

  • Starts with a letter
  • Contains only lowercase letters, numbers, or dashes
  • No punctuation other than “-“
  • No spaces
  • Is not just a collection of your first or last initials… that’s not creative

Then create a group with that name for your team in Gerrit. Change the Group Options to Make group visible to all registered users, and Save Group Options.

Next, create a repository for your team in Gerrit with the same name. Be sure to set the Owner to your team group.

Cloud

Finally, your team should create a project in Google Cloud:

  • Register for a coupon code as instructed via e-mail using your @g.ucla.edu account. The billing account will be created in the g.ucla.edu organization but can be used by your project in cs130.org.
  • Navigate to the New Project page. Make sure you are logged in with your @g.ucla.edu account as shown in the Google account selector in the upper right corner.
  • Enter your team name as Project Name. The generated Project ID, which must be unique across all of Google Cloud, may end up with a numeric suffix.
  • The Billing account should match the name of your recently created account (e.g. Billing Account for Education).
  • Set the Organization to cs130.org.
  • In Location, click Browse and select 2025F (under cs130.org) in the dialog.
  • Click Create to create your project.
  • You should be taken to the Dashboard with your project selected from the drop-down in the blue title bar at the top of the page. It may take a few seconds for your project to finish being initialized.
  • Navigate to the IAM & Admin section from the hamburger menu (☰ icon) in the upper left and select IAM.
  • At the top you will find a button to Grant Access for each of your team members by e-mail address (@g.ucla.edu) as New principals with the Owner role, then Save.
  • Verify that your entire team is listed in the Permissions table with Owner in the Role column. New Owners may need to accept an e-mail invitation sent by the system, so make sure your team members accept the invites and any orange warning signs disappear.

With that, your project should be set up. You will use this project throughout the class to build, store, and deploy your applications on servers running in Google’s data centers, i.e. the cloud.

At this point you should initialize the Google Cloud SDK tool, gcloud. Follow these instructions to login and enable APIs for future use with gcloud.

Add initial skeleton code

At this point the TL should hand over work to a team member to handle coding tasks.

As you did in Assignment 1, start by uploading some skeleton code to your team repository. You will be using the Boost library (documentation) to help create your server. The official Boost examples include a simple echo server that would make a reasonable starting point for your web server. (Yes, the examples also include a simple HTTP server, but let’s not jump there yet. Start with the echo server.) We’ve packaged the echo server into a file so that you can use it to get started.

$ git clone ssh://${USER}@code.cs130.org:29418/${REPO}
$ cd ${REPO}
$ git checkout -b skeleton
$ git review -s
$ curl http://static.cs130.org/src/boost-server.tar.gz | tar -zxv

You should once again generate config files from our project templates to get you started. You will need to edit CMakeLists.txt to compile server_main.cc and link it with Boost::system. Since you do not have any unit tests (yet), you can comment out the test executable and gtest_discover_tests rule, as well as all the lines at the end relating to code coverage.

You should be able to compile the server without making changes to the code, using CMake followed by make. Launch the server with a test port (8080), and then test that the server is functioning correctly by typing text and checking for a response, using netcat in another terminal:

$ cd build
$ cmake ..
$ make
$ bin/server 8080

In another terminal:

$ nc localhost 8080

Type text into netcat (nc) and verify it is printed back to you. Assuming all goes well, send this initial code out for review on Gerrit and submit.

Write an echoing web server

Next, you will modify the simple socket server to create a functional HTTP Echo Server. Your server must correctly handle the basics of the HTTP/1.1 protocol.

Your server must:

  1. Read a Complete HTTP GET Request: Read from the client socket until you receive a full HTTP request (signified by the \r\n\r\n delimiter). Store the entire raw request in a buffer.
  2. Construct a Valid HTTP Response: Send back a well-formed HTTP/1.1 200 OK response. This response must include:
    • A Content-Type header set to text/plain.
    • A Content-Length header with the exact size in bytes of the original raw request.
  3. Echo the Request: The body of your HTTP response must be the complete, raw HTTP request that you received.

For reference you can consult the official HTTP/1.1 spec for request and response or search the web for examples.

You should start by refactoring server_main.cc into several source files, creating a separate source and header file for each class. The refactoring alone (with no behavior change) should be sent out for review.

Your web server should read its configuration from a file in Nginx format. Use the code (and unit tests) from from one of your team members’ submissions for Assignment 1 as a starting point. Copy the code into your shared repository and update CMakeLists.txt to include it. The only configuration parameter you should need (so far) is the port number. Do not just use example_config as-is from Assignment 1, which contains other unnecessary parameters.

The server should take a path to the config file on the command line, as such:

$ bin/webserver my_config

Verification: Before proceeding, ensure your server compiles and runs correctly in the development environment. Test it again, this time with curl (curl -v http://localhost:<port>/) and confirm it echoes the request.

Once your server is running as you expect, send it out for review and submit it.

Create a Docker container

Next, you will create a Dockerfile to package your webserver. Address the TODO(!) comments in the docker/Dockerfile from the project templates to create a multi-stage build.

  • The builder stage should compile your server.
  • The deploy stage should start from a clean base image and copy only the compiled binary and necessary configuration files from the builder stage.

In the deploy stage, you should add command-line parameters (e.g. your server configuration file name) for the ENTRYPOINT binary using the CMD statement. Make sure you COPY your configuration file from the builder stage so it’s accessible in the deploy stage (see Docker docs on multi-stage builds).

Within the Docker container you should probably just listen on port 80. To make things easier later, create a new server configuration file using port 80, and use that configuration file specifically for your Docker container (not for local development).

Note, you will need to build and tag your :base image before building the builder/deploy image since builder depends on :base.

Local Verification: This is a critical checkpoint. Before moving to Google Cloud, you must verify that your container works locally.

  1. Build your image: $ docker build -t ${REPO}:latest .
  2. Run your container, mapping a port: $ docker run -p 8080:80 --rm ${REPO}:latest
  3. In another terminal outside the development environment, test it: $ curl -v localhost:8080
    • Note: When you run the container with docker, it is run on your host machine, outside the development environment, so it cannot be tested within the development environment.
  4. Shut down the container

If your server responds correctly, you are ready for cloud deployment. Do not proceed until this step is successful.

Make sure you submit your updated Dockerfile to your repository.

Deploy your web server to Google Cloud

In this final step, you will deploy your Docker container to Google’s cloud platform.

Next you will use your Docker container definition to create a container image on Google Cloud. Follow the guide for building a container, and then visit Cloud Build to see the results of your build. Click on a Build ID in the Build history table to see the Build details. From there you can view the Build Logs from each of the Steps that were run and, if successful, see links to the generated Images in the Build Artifacts tab. Note the full name of your generated image, e.g. gcr.io/.../...:latest.

Next you will deploy your container image to a server on Compute Engine. From the VM instances page, click Create Instance, and then fill in the following settings:

  • Within the Machine configuration tab:
    • Enter a descriptive name for Name, such as web-server
    • For Region choose us-west1 (Oregon) and leave the default Zone. Do not choose us-west2 (Los Angeles), it’s more expensive. Cost of living and computing are less in Oregon.
    • In the General purpose machine type section, choose E2 for Series and e2-micro for Machine type. It sounds small, but your server probably will not be seeing heavy loads. And, being written in C++, it’s fairly lightweight. In any case, it’s not too expensive and you can create a new faster instance later if you need to. At this point your monthly estimated cost should be $7-8.
  • Within the OS and storage tab:
    • Click Deploy Container. For Container image, enter the full name of your generated image, which looks like gcr.io/${PROJECT}/${REPO}:latest. Click Select to close the container dialog.
  • Within the Data protection tab:
    • Under Back up your data select No backups.
  • Within the Networking tab:
    • Under Firewall, click to Allow HTTP traffic.
    • Click the default under Network interfaces, and under External IPv4 address select Reserve static external IP address. In the dialog that appears, enter a name (such as web-server-ip), a reasonable description, and click Reserve. Click Done to close the Edit network interface editor.
    • NOTE: External IP addresses are only free as long as they are attached to a running GCE machine. Try not to create create more than one or two external addresses, and always keep them attached to running machines. You can view and release IPs you have reserved here. Creating unused external IPs without cleaning them up will be viewed as a sign of poor project health, and graded accordingly.
  • Within the Advanced tab:
    • Under Metadata click Add item and enter a Key of google-logging-enabled and Value of true. This will allow your Docker container logs to propagate to Google Cloud’s Logs Viewer.
  • Click Create to create your instance.

Once your instance finishes starting, you can access your server on port 80 of the External IP shown in the table by clicking the linked IP adddress in the table. If something isn’t working, you can start troubleshooting by connecting to the instance over SSH:

$ gcloud compute ssh <instance_name>
web-server ~$ docker ps
web-server ~$ docker logs <container_name>

If your server is up and running, returning responses, you’re done! Submit any config changes, and have the TL fill out the team submission.

Grading criteria

The minimum requirements for this assignment are drawn from the instructions above. The team grading criteria includes:

  • Correct refactoring
  • Successful update of Dockerfile
  • Server builds without failure
  • Successful deployment of server on GCP
  • Server correctly implements the HTTP Echo protocol (reads full request, sends valid 200 OK response with correct headers and body).
  • Server can be run with a simple command (e.g. ./webserver <config_file> or similar)
  • The port is configurable via config file

Individual Contributor criteria includes:

  • Code submitted for review (follows existing style, readable, testable)
  • Addressed and resolved all comments from TL

Tech Lead criteria includes:

  • Kept assignment tracker complete and up to date
  • Maintained comprehensive meeting notes
  • Gave multiple thoughtful (more than just an LGTM) reviews in Gerrit

General criteria includes how well your team follows the class project protocol. Additional criteria may be considered at the discretion of graders or instructors.

Submit your assignment

Everyone should fill out the submission form before 11:59PM on the due date. We will only review code that was submitted to the main branch of the team repository before the time of the TL’s submission. You may update your submission by re-submitting the form, which will update the submission time considered for grading purposes if you are the TL.

Late hours will acrue based on the submission time, so TL’s should avoid re-submitting the form after the due date unless they want to use late hours.


Back to top

“You may think using Google’s great, but I still think it’s terrible.” —Larry Page

Page last modified: October 28, 2025.