400和422对数据POST的响应

本文翻译自:400 vs 422 response to POST of data

I'm trying to figure out what the correct status code to return on different scenarios with a "REST-like" API that I'm working on. 我正在尝试使用正在使用的“类似REST”的API找出在不同情况下返回的正确状态代码是什么。 Let's say I have a end point that allows POST'ing purchases in JSON format. 假设我有一个端点,允许JSON格式的POST购买。 It looks like this: 看起来像这样:

{
    "account_number": 45645511,
    "upc": "00490000486",
    "price": 1.00,
    "tax": 0.08
}

What should I return if the client sends me "sales_tax" (instead of the expected "tax"). 如果客户寄给我“ sales_tax”(而不是预期的“ tax”),我应该返回什么。 Currently, I'm returning a 400. But, I've started questioning myself on this. 目前,我要退回400。但是,我开始对此提出质疑。 Should I really be returning a 422? 我真的应该归还422吗? I mean, it's JSON (which is supported) and it's valid JSON, it's just doesn't contain all of the required fields. 我的意思是,它是JSON(受支持),并且是有效的JSON,只是不包含所有必填字段。


#1楼

参考:https://stackoom.com/question/15hAZ/和-对数据POST的响应


#2楼

400 Bad Request is proper HTTP status code for your use case. 400 Bad Request是您的用例的正确HTTP状态代码。 The code is defined by HTTP/0.9-1.1 RFC. 该代码由HTTP / 0.9-1.1 RFC定义。

The request could not be understood by the server due to malformed syntax. 由于语法格式错误,服务器无法理解该请求。 The client SHOULD NOT repeat the request without modifications. 客户不应在没有修改的情况下重复请求。

http://tools.ietf.org/html/rfc2616#section-10.4.1 http://tools.ietf.org/html/rfc2616#section-10.4.1

422 Unprocessable Entity is defined by RFC 4918 - WebDav. 422无法处理的实体由RFC 4918-WebDav定义。 Note that there is slight difference in comparison to 400, see quoted text below. 请注意,与400相比略有差异,请参见下面的引文。

This error condition may occur if an XML request body contains well-formed (ie, syntactically correct), but semantically erroneous, XML instructions. 如果XML请求主体包含格式正确(即,语法正确)但语义上错误的XML指令,则可能发生此错误情况。

To keep uniform interface you should use 422 only in a case of XML responses and you should also support all status codes defined by Webdav extension, not just 422. 为了保持统一的接口,您仅应在XML响应的情况下使用422,并且还应支持Webdav扩展定义的所有状态代码,而不仅仅是422。

http://tools.ietf.org/html/rfc4918#page-78 http://tools.ietf.org/html/rfc4918#page-78

See also Mark Nottingham's post on status codes: 另请参阅Mark Nottingham关于状态码的帖子:

it's a mistake to try to map each part of your application “deeply” into HTTP status codes; 尝试将应用程序的每个部分“深入”映射到HTTP状态代码是一个错误; in most cases the level of granularity you want to be aiming for is much coarser. 在大多数情况下,您想要的粒度级别要粗糙得多。 When in doubt, it's OK to use the generic status codes 200 OK, 400 Bad Request and 500 Internal Service Error when there isn't a better fit . 如有疑问,可以使用通用状态码200 OK,400错误请求和500内部服务错误,如果不合适的话

How to Think About HTTP Status Codes 如何思考HTTP状态码


#3楼

400 Bad Request would now seem to be the best HTTP/1.1 status code for your use case. 对于您的用例,现在400 Bad Request似乎是最好的HTTP / 1.1状态代码。

At the time of your question (and my original answer), RFC 7231 was not a thing; 在提出问题时 (和我的原始答案), RFC 7231并不是问题。 at which point I objected to 400 Bad Request because RFC 2616 said (with emphasis mine): 当时我反对400 Bad Request因为RFC 2616表示(重点是我的):

The request could not be understood by the server due to malformed syntax . 由于语法格式错误 ,服务器无法理解该请求。

