Are multiple status code headers allowed in a single HTTP response? - http

I have a web app which sends HTTP status codes. In some instances, a 404 code is sent as a header, but then a 200 error is sent as well, in the same response.
HTTP/1.0 404 Not Found
HTTP/1.0 200 Ok
I can't change the execution order to prevent the first status code from being sent, so the second code is attempting to override it.
Chrome ignores the first code and assumes the status to be Ok. Does this conform to the HTTP standard, and should I rely on it?

No, it does not conform to the standard, and you should not rely on it. See https://www.greenbytes.de/tech/webdav/rfc7230.html#rfc.section.5.6:
More than one response message per request only occurs when one or more informational responses (1xx, see Section 6.2 of [RFC7231]) precede a final answer to the same request.

The rfc for http 1.1 is given here: https://www.rfc-editor.org/rfc/rfc7230
Section 2.1 states:
A server responds to a client's request by sending one or more HTTP
response messages, each beginning with a status line ...
The standard states that you can send more than one response, if you wish, but that each response must have it's own status line. Further, the first line of the header must contain the status-line/code.
So, according to the standard interpreted literally, in theory you can send more than one response, but I've no idea what browsers would do with that, and definitely wouldn't rely on it.
What you've got at the moment is conforming to the rfc; the rfc doesn't say you can't have more than status line, only that the status line on the first line of each response is the one that matters - which chrome doesn't interpret correctly according to the rfc.
It might work, but I wouldn't rely on it.

Related

Why is there a HTTP status message when there already is a HTTP status code?

An HTTP response may look like:
HTTP/1.1 200 OK
I think 200 is already tell client that it is OK, and OK in response can be omitted. So what is the approach that is existed?
From https://greenbytes.de/tech/webdav/rfc7230.html#rfc.section.3.1.2:
The reason-phrase element exists for the sole purpose of providing a textual description associated with the numeric status code, mostly out of deference to earlier Internet application protocols that were more frequently used with interactive text clients. A client SHOULD ignore the reason-phrase content.
Such message is called reason phrase and, as mentioned in Julian Reschke's answer, it simply provides a textual description associated with the numeric status code and it should be ignored by the client. The reason phrase can even be empty.
While your question is about the HTTP/1.1 protocol, I would like to highlight that HTTP/2 responses don't carry any reason phrase. They carry only the status code, as defined in the RFC 7540:
For HTTP/2 responses, a single :status pseudo-header field is defined that carries the HTTP status code field. This pseudo-header field MUST be included in all responses; otherwise, the response is malformed.
HTTP/2 does not define a way to carry the version or reason phrase that is included in an HTTP/1.1 status line.

What are proper status codes for CORS preflight requests?

What status code should a well-written HTTP server return when it gets a CORS preflight (OPTIONS) request?
200, 204 or something else?
Should the status code be different in case origin is allowed (and corresponding headers will be set) or not allowed (and CORS headers will not be set or will not match the origin)?
The gist of it is, just use 200.
A little more generally: You should just send back the same status code for the CORS preflight OPTIONS request that you’d send back for any other OPTIONS request. The relevant specs don’t require or recommend anything more than that.
What the specs say: The Fetch spec at https://fetch.spec.whatwg.org/ is where requirements for the CORS protocol are defined, and it says the status can be anything in the range 200-299.
That’s from the CORS-preflight fetch algorithm, in a step saying it can be any “ok status":
If a CORS check for request and response returns success and response’s status is an ok status, run these substeps: …
And as far as what an “ok status” is, the spec says this:
An ok status is any status in the range 200 to 299, inclusive.
Beyond that though, the Fetch spec doesn’t recommend any particular status within 200-299.
The other relevant spec here is the HTTP 1.1 spec, which has a section defining semantics of all HTTP response status codes, and within that, a section that defines Successful 2xx codes.
And within that section there’s a specific section for 200 OK, which says this:
The 200 (OK) status code indicates that the request has succeeded.
The payload sent in a 200 response depends on the request method.
For the methods defined by this specification, the intended meaning
of the payload can be summarized as:
…
OPTIONS a representation of the communications options;
So a response to a CORS preflight OPTIONS just needs to be:
an indication that the request has succeeded
a representation of the communication options (which in this case includes the Access-Control-Allow-Methods and Access-Control-Allow-Headers response headers)
That’s what 200 OK is defined by the HTTP spec to be, so you can stop right there.
But if you read through the rest of the 2xx codes in that section, you can confirm the semantics of none of them make sense for an OPTIONS response—except for 204 No Content.
Now as far as 204 No Content goes, there’s nothing wrong with using it for OPTIONS responses—but there’s also not really any point. That’s because:
unlike for some other methods, the HTTP spec defines no use for an OPTIONS payload
therefore in practice, clients don’t expect any payload (content) to come back for an OPTIONS (and wouldn’t do anything with any payload that did come back)
…so there’s no practical purpose in using a specific 204 status code in an OPTIONS response to explicitly tell clients there’s no payload.
Should the status code be different in case origin is allowed (and corresponding headers will be set) or not allowed (and CORS headers will not be set or will not match the origin)?
No. There’s no standard-defined code other than 200 or 204 you could use anyway—but regardless of that, the specs don’t require it to be any different and don’t define any different use if it is. And think about it: What is any existing client code going to do any differently due to any difference in the status codes for those two cases?
If the answer to that is, “Nothing”, then there’s no point in making it different.
Given all the above, the bottom line is: just send 200 OK for CORS preflight OPTIONS responses. Sending any code other than just 200 OK isn’t necessary or useful.
I used 204. Now it's not working cross-browser anymore. Use 200. Firefox started rejecting CORS requests if 204 is received in the preflight. It wasted me almost 2 hours debugging it.
Lesson to learn: When in doubt about web standards don't choose what makes sense spec wise(i.e. 204 for no content)...choose what most people do(the easy/stupid choice)
I am using basic auth passed through headers from an AJAX call and both Firefox and Chrome are using 204 for (preflight/options).

