“This is the fifth day of my participation in the August More Text Challenge. For details, see: August More Text Challenge.”

Network applications are divided into two parts: front end and back end. The current trend is that front-end devices are emerging all the time (mobile phones, tablets, desktops, other dedicated devices……) .

Therefore, there must be a unified mechanism for different front-end devices to communicate with the back-end. This led to the popularity of API architecture and even the idea of “API First”. RESTful API is a mature set of API design theories for Internet applications. See Understanding RESTful Architecture for an overview of how to understand this concept.

Today, I’m going to go into the details of RESTful API design and discuss how to design an API that makes sense and works well. My main references are two articles (1,2).

agreement

API communication protocol with the user, always using HTTPs protocol.

The domain name

Try to deploy the API under a private domain name.


https://api.example.com
Copy the code

If you are sure that the API is simple and will not be extended further, consider placing it under the primary domain name.


https://example.org/api/
Copy the code

Versioning

You should put the version number of the API in the URL.


https://api.example.com/v1/
Copy the code

Alternatively, put the version number in the HTTP header, but it’s less convenient and intuitive than putting it in the URL. Github takes this approach.

Path (Endpoint)

The path, also called “endpoint”, represents the specific URL of the API.

In a RESTful architecture, each URL represents a resource, so there cannot be a verb in the url, only a noun, and the noun often corresponds to the name of the table in the database. In general, tables in a database are “collections” of the same records, so nouns in the API should also be plural.

For example, if an API provides information about zoos, as well as information about various animals and employees, its path should look like this.

  • api.example.com/v1/zoos
  • api.example.com/v1/animals
  • Api.example.com/v1/employee…

HTTP verbs

The specific type of operation on the resource is represented by an HTTP verb.

There are five common HTTP verbs (the corresponding SQL commands in parentheses).

  • GET (SELECT) : Retrieves one or more resources from the server.
  • POST (CREATE) : Creates a resource on the server.
  • PUT (UPDATE) : UPDATE the resource on the server (the client provides the full resource after the change).
  • PATCH (UPDATE) : Updates resources on the server (the client provides changed properties).
  • DELETE (DELETE) : Deletes resources from the server.

There are also two less common HTTP verbs.

  • HEAD: Obtain the metadata of the resource.
  • OPTIONS: Gets information about which properties of the resource can be changed by the client.

Here are some examples.

  • List all zoos
  • POST/upshot: Build a new zoo
  • — love/love/love — it can be a powerful motivation for a zoos zoos
  • Updating information about a specific zoo (provide full information about that zoo)
  • PATCH /zoos/ID: update information about a specific zoo (provide partial information about that zoo)
  • DELETE/love/love for a zoo
  • List all the animals at a given zoo
  • DELETE/love/love/love/love/love/love/love/love/love/love

Information Filtering

If the number of records is large, the server cannot return them all to the user. The API should provide parameters to filter the returned results.

Here are some common parameters.

  • ? Limit =10: Specifies the number of records to return
  • ? Offset =10: Specifies the starting position of the returned record.
  • ? Page =2&per_page=100: Specifies the number of pages and the number of records per page.
  • ? Sortby = name&ORDER = ASC: Specifies which attribute to sort the returned results by, and in what order.
  • ? Animal_type_id =1: specifies the filter criteria

The design of the parameters allows for redundancy, that is, API path and URL parameters that occasionally overlap. For example, GET /zoo/ID/animals versus GET /animals? Zoo_id =ID has the same meaning.

Status Codes

The server returns a status code and a prompt message to the user. Common examples include the following (the HTTP verb for the status code is in square brackets).

  • 200 OK – [GET] : The server successfully returns the data requested by the user. This operation is Idempotent.
  • 201 CREATED – [POST/PUT/PATCH] : The user creates or modifies data successfully.
  • 202 Accepted – [*] : indicates that a request has been queued in the background.
  • 204 NO CONTENT – [DELETE] : the user successfully deletes data.
  • 400 INVALID REQUEST – [POST/PUT/PATCH] : The REQUEST sent by the user is incorrect. The server does not create or modify data. The operation is idempotent.
  • 401 Unauthorized – [*] : Indicates that the user does not have permissions (the token, user name, and password are incorrect).
  • 403 Forbidden – [*] Indicates that the user is authorized (as opposed to the 401 error), but access is Forbidden.
  • 404 NOT FOUND – [*] : The user made a request for a record that does NOT exist. The server did NOT perform an operation. The operation is idempotent.
  • 406 Not Acceptable – [GET] : The format that the user requests is Not available (e.g. the user requests JSON format, but only XML format).
  • Gone -[GET] : Indicates that the requested resource has been permanently deleted and will not be retrieved.
  • 422 Unprocesable Entity – [POST/PUT/PATCH] A validation error occurred while creating an object.
  • 500 INTERNAL SERVER ERROR – [*] : An ERROR occurred on the SERVER and the user cannot determine whether the request was made successfully.

See here for a complete list of status codes.

Error handling

If the status code is 4XX, an error message should be returned to the user. In general, return information with error as the key name and error message as the key value.


{
    error: "Invalid API key"
}
Copy the code

Returns the result

Depending on the operation, the results returned by the server to the user should conform to the following specifications.

  • GET /collection: Returns a list (array) of resource objects
  • GET/Collection /resource: Returns a single resource object
  • POST /collection: Returns the newly generated resource object
  • PUT/Collection/Resource: Returns a complete resource object
  • PATCH/Collection/Resource: Returns a complete resource object
  • DELETE /collection/resource: Returns an empty document

Hypermedia API

RESTful apis are better off using Hypermedia, that is, providing links to other API methods in the return results so that users can know what to do next without looking up documents.

For example, when a user makes a request to the root directory of api.example.com, such a document is obtained.


{"link": {
  "rel":   "collection https://www.example.com/zoos",
  "href":  "https://api.example.com/zoos",
  "title": "List of zoos",
  "type":  "application/vnd.yourformat+json"
}}
Copy the code

The above code indicates that there is a link property in the document that the user reads to know what API to call next. Rel represents the relationship between the API and the current url (collection relationship, and gives the url of the collection), href represents the PATH to the API, title represents the title of the API, and type represents the return type.

The design of the Hypermedia API is called HATEOAS. Github’s API is designed in this way, and a visit to api.github.com will yield a list of all available apis.


{
  "current_user_url": "https://api.github.com/user",
  "authorizations_url": "https://api.github.com/authorizations",
  // ...
}
Copy the code

As you can see above, if you want to get information about the current user, you should go to api.github.com/user, and you get the following result.


{
  "message": "Requires authentication",
  "documentation_url": "https://developer.github.com/v3"
}
Copy the code

The above code indicates that the server gave the prompt message and the url of the document.

other

(1) API authentication should use OAuth 2.0 framework.

(2) The data format returned by the server should be JSON rather than XML.