REST API 错误代码返回结构

Posted

技术标签:

【中文标题】REST API 错误代码返回结构【英文标题】:REST API error codes return structure 【发布时间】:2013-08-30 11:28:21 【问题描述】:

我正在编写一个 REST API,但我偶然发现了一个问题。返回验证错误的最佳方法是什么。

到目前为止,我一直在返回转储到一般错误代码中的错误消息(例如错误请求)


    "status": 400,
    "error": 
        "code": 1, // General bad request code
        "message": [
                "The Key \"a\" is missing",
                "The Key \"b\" is missing",
                "The Key \"c\" is missing",
                "Incorrect Format for field \"y\""
         ]
    

)

我对良好的 API 响应应该是什么样子进行了更多研究,并想到了以下选项:

    在第一个遇到的错误处停止并返回带有特定错误代码的响应

    
       "status": 400, //Same as the HTTP header returned
       "error" 
            "code": 1, // Specific field validation error code
            "message": "Field \"x\" is missing from the array structure",
            "developer_message": "The request structure must contain the following fields a,b,cx,y,z",
            "more_info" => "www.api.com/help/errors/1"
        
    )
    

    解析所有请求数据并返回多个字段验证错误。

    
      "status": 400,
      "error": 
        "code": 1 //General bad Request code
        "message": "Bad Request",
        "developer_message": "Field validation errors."
        "more_info": "www.api.com/help/errors/1",
        "error_details": 
                0: 
                        "code": 2 // Specific field validation error code
                        "message": "Field \"x\" is missing from the array structure",
                        "developer_message": "The request structure must contain the following fields a,b,cx,y,z",
                        "more_info": "www.api.com/help/errors/2"
                    ,
    
                1: 
                        "code": 3 // Specific field validation error code
                        "message": "Incorrect Format for field \"y\"",
                        "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"",
                        "more_info": "www.api.com/help/errors/3"
                   
                       
          
      
    

在我看来,选项 2 是正确的方法(它为开发人员/最终用户提供了更多有用的信息,并且服务器负载可能更低(更少的请求/无需重新验证有效数据/无需计算签名和对用户进行身份验证)),但我正在徘徊什么是最佳实践,以及是否有另一种方法来处理此类问题。

如果我在脚本流程中遇到一个致命错误,我认为选项 1 仍然有效。(不是验证错误)

请注意,代码只是一个简单的数组,以便更容易理解。响应格式为 JSON 或 XML。

【问题讨论】:

我想知道是否有人去了#2,也许有任何改进,所以我开了一个赏金。 这个 API 有什么用途,错误消息的目的是什么?这些消息是否会显示给最终用户?每秒/分钟/天预计有多少请求?没有这些信息,您的问题的答案就不可能准确。您没有答案,因为这个问题太宽泛了,这实际上取决于 API 的使用情况。 【参考方案1】:

就我个人而言,我会向用户提供较少的详细信息,并将开发人员所需的错误转储到数据库日志表或系统日志中。由于您使用的是 JSON,这在 Apache 服务器上最常见,并且您的代码看起来可能是 php(但您的带有花括号的代码示例可能是源自 PASCAL 的多种语言,例如 C、C# PERL、PHP、夏普)。如果您还不知道如何在 php http://php.net/manual/en/function.syslog.php 中使用,这里是如何将自定义错误输出到系统日志。如果您使用带有 JSON 和 CSharp 的罕见配置 IIS,那么也有 .NET 库可以做类似的事情。如果您在发生错误时向您的用户提供太多信息,那么您也为未来的黑客提供了一种探测您网站的方式。

【讨论】:

我假设在这种情况下,如果数据是从输入表单传递的,验证必须在前端完全完成,所以如果无效值传递到后端,假设前端代码出错?跨度> 如果前端出现错误,我最讨厌的地方是因为它断开连接,我正在考虑是否值得将异步 Ajax 发布到日志服务器端 php 脚本,这真的取决于严重程度的错误。如果它是微不足道的,请确保您可以将其显示给用户。如果客户端发生错误,那么 JSON 甚至可能不在等式中。您现在谈论的是纯 JQUERY 还是 javascript 错误?无效的表单输入通常只是输入框以红色高亮显示并带有一般消息。 简而言之,客户端发生的任何事情,您都可以使用 AJAX 发送服务器端,访问 facebook 并使用名为 firebug 的工具并选择服务器活动帖子,您会惊讶于返回服务器的帖子数量可能是。我正在使用该示例,因为我仍在尝试解决如何在其上重新打开一个组。这是一个很长的故事,我不能说太多。【参考方案2】:

我自己用过#2 几次。比#1好吗?我认为这取决于您的 API 的用途。

我喜欢 #2,因为它让正在通过一些测试调用测试 API 的开发人员快速了解他在请求中犯的所有错误/错误,因此他可以立即知道他必须修复哪些错误/错误该请求有效。如果您一一返回错误(如#1中),您必须不断重试请求并交叉手指希望这次它是有效的。

但正如我所说,#2 对开发人员非常有用,但原因并不真正适用于最终用户。最终用户通常不关心它是如何实现的。软件是执行 1 个返回 5 个错误的请求,还是执行 5 个后续请求,每个请求返回 1 个错误。 只要在客户端处理得好,最终用户就不会注意到差异。如何处理当然很大程度上取决于客户实际上是什么

除了加快开发速度之外,#2(在生产中)的另一个好处是它需要更少的请求,这当然会降低服务器负载。


我想知道是否有人去了#2,也许有任何改进,所以我开了一个赏金。

当然还有改进。事实上,正文中有一些数据可以省略。


  "status": 400,
  "error": 
    "code": 1 //General bad Request code
    "message": "Bad Request",
    "developer_message": "Field validation errors."
    "more_info": "www.api.com/help/errors/1",
    "error_details": 
            0: 
                    "code": 2 // Specific field validation error code
                    "message": "Field \"x\" is missing from the array structure",
                    "developer_message": "The request structure must contain the following fields a,b,cx,y,z",
                    "more_info": "www.api.com/help/errors/2"
                ,

            1: 
                (
                    "code": 3 // Specific field validation error code
                    "message": "Incorrect Format for field \"y\"",
                    "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"",
                    "more_info": "www.api.com/help/errors/3"
                )
            
)