and the request you describe is syntactically valid JSON encased in syntactically valid HTTP, and thus the server has no issues with the syntax of the request. 并且您描述的请求是语法有效的JSON(包含在语法有效的HTTP中),因此服务器的请求语法没有问题。

However as pointed out by Lee Saferite in the comments , RFC 7231, which obsoletes RFC 2616, does not include that restriction : 但是, 正如Lee Saferite在评论中所指出的那样 ,废弃了RFC 2616的RFC 7231不包括该限制

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (eg, malformed request syntax, invalid request message framing, or deceptive request routing). 400(错误请求)状态代码表示服务器由于某些原因(例如格式错误的请求语法,无效的请求消息框架或欺骗性的请求路由)而被视为客户端错误,因此服务器无法处理该请求。


However, prior to that re-wording (or if you want to quibble about RFC 7231 only being a proposed standard right now), 422 Unprocessable Entity does not seem an incorrect HTTP status code for your use case, because as the introduction to RFC 4918 says: 但是, 在重新措辞之前 (或者如果您想现在就仅将RFC 7231作为提议的标准进行422 Unprocessable Entity ),对于您的用例, 422 Unprocessable Entity不可422 Unprocessable Entity似乎不是错误的 HTTP状态代码,因为作为RFC 4918的介绍说:

While the status codes provided by HTTP/1.1 are sufficient to describe most error conditions encountered by WebDAV methods, there are some errors that do not fall neatly into the existing categories. 虽然HTTP / 1.1提供的状态代码足以描述WebDAV方法遇到的大多数错误情况,但是有些错误并没有很好地归类到现有类别中。 This specification defines extra status codes developed for WebDAV methods (Section 11) 该规范定义了为WebDAV方法开发的额外状态代码(第11节)

And the description of 422 says: 422的描述是

The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415(Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions. 422(不可处理实体)状态代码表示服务器了解请求实体的内容类型(因此415(不支持的媒体类型)状态代码不合适),并且请求实体的语法正确(因此400(错误请求) )状态代码不合适),但无法处理其中的说明。

(Note the reference to syntax; I suspect 7231 partly obsoletes 4918 too) (请注意对语法的引用;我怀疑7321也部分淘汰了4918)

This sounds exactly like your situation, but just in case there was any doubt, it goes on to say: 这听起来完全像你的情况,但万一有任何疑问,接着说:

For example, this error condition may occur if an XML request body contains well-formed (ie, syntactically correct), but semantically erroneous, XML instructions. 例如,如果XML请求主体包含格式正确(即,语法正确)但语义错误的XML指令,则可能发生此错误情况。

