This article takes you to understand the Open API design specification in detail

Written in front:

The OpenAPI Specification (OAS) defines a standard, language-independent RESTful API interface specification, which allows both developers and operating systems to view and understand the functionality of a service without access to source code, documentation, or network traffic inspection (both It is convenient for humans to learn and read, and it is also convenient for machines to read). When an OAS is properly defined, developers can understand and interact with remote services with minimal implementation logic.

In addition, the document generation tool can use the OpenAPI specification to generate API documentation, and the code generation tool can generate server-side and client-side code, test code and other use cases in various programming languages.

insert image description here

background

Open API, like the front-end page, has always been the facade of the product. If the Open API is not standardized, it will reduce the professionalism of the product. In the cloud scenario, many users will choose to build their own portals to connect to the Open API of cloud products. This appeals to us to build a mature Open API mechanism.

From a business perspective, there are some guiding principles to guide us to improve the Open API mechanism:

  • The interface used by the front-end page and the interface provided by the Open API are the same set of interfaces
  • Any front-end page interface should have a corresponding Open API

Recently, due to business needs, the cloud product CSB I participated in research and development needs to open the Open API to the outside world. It was not difficult at first, because the Open API opening mechanism inside Alibaba Cloud is very mature, and I don’t need to design it at all, but this time the demand is mainly For some independent deployment scenarios, we need to design a set of specifications by ourselves, which means that we need to impose some normative constraints on Open API. From a technical perspective, Alibaba Cloud has many API open standards for our reference. Some open source The Open API documentation of the product is also very complete.

In short, on the one hand, I will take its essence, and on the other hand, I must consider the particularity of the output form of my own products. This article will try to discuss a suitable Open API specification around many factors.

Open API Design Considerations

What exactly should a complete Open API specification regulate?

From a design point of view, you need to consider: naming specification, composition specification, path specification, entry and exit parameter specification, data type specification, unified return value specification, error code specification, and pagination specification.

From the perspective of the team, whether the back-end primary and intermediate development and front-end R&D in the team have enough experience to comprehend and implement the formulated API specification. At the same time, with the flow of personnel, whether this Open API specification can be passed on well.

From an industry perspective, it is necessary to consider whether the market for products that provide Open API is mature, and the API style may already have a corresponding specification.

From a product point of view, the API style suitable for each product is different, and the following will focus on this point of view.

In short, the design of Open API is difficult to form a conclusion. Before I introduce the Open API specification that my product finally adopts, I will first talk about some familiar concepts, such as restful.

The restful specification war

Where there are people, there will be rivers and lakes.

The same is true where there is code.

If you are in the code circle, you must have heard of the restful specification:

  • CRUD should be declared as: POST, DELETE, PUT, PATCH, GET

  • Verbs should not appear, and verbs are uniformly represented by HTTP Method

  • Reflects the abstraction of "resources"

  • Use pathVariable, queryParam, header, statusCode to express many business semantics

The restful specification seems beautiful, but if you really try to implement it, you will definitely encounter some similar problems:

  • Taking the user login interface as an example, it is difficult to map this type of interface to the addition, deletion, modification and query of resources
  • Take querying the error rate of interface requests in the last 7 hours as an example, complex query scenarios such as graphQL often require a json structure, which cannot be achieved by GET, and only POST can be passed

Based on this, the restful specification gradually has voices of opposition:

  • Forcing all things to be "resourced" is against the common sense of development, and the interface may not be mapped by simple addition, deletion, modification and query
  • Complex query semantics may not necessarily be expressible with GET

There are many supporters of the restful style who criticize these objections. In the community, it is inevitable that "the ones who reject the restful style are mainly low-level architects and front-end and back-end programmers who do not want to make progress. It is a human problem not to know how to design. Normative issues” and such remarks. At the same time, restful is sublimated: the retrieval of complex parameters should be classified as post in the restful semantics, because this behavior is not the positioning of resources (GET), but the retrieval of resources (POST)

This obviously stimulated the nerves of opponents of the restful style, and said with disdain: Oh, stupid restful fundamentalists.

I don't know if you are a supporter or opponent of restful? Or, neutral.

The restful debate is over for the time being. This debate is purely fictitious, and the judges don't have to worry about it. No matter how you look at restful, you can act as a neutral person in my discussion below, otherwise the effect will be halved.

ROA and RPC

API design does not only have a specification of restful. From a larger perspective, mainstream API design styles can actually be divided into

  • Resource-oriented design, namely ROA (Resource oriented architecture)
  • Process-oriented design, that is, RPC (Remote Procedure Call)