Where do extended (decimal, e.g. 400.1, 401.4, etc.) HTTP status codes come from?

More and more I am seeing the proliferation of decimal style HTTP status codes and I can't seem to find any RFC or other IETF recommendation or even W3C drafts or whatever on this except Microsoft IIS documentation (see https://support.microsoft.com/en-us/kb/943891)
Did Microsoft create these out of thin air? Wouldn't these decimal style status codes choke a lot of network components that might be expecting a whole integer value?
Does anyone know where these decimal status codes come from?
Julian's comment above is correct.
IIS defines substatuses to help differentiate cases within the same defined status code for debugging purposes. These aren't sent on the wire in the HTTP response; as others have noted, that's an integer. They may appear in the response entity if configured (by default, only for clients running on the same host), and they're logged in the W3C log under the "sc-substatus" column.
If you're seeing decimal status codes elsewhere (the original question), you'd need to follow up with the source of them. Particularly, if you're seeing them in the HTTP message itself, that's a protocol compliance issue.
As mentioned in the docs you also linked to:
[...]
IIS 7.0, IIS 7.5, and IIS 8.0 define the following HTTP status codes that indicate a more specific cause of a 400 error:
400.1 - Invalid Destination Header.
400.2 - Invalid Depth Header.
400.3 - Invalid If Header.
[...]
So yes, IIS defines them.
And from Wikipedia, there is this gem:
[...]
The first digit of the status code specifies one of five classes of response; the bare minimum for an HTTP client is that it recognises these five classes. The phrases used are the standard examples, but any human-readable alternative can be provided.
[...]
So it's only mandatory that it starts with a 1-5.
Even if the HTTP client doesn't understand the whole status code, it can still decide what type of response it is:
1xx Informational
2xx Success
3xx Redirection
4xx Client Error
5xx Server Error
Update1:
As stated in RCF7231#6:
The status-code element is a three-digit integer code giving the
result of the attempt to understand and satisfy the request.
But also:
HTTP status codes are extensible. HTTP clients are not required to
understand the meaning of all registered status codes, though such
understanding is obviously desirable. However, a client MUST
understand the class of any status code, as indicated by the first
digit, and treat an unrecognized status code as being equivalent to
the x00 status code of that class, with the exception that a
recipient MUST NOT cache a response with an unrecognized status code.
For example, if an unrecognized status code of 471 is received by a
client, the client can assume that there was something wrong with its
request and treat the response as if it had received a 400 (Bad
Request) status code. The response message will usually contain a
representation that explains the status.
Update2:
Setting a 404.1 header in PHP (although the docs say it only accepts ints)
http_response_code(404.1);
results in a classic 404
So, in conclusion, I take it, clients, when the status code is unrecognized (for instance a 401.4), transform it into a generic 400 (keeping the status class - 4 and filling with 00)

What HTTP status code use when the required header is not specified?

If the user sends request to the server and the link requires specific custom headers to be set in order to work. In this case the error code should be 400, 403 or 422 ?
The HTTP specification requires any client to treat the response as 400 by default if it does not understand the specific meaning of the final two digits. So you must always design with the assumption that some clients will treat the response as 400.
If you can find a 4xx status code whose special extra handling works better for your application, then use it. When the client understands enough to do that extra handling you are slightly better off than if you had sent the default status.
The currently registered status codes which seem to match your servers meaning are:
403 Forbidden - this is about server refusing the request until it is somehow changed. Preferrably with the reason stated in the response body.
406 Not Acceptible - this is more specifically about values in the request headers not being right. Most commonly used for the Accept: header values.
412 Precondition Failed - this is about the problems with headers involved with negotiating which response body would be sent. Most commonly used for the If-* header values.
The 403 seems to be most accurate for when a server refused to deliver anything unless the custom headers is sent.

