I think I pretty well understand CORS but still I get a but puzzled about the browser behaviors when it comes to the preflight requests.
Let's say the browser creates this preflight request:
OPTIONS http://myserver.local:7000/api/order/4 HTTP/1.1
Host: myserver.local:7000
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-my-custom-header
Origin: http://localhost:5000
Sec-Fetch-Mode: cors
Referer: http://localhost:5000/
and my API returns:
HTTP/1.1 204 No Content
Date: Wed, 09 Mar 2022 12:52:50 GMT
Server: Kestrel
Access-Control-Allow-Headers: x-my-custom-header
Access-Control-Allow-Methods: PUT,DELETE
Access-Control-Allow-Origin: http://localhost:5000
Vary: Origin
Now, you see the browser responds with allowed methods PUT/DELETE but the request is for POST that is not in the Allow-Methods list.
Should the browser not block this request due to the mismatch in the allow-methods header?
Or is enough that the server responds with 20x status code for the browser to accept the preflight and then carry out the actual request?
My assumptions was that the browser would compare the allow-methods and block the request if the requested method did no match?
Or did I miss something?
CodePudding user response:
An interesting question!
TL;DR
No, the browser doesn't require the server to explicitly allow the POST
method, because the latter, as a so-called CORS-safelisted method, gets a free pass.
More details
What the spec says
The answer, as always, lies in section 4.8 of the Fetch standard, which specifies how CORS preflight works:
- Let methods be the result of extracting header list values given
Access-Control-Allow-Methods
and response’s header list.
And further down:
- If request’s method is not in methods, request’s method is not a CORS-safelisted method, and request’s credentials mode is
"include"
or methods does not contain*
, then return a network error.
(my emphasis)
What is a CORS-safelisted method? The term is defined in section 2.2.1:
A CORS-safelisted method is a method that is
GET
,HEAD
, orPOST
.
Conclusion
If the method of the CORS request is one of GET
, HEAD
, or POST
, the browser doesn't require the server to explicitly list that method in the Access-Control-Allow-Methods
header for CORS preflight to succeed.
Experiment
I've found Jake Archibald's CORS playground useful for testing my (mis)understanding of CORS. Running this particular instance in your browser may convince you that the POST
method doesn't need to be explicitly allowed for CORS preflight to succeed.