RFC 7807: error handling standard for APIs

RFC 7807: error handling standard for APIs

Acknowledments

This article has been co-authored with Stefano Fago whom I would like to thank and acknowledge this contribution and review.

Introduction

Application specific problems have to be handled properly with machine readable and human friendly custom business error codes. RFC-7231?precisely specify different situations, mainly fine-grained technical problems by using a standard set of HTTP Codes (see Figure 1). However, they tend to be quite generic and with the huge adoption of APIs, it is needed to differentiate between many situations. Fortunately, we have a standard: RFC-7807. It provides not just the high level status code but also finer grained details of the error.

Let's see what it offers!

HTTP Codes

HTTP response status codes indicate whether a specific?HTTP?request has been successfully completed. These status codes (also called response status codes) serve as a means of communication between the server and the internet browser and there are multiple code classes based on the type of information they are communicating. The differences in classes are indicated through the first digit of the error code, for example: just like a 404, any other 4xx will mean that in some way the page or website could not be reached, while a 2xx means that your request was successfully completed.

HTTP status codes are split into 5 different categories. Each category will give you hints as to what the response was, even if you don't know the specific response code. The categories are the following (see Figure 1):

  1. Informational responses?(100–199)
  2. Successful responses?(200–299)
  3. Redirection messages?(300–399)
  4. Client error responses?(400–499)
  5. Server error responses?(500–599)

No alt text provided for this image

Figure 1 HTTP Codes define by RFC-7231 (Source: Cheatography)

RFC-7807

The purpose of the specification is to define common error formats for applications that may need them. This allows API Designer to not define custom errors and above all to avoid redefining the semantics of existing HTTP status codes ( 555 Status Code? [ reference in resources]). Even if an application chooses not to use it to pass errors, or there's no need to use it since the problems can be expressed with default http status code, using RFC 7807 can be a means to review API design decisions faced when transmitting errors in an existing format. An example of this reasoning is the classification of errors, separating what is system error from application error and consider the Consumer behavior in terms of retries or idempotence of requests.

Example:?

HTTP/1.1 403 Forbidden

Content-Type: application/problem+json

Content-Language: en




{

? "type": "https://myexample.com/issues/out-of-credit",?

? "title": "You do not have enough credit to book a room.",?

? "detail": "Your current balance is 30 EUR, but a room costs 50 EUR per night.",

? "instance": "/accounts/12345/errors/out-of-credit/err_instance_id=123",

? "balance": 30,

? "account": "/accounts/12345"

}        

RFC 7807 introduced a standardized means to report problems that occurred as a result of invoking a REST API to the client. This standard defines a preferred media type application/problem+json; for XML messages is defined a specific media type application/problem+xml.

Problem Details Object can be embedded in other formats, if possible, or can be processed to create the right mapping for the needed format.

Embedding Example

<script type="application/problem+json"

?{

??"type": "https://myexample.com/issues/out-of-credit",?

??"title": "You do not have enough credit to book a room.",?

??"detail": "Your current balance is 30 EUR, but a room costs 50 EUR per night.",

??"instance": "/accounts/12345/errors/out-of-credit/err_instance_id=123",

??"balance": 30,

??"account": "/accounts/12345"

?}
</script>
        

Problem Details Object follow the expected behavior in content negotiation supporting possibly translation of human-readable messages in supported languages. RFC 7807 defines standard fields to be used with their exact semantics. The RFC defines several pieces of information common to all Problem Details Objects.?Here’s a short summary:

  • type?– A URI reference that identifies the problem type. Ideally it should be a?stable?URL to the documentation of the details about this type of error but it also can be a?URN. This is the only required field.
  • title?– A short, human-readable summary of the problem type. SHOULD NOT change from occurrence to occurrence.
  • status?– The HTTP status code generated by the origin server for this occurrence of the problem
  • detail?– A human-readable explanation specific to this occurrence of the problem
  • instance?– A URI reference that identifies the specific occurrence of the problem

