View on GitHub

APCSP Documentation

The documentation for the 2019-20 APCSP project

Routing

We route requests to their respective functions by the request path and the method being used. This allows us to have a server do multiple things, rather than just having one ultra-complex route. Routing by both path and method gives further specificity as each HTTP verb has its own intended use. The API is designed in a RESTful manner where there are routes to manage a set of a resource and to manage a single resource.

Path-Based

Path-based routing is the most basic form of routing where a server receives some path following the domain, like /api/users/1, and acts on the data passed. In order to do path routing, we use a library called Mux which has many routing capabilities though we only use the path routing. The library builds on top of the standard net/http library by adding path routing and path parameters. Path parameters are variables that are specified in the path instead of the body or query parameters. For example, a path template could be /users/{id}/posts, where a possible request could be /users/2/posts. In this case, the the variable would be id as it is surrounded by two curly braces {} and is able to change based on the given request.

We use path-based routing as the first level of specification. In order to tell the server to create, read, update, or delete a resource, the proper path specifying the resource must be given. Below are each of the paths for the four resources we have:

# User resource
/api/users
/api/users/{user}

# Chat resource
/api/chats
/api/chats/{chat}

# Message resource
/api/chats/{chat}/messages
/api/chats/{chat}/messages/{message}

# File resource
/api/files/{file}

In each of these, except for the files, there are two levels of specificity. The first one pertaining to the entire group of the resource, and the second pertaining to a single resource. The single resource is specified through path parameters which allows for the easy denotation of the resource.

Method-Based

Method-based routing is just as simple as path-based routing. While it is offered by Mux, we use a custom solution in order to implement it in the way we want. Our solution uses a switch statement that assigns a certain function to a HTTP verb. There are GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, and PATCH as defined in MDN. These are the possible options, but we only use GET, POST, PUT, and DELETE.

Each verb is used for a different purpose: GET for retrieving a resource, POST for creating, PUT for updating, and DELETE for deleting. In general, GET and POST will be used together when referring to a group of resources, rather than a specific resource. And for GET, PUT, and DELETE, they will be used together when referring to a specific resource. As you can see with GET, it can be used in both general and single contexts because you can describe a single item and a list of items.

The switch statement works by checking the method of the request and calling a specific function based on the method. In pseudo-code, the switch statement looks like this:

switch (request method) {
   case "GET":
       read_resource()
       break

   // NOTE: POST, PUT, and DELETE will not normally appear together as explained above
   case "POST":
       create_resource()
       break

   case "PUT":
       update_resource()
       break

   case "DELETE":
       delete_resource()
       break

   default:
       send_method_not_allowed()
}

For an implemented example, see users/exported.go, chats/exported.go, files/exported.go, and messages/exported.go.