nginx config to enable CORS with origin matching
You can try to use map
istead of the first if
block:
map $http_origin $allow_origin { ~^http://(www\.)?example.com$ $http_origin;}map $http_origin $allow_methods { ~^http://(www\.)?example.com$ "OPTIONS, HEAD, GET";}server { listen 80 default_server; root /var/www; location / { add_header Access-Control-Allow-Origin $allow_origin; add_header Access-Control-Allow-Methods $allow_methods; # Handling preflight requests if ($request_method = OPTIONS) { add_header Content-Type text/plain; add_header Content-Length 0; return 204; } }}
nginx will refuse to add an empty HTTP headers, so they will be added only if Origin
header is present in request and matched this regex.
The only solution I've found so far is a hack to use a variable to aggregate multiple conditions and then match it with only a single if statement, therefore duplicating some directives:
server { listen 80 default_server; root /var/www; location / { set $cors ''; set $cors_allowed_methods 'OPTIONS, HEAD, GET'; if ($http_origin ~ '^https?://(www\.)?example.com$') { set $cors 'origin_matched'; } # Preflight requests if ($request_method = OPTIONS) { set $cors '${cors} & preflight'; } if ($cors = 'origin_matched') { add_header Access-Control-Allow-Origin $http_origin; } if ($cors = 'origin_matched & preflight') { add_header Access-Control-Allow-Origin $http_origin always; add_header Access-Control-Allow-Methods $cors_allowed_methods; add_header Content-Type text/plain; add_header Content-Length 0; return 204; } }}
Without getting into the details of your nginx setup, it's not going to work anyway, because the CORS header's you're returning are incorrect...
Specifically:
For preflight (OPTIONS) requests, the following are the only meaningful CORS response headers:
Access-Control-Allow Origin
, (required),Access-Control-Allow Credentials
(optional),Access-Control-Allow-Methods
, (required),Access-Control-Allow-Headers
, (required) andAccess-Control-Max-Age
, (optional). Any others are ignored.For regular (non-OPTIONS) requests, the following are the only meaningful CORS response headers:
Access-Control-Allow Origin
(required),Access-Control-Allow Credentials
(optional) andAccess-Control-Expose-Headers
(optional). Any others are ignored.
Note those required headers for pre-flight requests - currently you're only passing two of them... Also, note that you don't need to return Access-Control-Allow-Methods
for a non-OPTIONS request - it's not 'valid', so will be ignored.
As far as your specific nginx issue goes, I think @Slava Fomin II has the correct-est answer...