All other fields are extensions (custom, machine readable fields) that can be complex types, as long as they are (de)serializable.

HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Content-Language: en

{
  "type": "https://myexample.com/issues/out-of-credit", 
  "title": "You do not have enough credit to book a room.", 
  "detail": "Your current balance is 30 EUR, but a room costs 50 EUR per night.",
  "instance": "/accounts/12345/errors/out-of-credit/err_instance_id=123",
  "balance": 30,
  "account": "/accounts/12345"
}        

The Problem Details, Extensions and Multiple Errors

The specification makes it possible to define custom fields called extensions. These need to be (de)serializable and have the right name just following the?same rules expressed in the RFC.?Extensions don't need to be understood by the Consumer that can skip them without?errors.?

RFC 7807 make possible to support multiple errors thanks to extensions as can happen in validation use-cases: a response report the reference and reason of the different parts of the request document that offend some business rules.?

The actual specification supports the format derived from the usage of 207 Http Status Code ( https://www.rfc-editor.org/rfc/rfc4918.html ). Also if more comfortable, in future versions, this approach will be skipped to preserve a more semantic adherence to HTTP semantics that does not support directly batching-request or multi-request.?

Example:

POST /details HTTP/1.1

Host: account.example.com

Accept: application/json

{

?"age": 42.3,

?"profile": {

??"color": "yellow"

?}

}        


HTTP/1.1 400 Bad Request

Content-Type: application/problem+json

Content-Language: en

{

?"type": "https://example.net/validation-error",

?"title": "Your request is not valid.",

?"errors": [

???????{

????????"detail": "must be a positive integer",

????????"pointer": "#/age"

???????},

???????{

????????"detail": "must be 'green', 'red' or 'blue'",

????????"pointer": "#/profile/color"

???????}

?????]

?}        

Security Considerations

RFC 7807 is a useful tool but being in the context of the API we cannot fail to remember?that APIs are one of the main attack surfaces. The possibility of expressing problems and errors must follow the classic rules of web security, avoiding exposing details that may?prove harmful or increase the possibility of attacking the same API: minimize the information reported and avoid making implementation details available, such as a dump of the stack, through the HTTP interface are concepts to pay attention to when designing error messages in this area as well.

We need also to consider to protect dereferenced URI or make them part of adopted infrastructure for API Lifecycle/Governance and, as said before, evaluate to not use Problem Details format when Status Codes are enough.

The next future and HTTP API evolution

RFC 7807 is an interesting specification and is one of the most effective efforts in defining the HTTP API along with the concepts of HTTP Warning, Health Check Response, Query Method which could appear as important tools.

In the near future, an evolution of this element (RFC 7807 bis) is being prepared to support a standardization process of the API, in compliance with the renewed semantics of HTTP and elasticity of the design of API. A promising idea is the definition of a new header that can convey information about problems/errors without forcing the production of a response body as in the following example:

HTTP / 1.1 200 OK

Content-Type: application / json

Problem: type = "https://example.net/problems/almost-out",

??title = "you're almost out of credit", credit_left = 20        

References

HTTP Status Code:

RFC7807 Related:

Problem Details & IOT:

John Borys

Technical Excellence Leader, Lean & eXtreme Programming Practitioner, Full-Stack developer, Polyglot Dev. Test Driven Development and XP fundamentals are how I build better software sooner.

1 年

You wrote, "RFC 7807 make possible to support multiple errors thanks to extensions". Would you happen to have an example that handles multiple validation errors? Specifically MethodArgumentNotValidExceptiion and how to map it to Problem Detail for readable json?

回复
Daniel de Souza Teixeira

Software Developer | Backend Developer | Software Engineer

1 年

Nice article.

Pascal Gacina

Partner Vice President Consulting - Expert - Enterprise Event & Integration Practice (EDA/API/iPaaS) - CGI Digital Innovation Center

2 年

要查看或添加评论,请登录

David Roldán Martínez的更多文章

社区洞察

其他会员也浏览了