background

The company I work for is an outsourcing company. There is no fixed combination of front and back end personnel and they all follow the project, so all the back end/front end developers have poor communication, and everyone has different understanding of the interface, which leads to a large amount of time spent in interface joint adjustment during the development process. The team held an internal meeting to discuss the interface standardization. As a front-end staff member, I put forward my own views, which are here for your reference.


How do I normalize interfaces

This is because everyone has different understanding of their own language, different familiarity with HTTP protocol, different thinking logic, and different development experience. People with ideas for interface specifications should present their own ideas and give their own reasons. Let others evaluate, discuss a uniform set of rules, and eventually unify into an internal standard. After the formation of a unified standard by the relevant personnel to write examples. For example, the front-end should provide sample code for GET request against jquery. ajax, FETCH, AXIos and other request libraries. Later directly refer to the sample code for development.

Because each project has many different ways to define the interface, ACCORDING to my previous experience, FROM the request method, request header, request body, response status code, response body and other aspects of the interface specification about their own views.

My understanding of standards

Our different projects use two types of request:

  • The GET and POST
  • GET, POST, PUT, DELETE

If the former is used, the action to be performed should be specified in the URL of the POST, while the latter need not be specified.

POST /api/user/addHTTP / 1.1POST /api/user/setHTTP / 1.1POST /api/user/deleteHTTP / 1.1In this example, the convention PUT is added, and POST is modified
POST /api/user HTTP/1.1
PUT /api/user HTTP/1.1
DELETE /api/user HTTP/1.1
Copy the code

As to whether to use the former or the latter, I prefer the former. If the latter is used, when to use POST and when to use PUT, some information is searched but not understood.

Interface URL

Interface URL should be known by name, there are certain rules. I don’t know much about it here, so I won’t say too much about it.

Conventions for data types

There should be no undefined in the front-end request because the data type is not supported (nor is it supported by JSON) on the back-end. If the content-type is multipart/form-data, the front end should not pass null because it will be converted to a string and the back end cannot determine whether it is user input or null.

Each project should specify what the following data means when requested

  • What does a null data type represent
  • What does an empty string type represent

A GET request

role

GET requests should read data and should not cause any “side effects”. It is important to note that the browser has a limit on the URL length. If the URL length is too long, it may cause unexpected consequences. You can use POST/PUT for query.

way

The parameters of a GET request should be placed in the REQUEST URL, not in the request body. For example, here is a standard GET request (irrelevant HTTP header fields removed)

GET /api/user? userId=12345HTTP / 1.1Host: http://www.example.com
Copy the code

POST/PUT/DELETE request

All three request methods pass parameters in the same format. The following uses POST as an example. The POST type is used in a variety of ways, and I’ve seen a variety of weird ways, but it’s also the one that takes the most time, which can seriously affect development progress. I’m only going to talk about what I think is the standard way.

role

POST requests are used to add, modify, or delete data and, in rare cases, to query data.

way

The parameters of the POST request must be placed in the request body. POST requests can be made in four ways:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json
  • text/xml

These are controlled by the Content-Type header field in the HTTP header.

multipart/form-data

The one we use most today is multipart/form-data.

POST /api/user/setHTTP / 1.1Host: http://www.example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2KbanAZwv0mKceX0

------WebKitFormBoundary2KbanAZwv0mKceX0
Content-Disposition: form-data; name="userName"Zhang SAN------WebKitFormBoundary2KbanAZwv0mKceX0
Content-Disposition: form-data; name="userId"

123456
------WebKitFormBoundary2KbanAZwv0mKceX0--
Copy the code

This approach is not suitable for passing complex data types, such as an interface that needs to modify multiple users simultaneously:

const userList = [
  {
    userID: 123.userName: 'Joe'.isAdmin: true}, {userID: 456.userName: 'bill'.isAdmin: false,},];Copy the code

So that’s the only way to do it in a POST request

POST /api/userlist/setHTTP / 1.1Host: http://www.example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2KbanAZwv0mKceX0

------WebKitFormBoundary2KbanAZwv0mKceX0
Content-Disposition: form-data; name="userID"

123.456
------WebKitFormBoundary2KbanAZwv0mKceX0
Content-Disposition: form-data; name="userName"Tom, Tom------WebKitFormBoundary2KbanAZwv0mKceX0
Content-Disposition: form-data; name="isAdmin"

1.0
------WebKitFormBoundary2KbanAZwv0mKceX0--
Copy the code

More importantly, there is no support for data types in this approach, and any data that is passed in will be converted to string type. The back end often uses 1 for true, requiring arrays or objects to be split apart.

application/json

This is what I recommend as an effective remedy for multipart/form-data. But for some reason our team doesn’t use that anymore. Application/JSON also has a drawback that it does not support uploading files (special methods are not recommended here). If you want to upload files, use multipart/form-data.

Here is an example request

POST /user HTTP/1.1 Host: http://www.example.com Content-type: application/json; Charset = utf-8 [{" userID ": 123," userName ":" zhang ", "isAdmin" : true}, {" userID ": 456," userName ":" bill ", "isAdmin" : false}]Copy the code

The response

I don’t know what status codes the server will return for different processes, but I won’t discuss them here. We return a logical status code with a message MSG, and the response body looks like this.

{"code":200."msg":"Handled successfully!"."data": {}}Copy the code

Add some restrictions to this:

It is recommended that the data field always be of object type

Easy to extend, for example the current interface is a user list page and data uses arrays. The v2 interface adds paging queries, so data must be an object type.

If the field is of complex type, null is not allowed

Complex types include arrays and objects. To make it easier to read, the JSON string is converted to a JS object.

const resBody = {
  code: 200.msg: 'Processing successful'.data: {
    list: [{userID: 123.userName: 'Joe',},],},};Copy the code

Return if no data is available

const resBody = {
  code: 200.msg: 'Processing successful'.data: {
    list: null,}};Copy the code

In this case, when the front end iterates through the list, null will cause an error in the code, and the data type of the field should always remain the same. The correct return method is as follows.

const resBody = {
  code: 200.msg: 'Processing successful'.data: {
    list: [].}};Copy the code

other

If you have additional additions or corrections, please feel free to comment at 👏.

The resources

  • Hypertext transfer protocol
  • The HTTP header fields
  • There are four common ways to submit data through POST
  • JSON

update:2019/06/27

I’ve heard about Restful apis before, but I ignored them when I wrote the article and didn’t read the relevant documentation. I think the ultimate goal of standardization is to rely on open source specifications. Rather than make a set of internal standards, so the starting point of this article is not correct.

You should use a mature specification to find the rules you need, and the prerequisite for judging whether a rule is usable is whether the benefit of the rule outweighs the impact of the rule on development.

PS: I’ll take a look at Restful apis and Google API Design when I have time.