Restful is a typical example of ROA style, while RPC style is relatively less well-known, but in fact, most system interfaces may be RPC style, but the concept of RPC style is not well known.

Taking the CRUD of the user module as an example, compare the following two styles:

ROA style

CREATE USER (POST)

Request:
POST /users

{
    
    "name": "kirito", "age": 18}

Response:
HTTP 201 Created

{
    
    "id": 1, "name": "kirito", "age": 18}

Query users (GET)

Request:
GET /users/1

Response:
HTTP 200 OK

{
    
    "id": 1, "name": "kirito", "age": 18}

Query user list (GET)

Request:
GET /users

Response:
HTTP 200 OK

{
    
    [{
    
    "id": 1, "name": "kirito", "age": 18}], "next": "/users?offset=1"}

Create/modify user (PUT)

Request:
PUT /users/1

{
    
    "name": "kirito", "age": 19}

Response:
HTTP 200 OK

{
    
    "id": 1, "name": "kirito", "age": 19}

Modify user (PATCH)

Request:
PATCH /users/1

{
    
    "age": 20}

Response:
HTTP 200 OK

{
    
    "id": 1, "name": "kirito", "age": 20}

delete user (DELETE)

Request:
DELETE /users/1

Response:
HTTP 204 No Content

The ROA style and the restful specification describe the same thing. To facilitate the comparison with the RPC style interface, here are some noteworthy points of the above example:

  • Use HTTP response codes (200, 201, 204) to complete the mapping between HTTP semantics and business semantics, and exception flows also appear 404, 401, etc. (For space considerations, this article does not introduce exception flows)
  • The PATCH part modifies the resource, and the request body is the content of the modified part; PUT creates/modifies the resource, and the request body is the entire content of the new resource
  • id is a resource locator, while age and name are attributes

RPC style

CREATE USER (POST)

Request:
POST /user/createUser

{
    
    "name": "kirito", "age": 18}

Response:
HTTP 200 OK

{
    
    "code": 0, "message": "", "data": {
    
    "id": 1, "name": "kirito", "age": 18}}

query user (POST)

Request:
POST /user/getUser

{
    
    "id": 1}

Response:
HTTP 200 OK

{
    
    "code": 0, "message": "", "data": {
    
    "id": 1, "name": "kirito", "age": 18}}

Query user list (POST)

Request:
POST /user/listUsers

Response:
HTTP 200 OK

{
    
    "code": 0, "message": "", "data": {
    
    "user": [{
    
    "id": 1, "name": "kirito", "age": 18}], "next": "/user/listUsers?offset=1"}}

modify user (POST)

Request:
POST /user/modifyUser

{
    
    "id": 1, "name": "kirito", "age": 19}

Response:
HTTP 200 OK

{
    
    "code": 0, "message": "", "data": {
    
    "id": 1, "name": "kirito", "age": 19}}

Modify Username (POST)

Request:
POST /user/modifyUserAge

{
    
    "id": 1, "age": 20}

Response:
HTTP 200 OK

{
    
    "code": 0, "message": "", "data": {
    
    "id": 1, "name": "kirito", "age": 20}}

delete user (DELETE)

Request:
POST /user/deleteUser

{
    
    "id": 1}

Response:
{
    
    "code": 0, "message": ""}

The RPC style is not like the restful ROA style. There are some conventions and specifications. Each business system has differences when it is implemented. Therefore, this is just the author's personal experience. I hope readers can seek common ground while reserving differences:

  • user is the module name, no need to use plural form like ROA style
  • Use a clear verb-object structure instead of mapping CRUD to HTTP Method, HTTP Method uses POST uniformly, and query scenarios can also use GET
  • The return value carries code, message and data to map the response status and response information. Generally, you can define the status code of the code yourself. In this article, 0 is used to indicate that the request is successful. The message is only meaningful when the business response fails, and data represents the result of the business response

How to choose RPC and ROA needs to be decided according to the business situation of the product itself. There are the following guiding principles:

  • For APIs with complex business logic, the RPC style should be used when simple addition, deletion, modification, and query descriptions cannot be used.
  • If the industry standard of the business requires a restful style API or ROA to meet business needs, the ROA style should be used.

AWS mainly adopts the RPC style, Azure and Google mainly adopt the ROA (restful) style, and Alibaba Cloud OpenAPI supports both RPC and ROA, with RPC as the main method.

