Naming conventions
One of the keys to achieving a good RESTful design is naming the HTTP verbs appropriately. It is really important to create understandable resources that allow people to easily discover and use your services. A good resource name implies that the resource is intuitive and clear to use. On the other hand, the usage of HTTP methods that are incompatible with REST patterns creates noise and makes the developer's life harder. In this section, there will be some suggestions for creating clear and good resource URIs.
It is good practice to expose resources as nouns instead of verbs. Essentially, a resource represents a thing, and that is the reason you should use nouns. Verbs refer to actions, which are used to factor HTTP actions.
Three words that describe good resource naming conventions are as follows:
- Understandability: The resource's representation format should be understandable and utilizable by both the server and the client
- Completeness: A resource should be completely represented by the format
- Linkability: A resource can be linked to another resource
Some example resources are as follows:
Users of a system
Blogs posts
An article
Disciplines in which a student is enrolled
Students in which a professor teaches
A blog post draft
Each resource that's exposed by any service in a best-case scenario should be exposed by a unique URI that identifies it. It is quite common to see the same resource being exposed by more than one URI, which is definitely not good. It is also good practice to do this when the URI makes sense and describes the resource itself clearly. URIs need to be predictable, which means that they have to be consistent in terms of data structure. In general, this is not a REST required rule, but it enhances the service and/or the API.
A good way to write good RESTful APIs is by writing them while having your consumers in mind. There is no reason to write an API and name it while thinking about the APIs developers rather than its consumers, who will be the people who are actually consuming your resources and API (as the name suggests). Even though the resource now has a good name, which means that it is easier to understand, it is still difficult to understand its boundaries. Imagine that services are not well named; bad naming creates a lot of chaos, such as business rule duplications, bad API usage, and so on.
In addition to this, we will explain naming conventions based on a hypothetical scenario.
Let's imagine that there is a company that manages orders, offers, products, items, customers, and so on.
Considering everything that we've said about resources, if we decided to expose a customer resource and we want to insert a new customer, the URI might be as follows:
POST https://<HOST>/customers
The hypothetical request body might be as follows:
{
"fist-name" : "john",
"last-name" : "doe",
"e-mail" : "john.doe@email.com"
}
Imagine that the previous request will result in a customer ID of 445839 when it needs to recover the customer. The GET method could be called as follows:
GET https://<HOST>/customers/445839
The response will look something like this:
sample body response for customer #445839:
{
"customer-id": 445839,
"fist-name" : "john",
"last-name" : "doe",
"e-mail" : "john.doe@email.com"
}
The same URI can be used for the PUT and DELETE operations, respectively:
PUT https://<HOST>/customers/445839
The PUT body request might be as follows:
{
"last-name" : "lennon"
}
For the DELETE operation, the HTTP request to the URI will be as follows:
DELETE https://<HOST>/customers/445839
Moving on, based on the naming conventions, the product URI might be as follows:
POST https://<HOST>/products
sample body request:
{
"name" : "notebook",
"description" : "and fruit brand"
}
GET https://<HOST>/products/9384
PUT https://<HOST>/products/9384
sample body request:
{
"name" : "desktop"
}
DELETE https://<HOST>/products/9384
Now, the next step is to expose the URI for order creation. Before we continue, we should go over the various ways to expose the URI. The first option is to do the following:
POST https://<HOST>/orders
However, this could be outside the context of the desired customer. The order exists without a customer, which is quite odd. The second option is to expose the order inside a customer, like so:
POST https://<HOST>/customers/445839/orders
Based on that model, all orders belong to user 445839. If we want to retrieve those orders, we can make a GET request, like so:
GET https://<HOST>/customers/445839/orders
As we mentioned previously, it is also possible to write hierarchical concepts when there is a relationship between resources or entities. Following the same idea of orders, how should we represent the URI to describe items within an order and an order that belongs to user 445839?
First, if we would like to get a specific order, such as order 7384, we can do that like so:
GET https://<HOST>/customers/445839/orders/7384
Following the same approach, to get the items, we could use the following code:
GET https://<HOST>/customers/445839/orders/7384/items
The same concept applies to the create process, where the URI is still the same, but the HTTP method is POST instead of GET. In this scenario, the body also has to be sent:
POST https://<HOST>/customers/445839/orders/7384
{
"id" : 7834,
"quantity" : 10
}
Now, you should have a good idea of what the GET operation offers in regard to orders. The same approach can also be applied so that you can go deeper and get a specific item from a specific order and from a specific user:
GET https://<HOST>/customers/445839/orders/7384/items/1
Of course, this hierarchy applies to the PUT, PATCH, and POST methods, and in some cases, the DELETE method as well. It will depend on your business rules; for example, can the item be deleted? Can I update an order?