htmlhttpinternet-explorermicrosoft-edgehttp-status-code-204

MSIE/Edge uses HTTP HEAD for <object> data URLs, then treats 204 response as error?


Background:

My PHP code handles typical HTTP HEAD requests by sending either an HTTP status 404 response or a 204 response. This seems correct to me, since RFC7231 specifies HTTP status 204 as:

6.3.5. 204 No Content

The 204 (No Content) status code indicates that the server has successfully fulfilled the request and that there is no additional content to send in the response payload body. Metadata in the response header fields refer to the target resource and its selected representation after the requested action was applied...

The 204 response allows a server to indicate that the action has been successfully applied to the target resource, while implying that the user agent does not need to traverse away from its current "document view" (if any)...

A 204 response is terminated by the first empty line after the header fields because it cannot contain a message body...

https://www.rfc-editor.org/rfc/rfc7231#section-6.3.5

Since the user agent is only requesting the headers and not the file itself, 204 seems to fit.

Surprise #1:

When an <object> element has a URL for the data attribute, MSIE/Edge initially makes an HTTP HEAD request in order to determine the content-type via the response headers. While another MS quirk, it makes sense, as it allows the browser to pre-load the needed handlers in advance of receiving the content. When it receives a suitable response to the HEAD request, it will then make an HTTP GET request for the file itself.

Now, this wouldn't have been so much of an issue if it weren't for...

Surprise #2:

When MSIE/Edge receives a 204 response to its HEAD request, it treats it as an error and aborts loading the file.

This was, needless to say, quite frustrating to discover (the process and the discovery itself).

Have I misunderstood the purpose or usage of the 204 response? I know industry-usage often diverges from specifications, but this seems... wrong.


Solution

  • When you are returning 204 with the HEAD you are telling the user-agent that if it were to do a GET then it would also get a 204 and therefore there is no content to retrieve. From the perspective of the user-agent there is no point doing a GET because the HEAD retrieved all the information that was available.

    If doing a GET request returns a 200, then the HEAD should also return a 200.