对于 HTTP 响应,状态代码不应放在正文中,而应放在标头中。这意味着这里可以省略"status": 400"message": "Bad Request"。 400 应该是响应的状态码,400 表示 Bad Request。这是一个 HTTP 标准,不必在响应中解释。此外,"developer_message": "Field validation errors." 有点重复,因为具体错误已经包含在每个单独的错误中,所以我们可以省略它。

离开


  "error": 
    "code": 1 //General bad Request code
    "more_info": "www.api.com/help/errors/1",
    "error_details": 
            0: 
                    "code": 2 // Specific field validation error code
                    "message": "Field \"x\" is missing from the array structure",
                    "developer_message": "The request structure must contain the following fields a,b,cx,y,z",
                    "more_info": "www.api.com/help/errors/2"
                ,

            1: 
                (
                    "code": 3 // Specific field validation error code
                    "message": "Incorrect Format for field \"y\"",
                    "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"",
                    "more_info": "www.api.com/help/errors/3"
                )
            
)

"code": 1 //General bad Request code
"more_info": "www.api.com/help/errors/1",

这 2 行现在不再有意义了。它们也不是必需的,因为每个错误都有自己的代码和信息链接,所以我们也可以去掉这些行,留下这个


  "error": 
    "error_details": 
            0: 
                    "code": 2 // Specific field validation error code
                    "message": "Field \"x\" is missing from the array structure",
                    "developer_message": "The request structure must contain the following fields a,b,cx,y,z",
                    "more_info": "www.api.com/help/errors/2"
                ,

            1: 
                (
                    "code": 3 // Specific field validation error code
                    "message": "Incorrect Format for field \"y\"",
                    "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"",
                    "more_info": "www.api.com/help/errors/3"
                )
            
)

400 状态码已经表明有错误,所以你不必再指出"error": error details,因为我们已经知道有错误。错误列表可以简单地成为根对象:

[
    
        "code": 2//Specificfieldvalidationerrorcode
        "message": "Field \"x\" is missing from the array structure",
        "developer_message": "The request structure must contain the following fields a,b,cx,y,z",
        "more_info": "www.api.com/help/errors/2"
    ,
    
        "code": 3//Specificfieldvalidationerrorcode
        "message": "Incorrect Format for field \"y\"",
        "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"",
        "more_info": "www.api.com/help/errors/3"
    
]

所以现在剩下的只是一个错误列表。

状态码在响应标头中指定。 详细信息在响应正文中指定。

【讨论】:

同意所描述的方法:#2 应该改进以避免data redoundancy 所以如果它出现两次也可能是状态不一致。这被许多异常处理系统普遍采用,例如:asp.net/web-api/overview/error-handling/exception-handling【参考方案3】:

首先,您应该为客户提供 Rest API 方法的文档。因此,客户/开发人员应为参数提供有效数据。

现在已经说过 #1 是执行 Rest API 的最佳方式。开发人员的责任是最大限度地减少服务器的使用。因此,如果遇到任何致命错误,请构造带有相应错误代码和错误消息的响应并返回。

此外,我们无法确定在我们遇到的错误之后还有更多错误。因此,解析其余数据没有意义。考虑到最坏的情况,它不会很好地工作。

【讨论】:

开发者的责任是尽可能减少服务器的使用量。 但是如果你一个一个返回错误(需要后续调用),情况并非如此【参考方案4】:

