更合规的解决方案涉及更多,但确实会删除重复的正则表达式以进行域匹配,并且可以放入 sn-ps。
我在http { ... } 块内创建了文件/etc/nginx/snippets/cors-maps.conf,它必须是included。它包含如下规则:
# always set value to append to Vary if Origin is set
map $http_origin $cors_site_v
{
~. 'Origin';
}
# set site-specific origin header if it matches our domain
map $http_origin $cors_site_origin
{
'~^https://(?:[-a-z\d]+\.)+example\.com$' $http_origin;
}
# validate the options only if domain matched
map '$request_method#$cors_site_origin#$http_access_control_request_method' $cors_site_options
{
# is an allowed method
'~^OPTIONS#.+#(?:GET|HEAD|POST|OPTIONS)$' okay;
# requested an unknown/disallowed method
'~^OPTIONS#.' nope;
}
# set value of Access-Control-Allow-Origin only if domain matched
map '$request_method#$cors_site_origin' $cors_site_acao
{
'~^(?:GET|HEAD|POST)#.' $cors_site_origin;
}
# set value of Access-Control-Allow-Credentials only if Origin was allowed
map $cors_site_acao $cors_site_acac
{
~. 'true';
}
然后/etc/nginx/snippets/cors-site.conf 可以是多个location { ... } 块内的included:
# only using "if" safely with a "return" as explained in https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/
# return early without access headers for invalid pre-flight, because origin matched domain
if ($cors_site_options = nope)
{
add_header Vary $cors_site_v;
return 204 '';
}
# return early with access headers for valid pre-flight
if ($cors_site_options = okay)
{
add_header Access-Control-Allow-Origin $cors_site_origin;
add_header Access-Control-Allow-Credentials $cors_site_acac;
add_header Vary $cors_site_v;
add_header Access-Control-Allow-Methods 'GET, HEAD, POST, OPTIONS';
# probably overkill, gleaned from others' examples
add_header Access-Control-Allow-Headers 'Accept, Accept-Language, Authorization, Cache-Control, Content-Language, Content-Type, Cookie, DNT, If-Modified-Since, Keep-Alive, Origin, User-Agent, X-Mx-ReqToken, X-Requested-With';
add_header Access-Control-Max-Age 1728000;
return 204 '';
}
# conditionally set headers on actual requests, without "if", because directive ignored when values are empty strings ("map" default)
add_header Access-Control-Allow-Origin $cors_site_acao;
add_header Access-Control-Allow-Credentials $cors_site_acac;
add_header Vary $cors_site_v;
要匹配的值中的# 并不特殊,它们只是用作分隔符以允许使用多个输入变量进行测试。可以将额外的域添加到 map 的 $cors_site_origin,但需要进行一些调整以支持具有不同允许选项/标题的域。