This is not a huge problem in terms of how to handle business errors in Rest apis. In fact, for most architects, probably a lot of people don’t care much about this point.

But no matter how small the place can also have a more elegant and better way to implement, just recently the author also encountered and thought about this problem, special record.

1. HTTP response code

As we all know, HTTP response codes have a standard meaning. In general, I recommend adhering to this standard. HTTP response codes have a specific meaning from 1XX to 5XX, but the most commonly used Rest apis are probably 2XX and 4XX

[RFC7231, Section 6.3.2] 7d Accepted [RFC7231, Section 6.3.2] 7D Accepted [RFC7231, Section 6.3.2] 7D Accepted [RFC7231, Section 6.3.2] 7D Accepted Authoritative Information [RFC7231, Section 6.3.4] 204 No Content [RFC7231, AA, AA] 400 Bad Request [RFC7231, Section 6.5.1] 401 Unauthorized [RFC7235, [RFC7231, RFC7231, RFC7231, RFC7231 Section 6.5.3] 404 Not Found [RFC7231, Section 6.5.4] 405 Method Not Allowed [RFC7231, Section 6.5.4] Acceptable [RFC7231, Section 6.5.6] 706 Not Acceptable [RFC7231, Section 6.5.6]Copy the code

See the official specification document Http Status Code for details

2. How do I respond to service errors

Before this, the author did not pay special attention to this point, unified use of 200 response code, and then in the way of business status code. This is a common approach

2.1 Common Methods

The following is an example:

# response 200Business as usual {"code": 0."msg": "OK"."data": {
    "id": "123"
  }
}

# response 200Business error {"code":21
    "msg": "ID_CAN_NOT_NULL",}Copy the code

As shown in the above code, this is a common practice. 200 indicates that the network request is successful, and the business code is used to distinguish whether the service is normal or abnormal.

Code values, such as those used above, indicate business success when certain values (such as 0), while other values indicate different business errors. Successful responses are placed in fields such as data.

Is it appropriate and elegant?

2.2 The author’s thinking

Recently, when I was designing an API, I would have continued to do it the old-fashioned way, because it used to be done that way. But after careful thinking, I asked myself: why is this, what is the reason?

One advantage of the above approach is that the caller is less concerned with the status code and only deals with the 200 response. But I can’t think of any other advantage to this model.

After careful consideration, this model has several shortcomings, which is why I want to change the practice:

2.2.1 Disadvantage 1: It is not conducive to the expansion of other scenarios such as monitoring and statistics

This is also one of the most important shortcomings of the author

If the project is in the early stages, there is little need for monitoring or statistics, so this point is easily overlooked. But as projects or products become more widely used and natural monitoring or statistics come into play, this design can make this scenario difficult.

For example, we need to count or monitor the DIMENSIONS based on IP or customer, how many times an API is called, how many times it succeeds, and how many times it fails.

Such scenarios, whether by their own coding implementation, or through some tools like ELK to analyze the implementation, or directly from the nginx log analysis, if the above design, will increase the workload, and even some scenarios can not be achieved.

If the log contains the response body, it is good to be able to count by code, but without a similar response body log, this requirement may not be possible.

But if we do not design this way, and instead design 200 as a business success, then the above requirements, either way, will not encounter any obstacles.

2.2.2 Weakness two: Not following the single responsibility principle

We all know that one of the basic principles of object orientation is that a class, method, or module does only one thing.

Similarly, for response codes, we can also use this principle to design better.

Representing the 200 response as a mixture of business success and business failure obviously complicates the responsibility of the 200 status code, so why not just represent business success? Wouldn’t it be more pure?

And it’s not just the 200 response code, we have a series of 4XX that can be used to categorize the business into this category. In fact, if we look at the 4XX exception, it is obvious that it contains some business errors, such as insufficient permissions, forbidden, resources not existing, etc., which can be counted as part of the business error itself.

2.3 Thinking about error codes

In addition to the fact that using 200 in response to a business error is not a good idea, the other thing I don’t recommend is using a numeric value to represent an error code

Some teams or people may prefer to use numerical values for error codes, such as 101 for a problem on XXX and 102 for another business error. Personally, I do not recommend this practice.

Because numbers are not enough. Using characters is more appropriate.

Of course, the advantage of using numbers is that they match faster than characters. Program recognition is faster. But if we do not use the above design, this point is not to be considered.

3. The author’s design

Based on the above principles, the author’s new design principles are as follows:

  • Principle 1:2XX only indicates that the service successfully processes the request
  • Rule 2: Use 4XX to indicate business errors. If there are special designs in 4XX, use special designs, such as insufficient permissions, use 403. And without special design, unified use400
  • Rule 3: For 4XX responses, use additionalService error codeTo indicate a further business error
  • Principle 4: Use characters to represent service error description codes.

This API is derived from MyDDD-Vertx, based on vert. x and Kotlin’s responsive DDD framework

Mainstream API reference

Of course, a problem can not only from their own point of view to think, to see others’ opinions and practices.

Ruan Yifeng, a well-known teacher in China, also mentioned this in his RESTful API best practices, but did not mention the specific reason.

3.2 Do not return the 200 status code when an error occurs<br/>It is not appropriate to return the 200 status code even if an error occurs, putting the error message in the data body...Copy the code

Looking at the design of some mainstream apis, you can also see how they are designed for this point

Github Api

ZOOM API

Of course, there are some that don’t, such as Instagram’s API, which uses the Meta field to distinguish between business right and wrong

What do you think? Let’s have a different opinion


For more quality articles, please visit the author’s personal website: LingenLiu. cc or official account: [Royal Sword Xuan] – dedicated to practice and spread elegant coding