让我们看看Facebook's Graph API。这受到了重创,并且很可能会产生很多错误。以下是 Facebook 在 API 错误时返回的内容:

 
   "error": 
     "message": "Message describing the error", 
     "type": "OAuthException", 
     "code": 190,
     "error_subcode": 460,
     "error_user_title": "A title",
     "error_user_msg": "A message"
   
 

他们试图使 Graph API 尽可能有用,但他们似乎返回带有代码和子代码的特定错误 (Ref)。每个错误都有自己的代码这一事实意味着更容易搜索所述代码或消息作为调试的起点。这可能就是他们不在官方错误响应中累积错误消息的原因。如果它对 Facebook 来说足够好和方便,那对我们来说可能就足够了。

错误响应示例:


  "error": 
    "message": "(#200) Must have a valid access_token to access this endpoint", 
    "type": "OAuthException", 
    "code": 200
  

"error": 
  "message": "(#604) Your statement is not indexable. The WHERE clause must contain 
   an indexable column. Such columns are marked with * in the tables linked from
   http://developers.facebook.com/docs/reference/fql ", 
  "type": "OAuthException", 
  "code": 604


然后是JSend,它“是一个规范,它为来自 Web 服务器的 JSON 响应的格式设置了一些规则。”他们的目标是:

有很多提供 JSON 数据的 Web 服务,每个服务都有自己的格式化响应的方式。此外,为 JavaScript 前端编写的开发人员不断地重新发明***来从他们的服务器传输数据。虽然有许多常见的模式来构建这些数据,但在命名或响应类型等方面并没有一致性。此外,这有助于促进后端开发人员和前端设计师之间的快乐和团结,因为每个人都可以期待一种共同的方式来相互交互。

这是一个示例错误消息:


    "status" : "fail",
    "data" :  "title" : "A title is required" 

看起来 Facebook 和这个试图树立行业标准的团队正在选择您的选择 #1。


赏金问题

为了响应“如果有人去了#2 并且可能有任何改进?”的赏金请求,Pragmatic RESTful API 有一个设计模式指出:

验证错误需要字段细分。这最好通过使用固定的***错误代码来验证失败并在附加错误字段中提供详细错误来建模,如下所示:


  "code" : 1024,
  "message" : "Validation Failed",
  "errors" : [
    
      "code" : 5432,
      "field" : "first_name",
      "message" : "First name cannot have fancy characters"
    ,
    
       "code" : 5622,
       "field" : "password",
       "message" : "Password cannot be blank"
    
  ]

【讨论】:

【参考方案5】:

我最近研究了一个会在结果中返回多个警告或错误的 Rest API。从您的示例 #2 开始,我将对其进行如下修改:


  "status": 400,
  "results" : null,
  "warnings": 
        0: 
                // Build a warning message here, sample text to show concept
                "code": 1 // Specific field validation error code
                "message": "It is no longer neccessary to put .js on the URL"
           
  
  "errors": 
        0: 
                "code": 2 // Specific field validation error code
                "message": "Field \"x\" is missing from the array structure"
                "developer_message": "The request structure must contain the following fields a,b,cx,y,z",
            ,
        1: 
                "code": 3 // Specific field validation error code
                "message": "Incorrect Format for field \"y\"",
                "developer_message": "The field \"y\" must be in the form of \"Y-m-d\""
           
      
  

这将使您能够根据需要在响应中提供多个警告或错误的结果。

是的,这在结构上确实有些臃肿,但它也为开发人员提供了一个简单的接口,以便始终将他们的数据返回到相同的结构中。

我还将删除以下项目,恕我直言,它们应该在 API 文档中(如何使用错误代码查找帮助)而不是每个错误:

"more_info": "www.api.com/help/errors/2"
"more_info": "www.api.com/help/errors/3"

按照同样的思路,我不确定您是否同时需要消息和 developer_message。它们似乎是多余的,就好像您在调用者未能正确提供数据时尝试从 API 提供用户错误消息一样。

【讨论】:

【参考方案6】:

API 不适用于人类。因此,您不需要返回详细的错误文本。您甚至可以返回一个错误代码,表示“缺少参数”。只是不要忘记做好记录。

【讨论】:

API 也适用于人类,使用您的 API 的开发人员也是人类。此外,错误消息可能必须直接传递给最终用户。

以上是关于REST API 错误代码返回结构的主要内容,如果未能解决你的问题,请参考以下文章

返回 REST API 中错误 HTTP 方法的代码?

在带有 HTTP 状态代码 405 的 REST API 中返回啥错误消息?

对于使用错误凭据执行的登录请求,REST API 应返回啥状态代码?

REST API 错误返回良好做法 [关闭]

在 java rest api 上返回自定义状态和代码

Firebase 动态链接 REST API 返回 400 错误请求