CHAPTER 1
We can define Representational State Transfer (REST) as an architectural style that sits on top of a series of principles. The rise of REST in the last few years is tied to the API design that most web applications offer to extend their functionalities. Even if it is not tied to HTTP, REST is generally associated with web applications. HTTP happens to fit well with the REST principles.
The principles of REST are Uniform Interface, Stateless, Cacheable, Client-Server, Layered System, and Code on Demand.
This is a short introduction to REST architecture. What we need to understand is the basic principle and a general picture of a REST application. The idea of REST over HTTP is to use the protocol’s functionality as much as possible so that we don’t have to reinvent the wheel.
In the next chapters we will see how ASP.NET Web API helps in building web applications that match the REST constraints.
At the center of REST are the resources, the “things” that we want to manage using the API. A resource could be a blog post, a customer, a document, and in general, anything that we want to expose. A resource has an identifier, like a record in a database has a primary key. In the same way, a resource has a URI that identifies the resource itself. The URI is not a representation of the resource that can assume different formats. It is just an identifier that we can use to access the resource.
We can request the resource with the URI, and what we obtain is a representation of that requested resource in a particular format. The format is negotiated between the client and the server and could be anything from the most used XML and JSON, to HTML, PNG, CSV, or other binary formats. With the representation of the resource, the client can manipulate the state and operate with the resource using the server if it has the rights to do so.
Statelessness is a fundamental principle for a REST application; the server should never store information about the clients. This means that when a request comes to the server, the server loads the resource from storage (typically a database) and sends back the representation to the client. That is the state of the resource. If a second later the state on the storage changes because of a new request that arrives, the client is not meant to know.
Stateless also means that the server should never use sessions or other mechanisms to store client information, and every request is not correlated with past or future requests.
The client can cache the resource, and the server should provide information about the cacheability of the resource itself. If we manage the cache correctly, we can save several trips to the server.
What the client sees is the URI and the representation of the resource—that’s all. The client can’t see (and surely isn’t interested in seeing) where the resource is stored. On the other hand, the server should not know if the client has a particular resource, and if the interface doesn’t change, internals of the server and client could change without breaking anything.
The client knows very little about the server; it doesn’t know, for example, if it is directly connected to the server or if it arrived at the server by passing through a proxy or other intermediary server (balancer, etc.).
The server can extend the functionality of the client by passing executable code. For example, a server can send JavaScript to the client so that it can do some type of operation on the data.
If we read these principles carefully, we note that their primary focus is scalability. The fact that the server should not store client information permits it to save memory. The layered system permits us to use cache servers as a load balancer to obtain scalability. Adding new servers while adhering to the client-server principles allows us to change the implementation (for example, going from a SQL database to NoSQL storage) without the client’s knowledge.
But how do we obtain this and how does it work? In the original paper outlining REST, Roy Fielding doesn’t tie the REST architecture to HTTP, but as stated previously, HTTP seems perfect to build a REST API since most of the things that REST states are already built in the protocol itself (cacheability, for example).
The web itself is REST: we have the URL that is the identifier of the page that we need, we type the URL in the browser to obtain a representation in HTML format, and we use a link to transfer the state to another page.
An aspect of REST that contrasts with SOAP (RPC) is that the operation on the resource is based on the HTTP verb used in combination with the URI.
HTTP has the notion of verbs. We are used to GET and POST since the browser manages these two verbs, but others are specified in the HTTP specification (RFC 2616) that can be used for other operations.
The complete list of verbs is: OPTIONS, GET, HEAD, POST, PUT, PATCH, DELETE, TRACE, and CONNECT.
These can be used with their semantic meaning, so when we need to read a resource, we can use the GET method, and when we need to delete a resource, we can use a DELETE, and so on.
HTTP verbs and meanings
Verb | URI | Description |
GET | /posts | Get the post list. |
GET | /posts/42 | Get a single post (the one with id 42). |
DELETE | /posts/42 | Delete the post 42. |
POST | /posts | Create a post. |
PUT | /posts/42 | Update the post. |
PATCH | /post/42 | Partial update. |
OPTIONS | /post/42 | Retrieve the available operation on the resource. |
HEAD | /post/42 | Return only the HTTP header. |
As shown in the previous table, by using the right URI and the correct verb, we have the CRUD (Create, Read, Update, Delete) operations ready to be used.
After a request is issued to the server, the server parses it and builds the response to return the data or result to the client. Every response is represented with a state, and an HTTP status should be semantically used to inform the client of the result.
There are five types of HTTP status codes:
Every group has its own details. For example, if the request goes well, the status code of the response is 200 OK after a GET request, but is 201 CREATED after a POST request. In the case of a client not authorized to issue a request, 403 Forbidden should be used; if a resource could not be found, a 404 Not found is used.
So, the general case is to find the HTTP status that best represents the current situation. The complete list of status codes can be found in Appendix A at the end of the book.
The GET operation is used to read a resource. The URI specifies the resource that we are reading, and we can use the Accept header to ask for a specific format. For example, consider this HTTP request:
GET /posts HTTP/1.1 Accept: application/json |
The GET request is instructing the server to return the content of the “posts” resource in JSON format.
GET /posts/42 HTTP/1.1 Accept: text/xml |
This GET request asks the server to return a Post resource with an identifier of 42 in the XML format.
The GET operation is considered a safe one, so it should never modify the state of the resource.
The server generally responds to a GET request with the HTTP status 200 OK if everything goes well, 404 Not found if the URI points to a non-existent resource, or 400 Bad request if the request is not well formed.
HATEOAS (Hypermedia as the Engine of Application State) |
When POST is used to create a resource, the resource data is sent to the server as part of the request’s body. The server responds with a status 201 CREATED if everything goes well. When a new resource is created, it’s a best practice to use the Location header in the response to specify the URI of the newly created resource. This adheres to the HATEOAS principle.
PUT is used to modify the resource. The URI specifies the resource that we want to modify and the body contains the new resource values. The response HTTP status code should be 200 OK or 204 No content if the response doesn’t contain the modified resource. It is not necessary to return the URI of the resource itself in the Location header because the client already knows it. PUT has to be idempotent, which means that the result of a successful request is independent of the number of times it is executed. It has to be possible to place two equal calls to the server, and the server should not return errors; the second call simply redoes the update even if it does not change the resource.
DELETE is used to delete the resource. The result could be a 200 OK or 204 NO CONTENT if the response does not contain a body. It could be 404 Not Found if the URI is not correct and the resource cannot be found.
This is just a short introduction to REST, just what we need to correctly use the ASP.NET Web API. REST is a vast topic and entire books have been written about it. We just examined some principles and how the HTTP verbs are used to work with resources.