Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a cross-origin HEAD request need a preflight check?

I was reading the spec on CORS requests, and I found this about preflight requests:

These are requests to a non same origin URL with an HTTP request method other than GET that first need to be authorized using either a preflight result cache entry or a preflight request.

I had thought the purpose of preflight requests was to check whether a request was allowed before making it, in case it (illegitimately) changed server state.

But HEAD and OPTIONS don't modify server state. I must misunderstand the reason for preflight check.

What is the purpose (aka the reason, motivation, or rationale) for doing a preflight check for HEAD and OPTIONS but not GET? What is special about GET?

like image 950
Paul Draper Avatar asked Feb 28 '14 23:02

Paul Draper


People also ask

Why do CORS preflight?

A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood and a server is aware using specific methods and headers. It is an OPTIONS request, using three HTTP request headers: Access-Control-Request-Method , Access-Control-Request-Headers , and the Origin header.

What triggers a preflight request?

A preflight request is a small request that is sent by the browser before the actual request. It contains information like which HTTP method is used, as well as if any custom HTTP headers are present. The preflight gives the server a chance to examine what the actual request will look like before it's made.

How do I test cross-origin requests?

You can test your API's CORS configuration by invoking your API, and checking the CORS headers in the response. The following curl command sends an OPTIONS request to a deployed API.


1 Answers

The primary intent of preflighting is to ensure that servers aren't suddenly sent cross-origin browser-based requests that they could have never received before the CORS spec was implemented.

Before the CORS spec, it was impossible to send any browser-based cross-origin requests other than GET or POST. The browser simply would not allow you to fire up an XHR instance, set the method to PUT (for example) and send it off to an endpoint on a different origin. You couldn't send GET or POST cross-origin requests via XHR either, but you COULD send a cross-origin GET or POST via a form submit, or a cross-origin GET via an <img> or <script> tag, for example (which made JSONP the only option pre-CORS). Once browsers implemented the CORS spec, this changed. Now it IS possible to send any cross-origin ajax request, provided the server opts-in.

The CORS spec defines "simple" methods (GET and POST) along with "simple" request headers. These correspond to the types of cross-origin requests that you could already send from the browser pre-CORS spec. Non-simple cross-origin requests, such as PUT or POST/GET requests with an X-header (for example) could not be sent from a browser pre-CORS spec. So, for these types of requests, the concept of preflighting was written into the spec to ensure servers do not receive these types of non-simple cross-origin browser-based requests without explicitly opting in. In other words, if you don't want to allow these types of requests, you don't have to change your server at all. The preflight will fail, and the browser will never send the underlying request.

Directly addressing your question: HEAD requests do not normally result in a preflight. HEAD is considered a simple request method according to the CORS spec. As you know, HEAD requests are just GETs without a response payload. This is the most likely reason why HEAD and GET requests are treated the same, even though you could not send a cross-origin HEAD request pre-CORS from the browser. If your HEAD contains non-simple headers, it will be preflighted though, just like GET.

like image 138
Ray Nicholus Avatar answered Oct 20 '22 21:10

Ray Nicholus