REST API错误处理的最佳实践

1. 介绍

REST是一种无状态的架构,客户端可以在其中访问和操作服务器上的资源。通常,REST服务利用HTTP发布它们管理的一组资源,并提供允许客户机获取或更改这些资源状态的API。

在本教程中,我们将学习处理REST API错误的一些最佳实践,包括为用户提供相关信息的有用方法、来自大型网站的示例以及使用示例Spring REST应用程序的具体实现。

2. HTTP状态码

当客户端向HTTP服务器发出请求时——服务器成功接收到请求——服务器必须通知客户端请求是否被成功处理。HTTP完成这与五类状态代码:

  • 10x(信息性): 服务器确认请求
  • 20x(成功): 服务器按预期完成请求
  • 30x(重定向): 客户端需要执行进一步的操作来完成请求
  • 40x(客户端错误): 客户端发送了一个无效的请求
  • 50x(服务器错误): 服务器由于服务器错误而无法满足有效请求

客户端可以根据响应代码推测特定请求的结果。

3.处理错误

处理错误的第一步是向客户机提供正确的状态码。此外,我们可能需要在响应体中提供更多信息。

3.1 基本响应

处理错误最简单的方法是使用适当的状态码进行响应。

一些常见的回应码包括:

  • 400错误的请求: 客户端发送了一个无效的请求,例如缺少必需的请求体或参数
  • 401未经授权: 客户端对服务器进行身份验证失败
  • 403禁止: 经过身份验证的客户端,但没有访问请求资源的权限
  • 404未找到: 所请求的资源不存在
  • 412先决条件失败: 请求头字段中的一个或多个条件被评估为false
  • 500内部服务器错误: 一个通用错误发生在服务器上
  • 503服务不可用: 所请求的服务不可用

虽然很基本,但这些代码允许客户机了解所发生错误的广泛性质。例如,我们知道如果我们收到一个403错误,说明我们没有权限访问我们请求的资源。

然而,在许多情况下,我们需要在我们的答复中提供补充细节。

500错误表明服务器在处理请求时发生了一些问题或异常。一般来说,这个内部错误与我们的客户无关。

因此,为了尽量减少对客户机的响应,我们应该努力尝试处理或捕获内部错误,并在可能的情况下使用其他适当的状态代码进行响应。例如,如果由于请求的资源不存在而发生异常,我们应该将其公开为404错误,而不是500错误。

这并不是说不应该返回500,而是说应该将其用于阻止服务器执行请求的意外情况(如服务中断)。

3.2. 默认Spring错误响应

这些原则是如此普遍,以至于Spring已经在其默认的错误处理机制中编写了它们。

为了演示,假设我们有一个简单的Spring REST应用程序,它管理图书,有一个端点根据ID检索图书:

curl -X GET -H "Accept: application/json" http://localhost:8082/spring-rest/api/book/1

如果没有ID为1的书,我们期望控制器会抛出BookNotFoundException异常。在这个端点上执行GET,我们看到这个异常被抛出,响应体为:

{
    "timestamp":"2019-09-16T22:14:45.624+0000",
    "status":500,
    "error":"Internal Server Error",
    "message":"No message available",
    "path":"/api/book/1"
}

注意,这个默认的错误处理程序包括错误发生时的时间戳、HTTP状态代码、标题(错误字段)、消息(默认为空)和错误发生时的URL路径。

这些字段为客户端或开发人员提供信息,以帮助解决问题,还构成了标准错误处理机制的一些字段。

另外,请注意,当BookNotFoundException被抛出时,Spring会自动返回一个HTTP状态码为500。尽管有些api会返回500状态码或其他通用代码,正如我们将在Facebook和Twitter api中看到的那样——为了简单起见,对于所有错误,最好尽可能使用最具体的错误代码。

在我们的示例中,我们可以添加一个@ControllerAdvice,这样当BookNotFoundException被抛出时,我们的API会返回一个状态404,表示没有找到,而不是500内部服务器错误。

3.3. 更多的响应细节

正如在上面的Spring示例中看到的,有时状态代码不足以显示错误的细节。在需要时,我们可以使用响应体向客户机提供附加信息。在提供详细回应时,我们应包括:

  • 错误:错误的唯一标识符
  • 消息:一个简短的人类可读的消息
  • 细节: 对错误的更长的解释

例如,如果客户端发送了一个带有错误凭据的请求,我们可以发送一个包含以下内容的401响应:

{
    "error": "auth-0001",
    "message": "Incorrect username and password",
    "detail": "Ensure that the username and password included in the request are correct"
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!