Although the specification is innocent, I have seen many "pitfalls" in the practice of ROA style:

  • Require resources first, that is, design resources first, then design interface, which has higher requirements for software development process
  • Wrong ROA design case 1: When processing the HTTP request of the DELETE method, application servers such as tomcat do not allow the request body to be carried by default, and need to be explicitly enabled, resulting in deletion failure. (This case is a problem for the designer. For complex deletion scenarios, it should not be mapped to DELELE, but should be changed to POST. DELETE should not carry a request body.)
  • Wrong ROA design case 2: The parameters carried in the restful path may cause regular matching problems, such as mistakenly using the mailbox as a path parameter, or the conflict problem of multi-level path matching (this case is the problem of the designer, complex query scenario, it should not be mapped to GET, but should be changed to POST, only resource locators should appear in the path, and attributes should not be carried)
  • When the response code is 404, it is difficult to distinguish whether the real path does not exist or the resource does not exist
  • It is not conducive to scenarios where routing and forwarding need to be configured, such as connecting to a gateway

CSBThe Open API specification hopes to meet the following requirements:

  • When developing and designing interfaces at the back end, there is a clear design idea, so that you don’t get entangled with whether an interface is implemented with POST or GET, and you don’t need to spend too much time on the abstraction of resources (this does not mean that resources do not need to be designed)
  • When the front-end develops the docking interface, it can quickly cooperate with the back-end and facilitate the encapsulation of the front-end interface
  • When users connect to the Open API, the overall style is consistent and the modules are clear

To sum up, in terms of design style selection, I plan to adopt the RPC design specification. To summarize the advantages of the RPC style:

  • API design is less difficult and easy to implement
  • Most of Alibaba Cloud's mature IAAS layer products use the RPC specification
  • Suitable for complex business scenarios

A detailed example of an RPC interface document

create service

request parameters

serial number Field Chinese name Field English name type of data required illustrate
1 name name string yes display name
2 protocol protocol string yes Sheets: http/grpc/webservice
3 load balancing lb string yes Enumeration value: random/roundrobin
4 upstream type upstreamType string yes Enumeration value: fixed/discovery
5 node list nodes array no Required when upstreamType=fixed, example: [{“host”: “1.1.1.1”, “port”: “80”, “weight”: “1”}]
6 source id originId string no
7 service name serviceName string no The name in the registry, required when upstreamType=discovery
8 service description description string no
9 gateway-id gatewayId string yes

return parameter

serial number Field Chinese name Field English name type of data illustrate
1 response code code int 0
2 response message message string
3 response result data string return service id

request example

POST /service/createService

Request:
{
    
    
  "name": "httpbin",
  "protocol": "http",
  "lb": "random",
  "upstreamType": "fixed",
  "nodes": [
    {
    
    
      "host": "httpbin.org",
      "port": "80",
      "weight": "1"
    }
  ],
  "gatewayId": "gw-1qw2e3e4"
}

Response:
{
    
    
  "code": 0,
  "message": "",
  "serviceId": "s-1qw2e3e4"
}

API naming convention

  • The API should use English with correct spelling and conform to grammatical norms, including singular and plural, tense and language conventions

  • There cannot be multiple APIs with similar meanings but no actual difference in function, such as the presence of /user/getUser and /user/describeUser at the same time

  • Language Habits: Pinyin is prohibited

  • The naming rules of the following common scenarios are fixed

    • Parameters of type datetime should be named XxxxTime. For example:CreateTime
  • Common operation name specification

    • create:create
    • modify:change
    • delete:delete
    • get: Get the details of a single resource
    • list: get resource list
    • establishRelation: Create a resource relationship
    • destroyRelation: destroy resource relation

Summarize

When we discuss such norms, we must keep thinking about their purpose and context. In a real production environment, we have to face a large amount of code and growing demand, so we need to find a way to improve collaboration efficiency and code reliability to ensure that we can better meet customer needs .

Using the POST interface is a common and standard interface method , which can minimize the communication cost between users and developers, reduce the need for additional understanding of the interface, and also avoid the "GET" interface that may cause security issues.

In addition, this standardized interface method can also achieve better maintainability, because all interfaces in the system follow the same standard, developers can easily understand and modify these interfaces, so as to locate and Solve the problem.

In summary, using the POST interface is a reassuring and potentially profitable practice. For developers, this standardized approach will make it easier for them to follow the interface design specifications and reduce unnecessary workload to better complete work tasks. For the system and the company, this approach can also improve system efficiency, reduce maintenance and error positioning costs, thereby making the entire team more efficient and competitive.

Guess you like

Origin blog.csdn.net/m0_68089732/article/details/129849511