HTTP 400 (bad request) for logical error, not malformed request syntax

后端 未结 8 798
生来不讨喜
生来不讨喜 2020-12-02 09:11

The HTTP/1.1 specification (RFC 2616) has the following to say on the meaning of status code 400, Bad Request (§10.4.1):

The request could not be unde

相关标签:
8条回答
  • 2020-12-02 09:30

    In my case:

    I am getting 400 bad request because I set content-type wrongly. I changed content type then able to get response successfully.

    Before (Issue):

    ClientResponse response = Client.create().resource(requestUrl).queryParam("noOfDates", String.valueOf(limit))
                    .header(SecurityConstants.AUTHORIZATION, formatedToken).
    header("Content-Type", "\"application/json\"").get(ClientResponse.class);
    

    After (Fixed):

    ClientResponse response = Client.create().resource(requestUrl).queryParam("noOfDates", String.valueOf(limit))
                    .header(SecurityConstants.AUTHORIZATION, formatedToken).
    header("Content-Type", "\"application/x-www-form-urlencoded\"").get(ClientResponse.class);
    
    0 讨论(0)
  • 2020-12-02 09:35

    Status 422 (RFC 4918, Section 11.2) comes to mind:

    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. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.

    0 讨论(0)
  • 2020-12-02 09:35

    This is difficult.

    I think we should;

    1. Return 4xx errors only when the client has the power to make a change to the request, headers or body, that will result in the request succeeding with the same intent.

    2. Return error range codes when the expected mutation has not occured, i.e. a DELETE didn't happen or a PUT didn't change anything. However, a POST is more interesting because the spec says it should be used to either create resources at a new location, or just process a payload.

    Using the example in Vish's answer, if the request intends to add employee Priya to a department Marketing but Priya wasn't found or her account is archived, then this is an application error.

    The request worked fine, it got to your application rules, the client did everything properly, the ETags matched etc. etc.

    Because we're using HTTP we must respond based on the effect of the request on the state of the resource. And that depends on your API design.

    Perhaps you designed this.

    PUT { updated members list } /marketing/members
    

    Returning a success code would indicate that the "replacement" of the resource worked; a GET on the resource would reflect your changes, but it wouldn't.

    So now you have to choose a suitable negative HTTP code, and that's the tricky part, since the codes are strongly intended for the HTTP protocol, not your application.

    When I read the official HTTP codes, these two look suitable.

    The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource. This code is used in situations where the user might be able to resolve the conflict and resubmit the request. The server SHOULD generate a payload that includes enough information for a user to recognize the source of the conflict.

    And

    The 500 (Internal Server Error) status code indicates that the server encountered an unexpected condition that prevented it from fulfilling the request.

    Though we've traditionally considered the 500 to be like an unhandled exception :-/

    I don't think its unreasonable to invent your own status code so long as its consistently applied and designed.

    This design is easier to deal with.

    PUT { membership add command } /accounts/groups/memberships/instructions/1739119
    

    Then you could design your API to always succeed in creating the instruction, it returns 201 Created and a Location header and any problems with the instruction are held within that new resource.

    A POST is more like that last PUT to a new location. A POST allows for any kind of server processing of a message, which opens up designs that say something like "The action successfully failed."

    Probably you already wrote an API that does this, a website. You POST the payment form and it was successfully rejected because the credit card number was wrong.

    With a POST, whether you return 200 or 201 along with your rejection message depends on whether a new resource was created and is available to GET at another location, or not.

    With that all said, I'd be inclined to design APIs that need fewer PUTs, perhaps just updating data fields, and actions and stuff that invokes rules and processing or just have a higher chance of expected failures, can be designed to POST an instruction form.

    0 讨论(0)
  • 2020-12-02 09:36

    On Java EE servers a 400 is returned if your URL refers to a non-existent "web -application". Is that a "syntax error"? Depends on what you mean by syntax error. I would say yes.

    In English syntax rules prescribe certain relationships between parts of speech. For instance "Bob marries Mary" is syntactically correct, because it follows the pattern {Noun + Verb + Noun}. Whereas "Bob marriage Mary" would be syntactically incorrect, {Noun + Noun + Noun}.

    The syntax of a simple URLis { protocol + : + // + server + : + port }. According to this "http://www.google.com:80" is syntactically correct.

    But what about "abc://www.google.com:80"? It seems to follow the exact same pattern. But really it is a syntax error. Why? Because 'abc' is not a DEFINED protocol.

    The point is that determining whether or not we have a 400 situation requires more than parsing the characters and spaces and delimiters. It must also recognize what are the valid "parts of speech".

    0 讨论(0)
  • 2020-12-02 09:39

    Even though, I have been using 400 to represent logical errors also, I have to say that returning 400 is wrong in this case because of the way the spec reads. Here is why i think so, the logical error could be that a relationship with another entity was failing or not satisfied and making changes to the other entity could cause the same exact to pass later. Like trying to (completely hypothetical) add an employee as a member of a department when that employee does not exist (logical error). Adding employee as member request could fail because employee does not exist. But the same exact request could pass after the employee has been added to the system.

    Just my 2 cents ... We need lawyers & judges to interpret the language in the RFC these days :)

    Thank You, Vish

    0 讨论(0)
  • 2020-12-02 09:43

    HTTPbis will address the phrasing of 400 Bad Request so that it covers logical errors as well. So 400 will incorporate 422.

    From https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-18#section-7.4.1
    "The server cannot or will not process the request, due to a client error (e.g., malformed syntax)"

    0 讨论(0)
提交回复
热议问题