Many people involved in web development are no stranger to RESTful APIs. Different projects have a variety of different interface forms, some claiming to use RESTful, but not actually fully compliant with the specification, which makes me think, should we use the RESTful API style or not?

As an example, I believe you have seen many APIs in the following style:

Scenes Request Method Routing
Get a list of users GET /getUserList
Get information about a user GET /getUserInfo?id=1
Add a new user POST /createUser
Update a user POST /updateUser
Delete a user POST /deleteUser

This is the simplest CURD interface, and to be honest, I’m not opposed to this form of API, although it looks a bit cheesy, but at least see the name to know the meaning, except for the use of GET to get data, all other POST, simple and brutal, no big problem.

If we expand on this, the above form does not express the meaning of the interface better in complex cases, for example, if you were to write an interface to get a user’s friends list, it might be written like this

1
Get a list of a user's friends    GET   /getUserFriends?user_id=1

This type of naming leads to increasingly long interface names in complex cases. Readability becomes poor and at a glance it is not easy to see how the data relate to each other and is not well classified.

If RESTful is used, this form could be used:

1
Get a list of a user's friends   GET   /users/:id/friends

Traditional interfaces use a verb + interface name to convey meaning, while RESTful recommends using HTTP requests to define them, such as GET for getting data, POST for creating, PUT for modifying, and DELETE for deleting.

The above interfaces, if rewritten in RESTful form, would look like this:

Scenes Request Method Routing
Get a list of users GET /user
Get a user’s information GET /user/:id
Add a new user POST /user
Update a user PUT /user/:id
Delete a user DELETE /user/:id

There is also a disagreement about whether to use user or users, some people feel that the plural should be used as there are multiple users, so you have to use getUsers to get the users. The same problem exists with the names of data tables.

I think it depends on the name of the data table, if the data table is users then it is best to use the same for the interface, to be consistent.

As to whether or not to use plural data table names, many people have different opinions, so a clear and unified specification at the start of the project will do.

In addition, RESTful also recommends that the HTTP status code to distinguish the results, such as 200 means normal, 403 means no permission, the traditional interface is often uniformly used 200, and then in the response content to distinguish.

In short, RESTful was originally designed to treat these data entities as a resource, to locate the resource by URL, and to describe the operation using HTTP to achieve several goals:

  • look at the URL to know what to get
  • look at the HTTP method to know what to do
  • look at the HTTP status code to know what the result is

I’ve seen a lot of seemingly RESTful styles in my career, but in reality not exactly, for example PUT, DELETE where the id is passed as a query parameter rather than path:

1
Delete a user    DELETE    /user?id=1

There is also the interface is directly to all the parameters into the body inside the pass, although these ways can be said, and not trouble, because now many Web framework for these parameters are very convenient to deal with, but still feel incestuous, of course, sometimes forced, such as some table design without a single id primary key, only a composite primary key, which is difficult to use path this form.

It’s not perfect

The RESTful design specification is ideal, but not for all projects, as many interfaces are not purely CURD operations, it’s not just about inserting, deleting, updating, querying a table, which makes it difficult to convey meaning via URLs.

RESTful is more appropriate for interfaces that simply fetch and modify data, but when your interface contains very complex business logic, RESTful is very problematic and there is nowhere to start.

For example, an interface to get a nearby supermarket based on the user’s address might look like this if used in the traditional way

1
/getUserNearbySupermarket?user_id=1

If RESTful is used there is the question of whether this is designed around the user or the supermarket?

1
2
3
/user/:id/nearby_supermarket
/supermarket/nearby?user_id=1
/user_nearby_supermarket?user_id=1

Which of these 3 examples do you think is better? I have been struggling with this for a long time, but after referring to many cloud vendors’ APIs, I personally think the first one is more suitable.

Sometimes the four common methods of GET, POST, PUT and DELETE defined by the RESTful API do not meet all the application scenarios, or are not clear enough. For example, if the business has a scenario where the user’s blacklist is to be cleared, is this a PUT or a DELETE?

From the user’s point of view say PUT, because I am modifying the attributes attached to the user, but from the perspective of the blacklist is to delete the data, both have some justification.

Perhaps we could design it like this

1
POST    /user/:id/blacklist/empty

We can think of blacklist as a property of the user, and empty as an action, which is a bit clearer, and it makes little difference whether the method is POST or PUT.

Best Practices

For an open platform interface, say a cloud service provider, which needs to provide a corresponding sdk or api for users to use, it is recommended to use RESTful, in fact the api of a very cloud service provider is very standard RESTful style.

The cloud service itself is to provide resources, whether it is a server, IP, domain name, it is a network resource, and RESTful is born to describe the resources, and the operation logic of the cloud service is simple, there is no complex business logic, for the server is nothing but to create, view, modify, delete, restart, etc..

Previously used vultr’s API, is very standardized RESTful style, look very comfortable:

Scenes Request Method Routing
Get examples GET /instances
Get an example GET /instances/:id
Add an example POST /instances
Update an example PUT /instances/:id
Delete an instance DELETE /instances/:id
Start an instance POST /instances/:id/start
Batch start instances POST /instances/start

It is worth mentioning the “start” operation, which has 2 forms, one is to operate on a single instance, the parameters are placed inside the path, and the other is a bulk operation with multiple ids, when the parameters are placed inside the json body.

However, for many internal company system interfaces, RESTful is often not the best choice, if for the sake of simplicity and convenience, without regard to these messy specifications, I recommend using POST for everything except GET to get data.

Scenes Request Method Routing
Get a list of users GET /user
Add a new user POST /user
Update a user POST /user
Delete a user POST /user

For example, if you write the above, the first GET interface should support multiple parameter filtering, for example, you can write /user?id=1, which is equivalent to getting a single user. In addition to the GET request outside the query parameters are all put into the body, and the unified use of JSON form.

There is also a response to the question of status codes, I think it is more appropriate to unify the 200, in the response body inside another definition of code to express the results, that is, do not rely on the HTTP status code, although a little incompatible with the RESTful specification, but good compatibility, because you do not know which middleware will be how to deal with.

Summary

There is no clear answer to the question of whether to use a RESTful style API. If your application logic is simple, mostly for some data table additions, deletions and checks, you can consider using a RESTful style interface, on the contrary, if your application business logic is complex, you can also do without.

If you consider that this is an open API to the public, it is recommended to use the RESTful style, after all, this is an industry consensus. Using the getXXXByXXX style of routing is a bit unprofessional.

In fact, we can also use a mixture of the two, according to the actual situation to decide, after all, this is just an interface routing, there is no need to entangle too much, most Web frameworks support various forms of routing parameters, for simple CURD can use RESTful, for complex business logic is a special treatment.