(Replace "XML" with "JSON" and I think we can agree that's your situation) (用“ JSON”替换“ XML”,我想我们可以同意这是您的情况)

Now, some will object that RFC 4918 is about "HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)" and that you (presumably) are doing nothing involving WebDAV so shouldn't use things from it. 现在,有些人会反对RFC 4918关于“ Web分布式创作和版本控制(WebDAV)的HTTP扩展”,而您(大概)没有做任何涉及WebDAV的事情,因此不应使用其中的内容。

Given the choice between using an error code in the original standard that explicitly doesn't cover the situation, and one from an extension that describes the situation exactly, I would choose the latter. 可以选择在原始标准中使用错误代码(不明确涵盖该情况),而在扩展中准确描述该情况,则我选择后者。

Furthermore, RFC 4918 Section 21.4 refers to the IANA Hypertext Transfer Protocol (HTTP) Status Code Registry , where 422 can be found. 此外, RFC 4918第21.4节引用了IANA超文本传输​​协议(HTTP)状态代码注册表 ,可以在其中找到422。

I propose that it is totally reasonable for an HTTP client or server to use any status code from that registry, so long as they do so correctly. 我建议HTTP客户端或服务器使用该注册表中的任何状态代码是完全合理的,只要它们正确地使用了它们即可。


But as of HTTP/1.1, RFC 7231 has traction, so just use 400 Bad Request ! 但是从HTTP / 1.1开始, RFC 7231具有吸引力 ,因此只需使用400 Bad Request


#4楼

There is no correct answer, since it depends on what the definition of "syntax" is for your request. 没有正确的答案,因为它取决于您对请求的“语法”的定义。 The most important thing is that you: 最重要的是,您:

  1. Use the response code(s) consistently 始终使用响应代码
  2. Include as much additional information in the response body as you can to help the developer(s) using your API figure out what's going on.= 在响应正文中包含尽可能多的其他信息,以帮助使用API​​的开发人员了解正在发生的事情。=

Before everyone jumps all over me for saying that there is no right or wrong answer here, let me explain a bit about how I came to the conclusion. 在每个人都说我这里没有对或错的答案之前,让我跳过去,让我先解释一下我是如何得出结论的。

In this specific example, the OP's question is about a JSON request that contains a different key than expected. 在此特定示例中,OP的问题是关于包含与预期不同的密钥的JSON请求。 Now, the key name received is very similar, from a natural language standpoint, to the expected key, but it is, strictly, different, and hence not (usually) recognized by a machine as being equivalent. 现在,从自然语言的角度来看,收到的密钥名称与期望的密钥非常相似,但是严格来说是不同的,因此(通常)机器不认为它是等效的。

As I said above, the deciding factor is what is meant by syntax . 就像我在上面说的那样,决定因素是语法 If the request was sent with a Content Type of application/json , then yes, the request is syntactically valid because it's valid JSON syntax, but not semantically valid, since it doesn't match what's expected. 如果该请求是使用Content application/json类型发送的,则是的,该请求在语法上是有效的,因为它是有效的JSON语法,但在语义上无效,因为它与预期的不匹配。 (assuming a strict definition of what makes the request in question semantically valid or not). (假设对导致所讨论的请求在语义上有效或无效的严格定义)。

If, on the other hand, the request was sent with a more specific custom Content Type like application/vnd.mycorp.mydatatype+json that, perhaps, specifies exactly what fields are expected, then I would say that the request could easily be syntactically invalid, hence the 400 response. 另一方面,如果以更特定的自定义内容类型(例如application/vnd.mycorp.mydatatype+json )发送了请求,也许可以确切指定期望的字段,那么我可以说该请求可以很容易地在语法上无效,因此为400。

In the case in question, since the key was wrong, not the value , there was a syntax error if there was a specification for what valid keys are. 在这种情况下,由于密钥是错误的,而不是value ,所以如果存在有效密钥的规范则存在 语法错误。 If there was no specification for valid keys, or the error was with a value , then it would be a semantic error. 如果没有有效密钥的规范 ,或者错误带有value ,那么它将是语义错误。


#5楼

To reflect the status as of 2015: 为反映截至2015年的状况:

Behaviorally both 400 and 422 response codes will be treated the same by clients and intermediaries, so it actually doesn't make a concrete difference which you use. 从行为上讲,客户端和中介将对400和422响应代码进行相同的处理,因此实际上并不会对您使用的内容产生任何具体的影响

However I'd expect to see 400 currently used more widely, and furthermore the clarifications that the HTTPbis spec provides make it the more appropriate of the two status codes: 但是,我希望看到400当前被更广泛地使用,此外, HTTPbis规范提供的说明使其更适合两种状态代码:

  • The HTTPbis spec clarifies the intent of 400 to not be solely for syntax errors. HTTPbis规范阐明了400的意图不仅仅是语法错误。 The broader phrase "indicates that the server cannot or will not process the request due to something which is perceived to be a client error" is now used. 现在使用更宽泛的短语“指示服务器由于某种被视为客户机错误的原因而无法或不会处理请求”。
  • 422 Is specifically a WebDAV extension, and is not referenced in RFC 2616 or in the newer HTTPbis specification . 422特别是WebDAV扩展,在RFC 2616或较新的HTTPbis规范中未引用。

For context, HTTPbis is a revision of the HTTP/1.1 spec that attempts to clarify areas that where unclear or inconsistent. 就上下文而言,HTTPbis是HTTP / 1.1规范的修订版,试图澄清不清楚或不一致的区域。 Once it has reached approved status it will supersede RFC2616. 一旦达到批准状态,它将取代RFC2616。


#6楼

Your case: HTTP 400 is the right status code for your case from REST perspective as its syntactically incorrect to send sales_tax instead of tax , though its a valid JSON. 您的案例:从REST的角度来看, HTTP 400是正确的状态代码,因为它在语法上不正确,尽管发送了有效的JSON来发送sales_tax而不是tax This is normally enforced by most of the server side frameworks when mapping the JSON to objects. 在将JSON映射到对象时,大多数服务器端框架通常会强制执行此操作。 However, there are some REST implementations that ignore new key in JSON object. 但是,有些REST实现会忽略JSON对象中的新key In that case, a custom content-type specification to accept only valid fields can be enforced by server-side. 在这种情况下,服务器端可以强制执行仅接受有效字段的自定义content-type规范。

Ideal Scenario for 422: 422的理想方案:

In an ideal world, 422 is preferred and generally acceptable to send as response if the server understands the content type of the request entity and the syntax of the request entity is correct but was unable to process the data because its semantically erroneous. 在理想情况下,如果服务器理解请求实体的内容类型并且请求实体的语法正确但由于语义错误而无法处理数据,则422是首选并且通常可以作为响应发送。

Situations of 400 over 422: 422中400的情况:

Remember, the response code 422 is an extended HTTP (WebDAV) status code. 请记住,响应代码422是扩展的HTTP(WebDAV)状态代码。 There are still some HTTP clients / front-end libraries that aren't prepared to handle 422. For them, its as simple as "HTTP 422 is wrong, because it's not HTTP" . 还有一些HTTP客户端/前端库尚未准备好处理422。对于它们来说,它就像“ HTTP 422是错误的,因为它不是HTTP”一样简单。 From the service perspective, 400 isn't quite specific. 从服务的角度来看,400不是很具体。

In enterprise architecture, the services are deployed mostly on service layers like SOA, IDM, etc. They typically serve multiple clients ranging from a very old native client to a latest HTTP clients. 在企业体系结构中,服务主要部署在SOA,IDM等服务层上。它们通常为多个客户端提供服务,从非常老的本机客户端到最新的HTTP客户端。 If one of the clients doesn't handle HTTP 422, the options are that asking the client to upgrade or change your response code to HTTP 400 for everyone. 如果其中一个客户端不处理HTTP 422,则选项为要求客户端将所有人的响应代码升级或更改为HTTP 400。 In my experience, this is very rare these days but still a possibility. 以我的经验,这几天很少见,但仍有可能。 So, a careful study of your architecture is always required before deciding on the HTTP response codes. 因此,在决定HTTP响应代码之前,始终需要仔细研究您的体系结构。

To handle situation like these, the service layers normally use versioning or setup configuration flag for strict HTTP conformance clients to send 400, and send 422 for the rest of them. 为了处理这种情况,服务层通常对严格的HTTP一致性客户端使用versioning或设置configuration标志,以发送400,其余的则发送422。 That way they provide backwards compatibility support for existing consumers but at the same time provide the ability for the new clients to consume HTTP 422. 这样,它们为现有使用者提供了向后兼容性支持,但同时也为新客户端提供了使用HTTP 422的能力。


The latest update to RFC7321 says: RFC7321的最新更新为:

The 400 (Bad Request) status code indicates that the server cannot or
   will not process the request due to something that is perceived to be
   a client error (e.g., malformed request syntax, invalid request
   message framing, or deceptive request routing).

This confirms that servers can send HTTP 400 for invalid request. 这确认服务器可以发送HTTP 400进行无效请求。 400 doesn't refer only to syntax error anymore , however, 422 is still a genuine response provided the clients can handle it. 400不再仅指语法错误 ,但是422仍然是真正的响应,只要客户可以处理它。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: cURL 是一个在命令行下运行的开源工具和库,用来传输数据,支持多种协议,包括HTTPHTTPS。通过cURL发送POST请求并返回响应数据的步骤如下: 1. 引入cURL库。在C语言中,引入头文件`<curl/curl.h>`来使用cURL相关的函数和结构体。 2. 初始化cURL。使用函数`curl_global_init(CURL_GLOBAL_ALL)`来初始化cURL。 3. 创建一个`CURL`指针,并通过`curl_easy_init()`函数进行初始化。 4. 设置请求的URL。使用`curl_easy_setopt()`函数,设置请求的URL,通过参数`CURLOPT_URL`指定URL地址。 5. 设置POST请求,并传递需要发送的数据。使用`curl_easy_setopt()`函数,通过参数`CURLOPT_POST`设置为1,表示使用POST方法发送请求。然后使用`curl_easy_setopt()`函数,通过参数`CURLOPT_POSTFIELDS`将需要发送的数据传递给它。 6. 设置接收响应数据的回调函数。使用`curl_easy_setopt()`函数,通过参数`CURLOPT_WRITEFUNCTION`设置回调函数,用于接收响应数据。 7. 执行cURL请求。使用`curl_easy_perform()`函数来执行cURL请求,并等待服务器响应。 8. 获取响应状态码。使用`curl_easy_getinfo()`函数,通过参数`CURLINFO_RESPONSE_CODE`来获取服务器返回的响应状态码。 9. 清理cURL相关资源。使用`curl_easy_cleanup()`函数来释放创建的cURL指针。 10. 清理cURL全局资源。使用`curl_global_cleanup()`函数来释放cURL全局资源。 这样就可以使用cURL发送POST请求并返回响应数据了。根据实际需求,可以对步骤4和5进行调整来设置请求头信息、设置超时时间等。 ### 回答2: curl是一个广泛应用在命令行和脚本中的工具,可以用于发送HTTP请求并获取返回的响应数据。在使用curl发送POST请求时,我们需要使用以下命令格式: ``` curl -X POST -d "参数1=值1&参数2=值2" URL ``` 其中,`-X POST`表示发送POST请求,`-d`表示要发送的数据,以`参数=值`的形式进行传递,多个参数之间使用`&`连接,最后的URL为目标地址。 举例来说,如果我们要向`http://example.com/api`发送一个包含`username`和`password`的POST请求,并获取返回的响应数据,可以使用以下命令: ``` curl -X POST -d "username=admin&password=123456" http://example.com/api ``` 执行以上命令后,curl会向`http://example.com/api`发送一个POST请求,请求数据为`username=admin&password=123456`,然后会返回该请求的响应数据。 通过解析和处理返回的数据,我们可以根据具体情况使用不同的方式进行操作,例如将响应保存到文件中、提取特定字段等。 总而言之,使用curl发送POST请求的步骤是:构造请求数据、发送请求、获取并处理响应数据。这样我们就可以在命令行中使用curl方便地发送POST请求并获取响应数据。 ### 回答3: 使用cURL发送POST请求并返回响应数据,可以通过以下的步骤实现: 第一步,包含必要的头文件: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <curl/curl.h> ``` 第二步,定义回调函数来处理响应数据: ```c size_t write_callback(void *ptr, size_t size, size_t nmemb, char *data) { memcpy(data, ptr, size * nmemb); return size * nmemb; } ``` 第三步,编写发送POST请求的函数: ```c char* send_post_request(char* url, char* post_data) { CURL *curl; CURLcode res; struct curl_slist *header_list = NULL; char *response_data = malloc(1); int response_size = 0; curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(post_data)); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, response_data); res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_easy_cleanup(curl); } return response_data; } ``` 最后,可以通过以下方式调用函数发送POST请求并获取响应数据: ```c int main() { char url[] = "http://example.com/api"; char post_data[] = "key1=value1&key2=value2"; char *response_data = send_post_request(url, post_data); printf("Response data: %s\n", response_data); free(response_data); return 0; } ``` 以上就是使用C语言和cURL发送POST请求并返回响应数据的简单实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值