At current, RESTful is the most popular API design specification for the design of Web data interfaces.

In this post, I'll summarize the RESTful design details and show you how to design an API that is easy to understand and use in this article.

1. Design URL

1.1 verb + object

The core idea of ​​RESTful is that the data manipulation instructions issued by the client all have the structures of "verb + object". For example, there is a command of GET /articles , in which GET is a verb and /articles is an object.

Usually, verbs have five HTTP methods that correspond to CRUD operations.

GET: Read

POST: Create

PUT: Update

PATCH: Update, partial update usually

DELETE: Delete

Verbs should be capitalized according to the HTTP specification.

1.2 Override verbs

Some clients can only use the two methods of GET and POST . Thus the server has to accept to use the POST to simulate the other three methods ( PUT , PATCH , DELETE ).

You can tell the server which verb should be used to override the POST method by adding the property of X-HTTP-Method-Override to the HTTP request sent by the client.

POST /api/Person/4 HTTP/1.1 X-HTTP-Method-Override: PUT

In the above code, X-HTTP-Method-Override is used to specify that the method being requested is PUT , not POST .

1.3 Objects must be nouns

Objects are the URLs of the API, and HTTP verbs act on the objects. It should be nouns, not verbs. For example, the URL /articles is correct, while the URLs below are wrong, as they are not nouns.

/getAllCars

/createNewCar

/deleteAllRedCars

1.4 plural URL

Since the URL is a noun, which form should we use for the noun, plural or singular?

There is no uniform rule about this, but the common operation is to read a collection, such as GET /articles (to read all articles), which should be plural obviously.

For the sake of consistency, it is recommended to use the plural form for the URL, for GET /articles/2 is better than GET /article/2 .

1.5 Avoid multi-level URLs

Often, resources need to be classified at multiple levels, so it tends to be written out multi-level URLs. For example, when you want to get a certain type of articles written by a certain author:

GET /authors/12/categories/2

you can find that it is not conducive to expansion, and the semantic isn't clear either.

So it's better to use query strings to express all levels except the first level.

GET /authors/12?categories=2

Here's another example of querying published articles. You might design the URL as below.

GET /articles/published

The writing of using query string is significantly better.

GET /articles?published=true

2. Status Codes

2.1 Status codes must be accurate

The server must respond to every request from the client. The response includes two parts, the HTTP status code and the data.

The HTTP status code is a three-digit number, which can be divided into five categories.

1xx: related information

2xx: Operation succeeds

3xx: Redirect

4xx: Client error

5xx: Server error

These five categories contain a total of more than 100 status codes covering most of the situations that you may encountered. Each status code has a standard (or agreed) interpretation. The client only needs to look at the status code to determine what happened, so the status code returned from the server should be as accurate as possible.

API doesn't require 1xx status codes. So I'll give an accurate description for the other four types of status codes below.

2.2 2xx status codes

The 200 status code indicates that the operation succeeds, and different methods can return a more accurate status code.

GET: 200 OK

POST: 201 Created

PUT: 200 OK

PATCH: 200 OK

DELETE: 204 No Content

In the above code, the 201 status code returned by POST indicates that a new resource has been generated; the 204 status code returned by DELETE indicates that the resource no longer exists.

In addition, the 202 Accepted status code indicates that the server has received the request, but has not processed it yet and will process it in the future. So it's usually used for asynchronous operations. Below is an example.

HTTP/1.1 202 Accepted { "task": { "href": "/api/company/job-management/jobs/2130040", "id": "2130040" } }

2.3 3xx status codes

API doesn't need to use 301 status code (permanent redirection) and 302 status code (temporary redirection, the same as 307 ), because these status codes can be returned by the application level, and the browser will jump away directly, so you can ignore these two cases at the API level.

The 3xx status code mainly used by API is 303 See Other , which indicates that another URL is referenced. It has the same meaning as 302 and 307 , and also means temporary redirection, with the difference that 302 and 307 are used for GET requests and 303 is used for POST , PUT , and DELETE requests. After receiving 303 , the browser will not jump automatically, but will let the user decide what to do next. Below is an example.

