# | |
# Slightly tighter CORS config for nginx | |
# | |
# A modification of https://gist.github.com/1064640/ to include a white-list of URLs | |
# | |
# Despite the W3C guidance suggesting that a list of origins can be passed as part of | |
# Access-Control-Allow-Origin headers, several browsers (well, at least Firefox) | |
# don't seem to play nicely with this. | |
# | |
# To avoid the use of 'Access-Control-Allow-Origin: *', use a simple-ish whitelisting | |
# method to control access instead. | |
# | |
# NB: This relies on the use of the 'Origin' HTTP Header. | |
location / { | |
if ($http_origin ~* (whitelist\.address\.one|whitelist\.address\.two)) { | |
set $cors "true"; | |
} | |
# Nginx doesn't support nested If statements. This is where things get slightly nasty. | |
# Determine the HTTP request method used | |
if ($request_method = 'OPTIONS') { | |
set $cors "${cors}options"; | |
} | |
if ($request_method = 'GET') { | |
set $cors "${cors}get"; | |
} | |
if ($request_method = 'POST') { | |
set $cors "${cors}post"; | |
} | |
if ($cors = "true") { | |
# Catch all incase there's a request method we're not dealing with properly | |
add_header 'Access-Control-Allow-Origin' "$http_origin"; | |
} | |
if ($cors = "trueget") { | |
add_header 'Access-Control-Allow-Origin' "$http_origin"; | |
add_header 'Access-Control-Allow-Credentials' 'true'; | |
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; | |
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; | |
} | |
if ($cors = "trueoptions") { | |
add_header 'Access-Control-Allow-Origin' "$http_origin"; | |
# | |
# Om nom nom cookies | |
# | |
add_header 'Access-Control-Allow-Credentials' 'true'; | |
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; | |
# | |
# Custom headers and headers various browsers *should* be OK with but aren't | |
# | |
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; | |
# | |
# Tell client that this pre-flight info is valid for 20 days | |
# | |
add_header 'Access-Control-Max-Age' 1728000; | |
add_header 'Content-Type' 'text/plain charset=UTF-8'; | |
add_header 'Content-Length' 0; | |
return 204; | |
} | |
if ($cors = "truepost") { | |
add_header 'Access-Control-Allow-Origin' "$http_origin"; | |
add_header 'Access-Control-Allow-Credentials' 'true'; | |
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; | |
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; | |
} | |
} |
This comment has been minimized.
This comment has been minimized.
Thanks for this. I think you want a |
This comment has been minimized.
This comment has been minimized.
$http_origin is empty on my system. Is there some mechanism needed to have this available? |
This comment has been minimized.
This comment has been minimized.
curl -I -X OPTIONS -H "Origin: http://www.example.com" http://www.yourdomain.com |
This comment has been minimized.
This comment has been minimized.
Hi, I have observed when I use an if statement within a location then nginx returns a 404. So the below does not work: if ($cors = "true") { try_files $uri $uri/ /index.php?$args; causes nginx to not reach the try_files directive and return a 404. Anyone else with this issue? |
This comment has been minimized.
This comment has been minimized.
@spyrospph I have the same problem, and it's also documented at IfIsEvil. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
What does 'X-Mx-ReqToken' header actually do? I see it in all CORS tutorials for nginx but can't find any info otherwise. |
This comment has been minimized.
This comment has been minimized.
This is very helpful |
This comment has been minimized.
This comment has been minimized.
According to nginx, |
This comment has been minimized.
This comment has been minimized.
Correct ^ |
This comment has been minimized.
This comment has been minimized.
Very well, thanks |
This comment has been minimized.
This comment has been minimized.
+1 came here to say this |
This comment has been minimized.
This comment has been minimized.
it is great,thank you ,it works. |
This comment has been minimized.
This comment has been minimized.
Because the use of if is evil inside location like @mox601 and @bfricka said before, this was my solution::
|
This comment has been minimized.
This comment has been minimized.
I couldn't even get
|
This comment has been minimized.
This comment has been minimized.
If you're using PHP this basic set up may help.
<?php
require realpath(dirname(__FILE__)) .'/../src/bootstrap.php';
header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range");
switch (true) {
case '/api/query' === $_SERVER['REQUEST_URI'] && $_SERVER['REQUEST_METHOD'] === 'POST':
require APP_PATH . '/src/Api/Query.php';
exit;
case $_SERVER['REQUEST_METHOD'] === 'OPTIONS':
http_response_code(204);
exit;
default:
http_response_code(404);
exit;
} |
This comment has been minimized.
This comment has been minimized.
Hello, I have fixed
|
This comment has been minimized.
This is very great. I commented it, updated various parts (e.g., not returning preflight response headers to actual requests), and put the result here: https://gist.github.com/algal/5480916 .