Which HTTP status code to use for required parameters not provided?

I have several pages designed to be called with AJAX - I have them return an abnormal status code if they can't be displayed, and my javascript will show an error box accordingly.
For example, if the user is not authenticated or their session has timed out and they try to call one of the AJAX pages, it will return 401 Unathorized.
I also have some return 500 Internal Server Error if something really odd happens server-side.
What status code should I return if one of these pages was called without required parameters? (and therefore can't return any content).
I had a look at the wikipedia article on HTTP status codes, but the closest one I could find to the code I'm looking for was this:
422 Unprocessable Entity
The request was well-formed but was unable to be followed due to semantic errors.
Edit: The above code is WebDAV specific and therefore unlikely to be appropriate in this case
Can anyone think of an appropriate code to return?
What status code should I return if one of these pages was called without required parameters? (and therefore can't return any content).
You could pick 404 Not Found:
The server has not found anything matching the Request-URI [assuming your required parameters are part of the URI, i.e. $_GET]. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.
(highlight by me)
404 Not Found is a subset of 400 Bad Request which could be taken as well because it's very clear about what this is:
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
This is normally more common with missing/wrong-named post fields, less with get requests.
As Luca Fagioli comments, strictly speaking 404, etc. are not a subset of the 400 code, and correctly speaking is that they fall into the 4xx class that denotes the server things this is a client error.
In that 4xx class, a server should signal whether the error situation is permanent or temporary, which includes to not signal any of it when this makes sense, e.g. it can't be said or would not be of benefit to share. 404 is useful in that case, 400 is useful to signal the client to not repeat the request unchanged. In the 400 case, it is important then for any request method but a HEAD request, to communicate back all the information so that a consumer can verify the request message was received complete by the server and the specifics of "bad" in the request are visible from the response message body (to reduce guesswork).
I can't actually suggest that you pick a WEBDAV response code that does not exist for HTTP clients using hypertext, but you could, it's totally valid, you're the server coder, you can actually take any HTTP response status code you see fit for your HTTP client of which you are the designer as well:
11.2. 422 Unprocessable Entity
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.
IIRC request entity is the request body. So if you're operating with request bodies, it might be appropriate as Julian wrote.
You commented:
IMHO, the text for 400 speaks of malformed syntax. I would assume the syntax here relates to the syntax of HTTP string that the client sends across to the server.
That could be, but it can be anything syntactically expressed, the whole request, only some request headers, or a specific request header, the request URI etc.. 400 Is not specifically about "HTTP string syntax", it's infact the general answer to a client error:
The 4xx class of status code is intended for cases in which the client seems to have erred. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method. User agents SHOULD display any included entity to the user.
The important part is here that you must tell the client what went wrong. The status code is just telling that something went wrong (in the 4xx class), but HTTP has not been specifically designed to make a missing query-info part parameter noteable as error condition. By fact, URI only knows that there is a query-info part and not what it means.
If you think 400 is too broad I suggest you pick 404 if the problem is URI related, e.g. $_GET variables.
I don't know about the RFC writers' intentions, but the status code I have seen used in the wild for that case is 400 Bad Request.
422 is a regular HTTP status code; and it is used outside WebDAV. Contrary to what others say, there's no problem with that; HTTP has a status code registry for a reason.
See http://www.iana.org/assignments/http-status-codes
Read this carefully:
https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
422 is a WebDAV-specific thing, and I haven't seen it used for anything else.
400, even though not intended for this particular purpose, seems to be a common choice.
404 is also a viable choice if your API is RESTful or similar (using the path part of the URI to indicate search parameters)
Description as quoted against 400
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
(Emphasis mine)
That speaks of malformed syntax, which is not the case when the browser sends a request to the server. Its just the case of missing parameters (while there's no malformed syntax).
I would suggest stick with 404 :)
(Experts correct me if I am wrong anywhere :) )
I need to answer this old question because the most upvoted and accepted answer is plain wrong.
From RFC 9110 - HTTP Semantics:
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).
So 400 is what you have to use.
Do not use 404, because you will completely mislead the API consumer. 404 means that the resource was not found on the server:
The 404 (Not Found) status code indicates that the origin server did
not find a current representation for the target resource or is not
willing to disclose that one exists.

Resources