preface

In this article, I want to summarize my experience in designing RESTful apis.

Some specifications may differ from standard specifications, but all considerations are based on “reducing rework and increasing readability and maintainability.” Having said that, I’ve always felt that there’s really no obvious accepted specification for RESTful API design (if you’re referring to the inventor’s paper, not many people have read it in detail, and the author just came up with a set of concepts). The online tutorials, it seems, are all the same (I seriously suspect: “borrowed or copied” from Mr. Ruan yifong’s articles), stiff and rigid, and a little dogmatical (has anyone ever doubted them? I didn’t have much fun designing the API by them anyway).

Above, not all negation, good things to fully absorb, bad things, to integrate their own understanding, to transform.

Understanding RESTful apis

“RESTful is the abstraction of resources”, “combines the characteristics of HTTP” and so on. But these are just useless cliches with no nutritional value, and I want to talk about this in a different way.

Since this is an API, it generally follows the general pattern of apis:

ResultType ApiName(ParamType ) 1. Interface parameters, known as parameters. It can be a string, an int, or anything else you can call an argument. 2. Value returned by the interface. It can be a string, an int, or anything else you can call a return value. 3. Interface name (Signature)Copy the code

Let’s look at how RESTful fits into this pattern:

HttpResponse URL(HttpRequest) 1. HttpRequest: includes the request header, URL parameters, request body parameters 2. HttpResponse: includes the response header, response bodyCopy the code

In this sense, the RESTful API is just a special API, and the general API design principles apply to RESTful, but in a non-transformed form.

So what are the general criteria we have? Something like this:

  1. The interface name must be clear. Generally speaking, do the “verb-object phrase”.
  2. The fewer the interfaces, the better. Three is worse than two, two is worse than one, one is worse than none, the best API is “no API”.
  3. There are definite inputs and outputs. There is always a return value that tells the caller what I have done and how WELL I have done it: feedback.

Here’s a look at how these standards affect the following 🙂

URL design, and its antipatterns

The URL is the interface signature, and the signature must be clear and unambiguous.

There is a uniform prefix & versioning

If the backend architecture is servized, and there is a chance that each service will provide a common RESTful API to the outside world, it would be good to have a uniform prefix format, such as:

/SERVICE_NAME/v1/users
or
/APP_NAME/v2/users
Copy the code

As far as possible short

There are different ways to understand the same resource. Such as:

User -- 1:N --> Server-- 1:N --> Client... /users/{user_id}/ Servers /{server_id}/clients 2. /clients Option 1 is preferred. But option 2 is also a good choice. Anyway, it's a matter of taste.Copy the code

As few as possible

The smaller the number of interfaces, the better. Merge the interfaces that can be merged. For example, here’s the situation:

GET /users/{id} GET /users/{id} GET /users/{id} GET /users/{id} So only keep the batch interface, query one, with the URL parameter passed.Copy the code

A situation like this:

PUT /users/{id} PUT /users/{id} PUT /usersCopy the code

And here’s the extreme:

DELETE /users/{id} If you want to delete 100 users at a time, do you want the front end students to tune the interface 100 times? One more call, one more risk (such as network problems), this time don't keep RESTful those dogma, the usability of the interface, efficiency, more important. In this case, it is better to design the deletion {POST /users_deletion {in the DELETE interface. (We will not discuss whether the DELETE interface can send the Request body.)"user_ids"[1, 2, 3, 4, 5]}Copy the code

Return value design

As mentioned earlier, in HttpResponse, we can use:

Response Headers can do a few articles, such as a custom Header Status Code. According to the basic specifications, the 404 of the 404, the 200 of the 200 Response body are basically around this articleCopy the code

The Response body should not only be able to return information normally, but also tell the reason (error code) and details of the error if there is an error. So we could design something like this:

{success Boolean"is_success": how much is the error code number | null"err_code": error message string | null"err_msg"Details: error (optional) a string | null"err_detail": when the error of which service string | null"provider": Indicates the data that is returned normally"response_data": {}}Copy the code

In this way, the front-end call API, there are rules to follow, not blind.

Field Naming convention

There is no clear specification, but try to follow the style of the database, namely: underline style. This may be handy when serializing the entire Model.

Other specifications

The interface current limiting

Reference GitHub style.

Interface security

This is not systematic, you can refer to the relevant articles on the network.