HTTP/1.1 303 See Other Location: /api/orders/12345

2.4 4xx status codes

The 4xx status codes indicate client errors:

400 Bad Request : The server doesn't understand the client's request, and doesn't do anything.

: The server doesn't understand the client's request, and doesn't do anything. 401 Unauthorized : The user doesn't provide authentication credentials, or isn't authenticated.

: The user doesn't provide authentication credentials, or isn't authenticated. 403 Forbidden : The user has been authenticated but doesn't have the required permissions to access the resource.

: The user has been authenticated but doesn't have the required permissions to access the resource. 404 Not Found : The requested resource doesn't exist or is not available.

: The requested resource doesn't exist or is not available. 405 Method Not Allowed : The user has been authenticated, but the HTTP method used is not within his permissions.

: The user has been authenticated, but the HTTP method used is not within his permissions. 410 Gone : The requested resource has been transferred from this address and is no longer available.

: The requested resource has been transferred from this address and is no longer available. 415 Unsupported Media Type : The return format requested by the client is not supported. For example, API can only return JSON format, but the client requires an XML format.

: The return format requested by the client is not supported. For example, API can only return JSON format, but the client requires an XML format. 422 Unprocessable Entity : The attachment uploaded by the client could not be processed, causing the request to fail.

: The attachment uploaded by the client could not be processed, causing the request to fail. 429 Too Many Requests : The number of requests from the client exceeds the limit.

2.5 5xx status codes

The 5xx status codes indicate server errors. In general, API won't expose the details of the server to the user, so only two status codes are enough.

500 Internal Server Error : The request from the client is valid, but an exception occurred while the server is processing.

: The request from the client is valid, but an exception occurred while the server is processing. 503 Service Unavailable : The server cannot process the request, and it is generally used when the website is in a maintenance status.

3. Responses from the server

3.1 Do not return pure text

The data format returned from the API should not be plain text, but rather a JSON object, so as to return standard structured data. Therefore, the Content-Type property of the HTTP header responded from the server should be set to application/json .

It must tell the server explicitly that it can accept the JSON format if the client has the request, which means that the ACCEPT property of the requested HTTP header should also be set to application/json . Here is an example.

GET /orders/2 HTTP/1.1 Accept: application/json

3.2 Do not return 200 status code when an error occurs

An inappropriate approach is to return a 200 status code even if an error occurs, and to place the error message in the data body as shown below.

HTTP/1.1 200 OK Content-Type: application/json { "status": "failure", "data": { "error": "Expected at least two items in list." } }

In the above code, only after parsing the data body can you know that the operation has failed.

In fact, this kind of practice cancels status codes, which is inadvisable. The correct approach is to use the status code to reflect the error that occurred, and to return the detailed error message in the data body. Here is an example.

HTTP/1.1 400 Bad Request Content-Type: application/json { "error": "Invalid payoad.", "detail": { "surname": "This field is required." } }

3.3 Links

To use the API doesn't mean to know how to design the URL. So one of the solutions is to give relevant links in the response to facilitate the next step. Thus users can look for other URLs just by remembering one URL. This method is called HATEOAS.

For example, the APIs for GitHub are all in api.github.com . You can get other URLs by accessing it.

{ ... "feeds_url": "https://api.github.com/feeds", "followers_url": "https://api.github.com/user/followers", "following_url": "https://api.github.com/user/following{/target}", "gists_url": "https://api.github.com/gists{/gist_id}", "hub_url": "https://api.github.com/hub", ... }

In the above response, You can also get other more URLs by accessing one of the URLs. There is no need for the user to remember the URL design any more, as what the user only to do is to look it up step by step from api.github.com .

The format of HATEOAS hasn't been defined uniformly. You can find that GitHub puts them together with other properties in the above example. A better approach would be to separate related links from other properties.

HTTP/1.1 200 OK Content-Type: application/json { "status": "In progress", "links": {[ { "rel":"cancel", "method": "delete", "href":"/api/status/12345" } , { "rel":"edit", "method": "put", "href":"/api/status/12345" } ]} }

4. Reference