Nginx 位置,try_files 和 headers 问题
Nginx locations, try_files and headers issue
所以我用 Puma 替换了 Passenger 作为 Rails 应用程序,我刚刚注意到我现在的 cdn 资产有问题,它们现在给出 CORS 错误。
当我使用 Passenger 时,我对 Nginx 进行了以下配置:
server {
server_name mysite.com;
root /var/www/mysite.com/public;
client_max_body_size 4000M;
passenger_enabled on;
rails_env production;
location ~* ^/cdn/ {
add_header Access-Control-Allow-Origin *;
expires 364d;
add_header Pragma public;
add_header Cache-Control "public";
break;
}
location ~* ^/assets/ {
# Per RFC2616 - 1 year maximum expiry
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
expires 1y;
add_header Cache-Control public;
# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
listen 443 ssl; # managed by Certbot
#the rest of the certbot ssl stuff
}
然后我将配置更改为此,使其适用于 Puma 和 unix 套接字:
upstream puma {
server unix:///var/www/mysite.com/shared/sockets/puma.sock;
}
server {
server_name mysite.com;
root /var/www/mysite.com/public;
client_max_body_size 4000M;
location / {
try_files $uri @app;
}
location ~* ^/cdn/ {
add_header Access-Control-Allow-Origin *;
expires 364d;
add_header Pragma public;
add_header Cache-Control "public";
break;
}
location ~* ^/assets/ {
# Per RFC2616 - 1 year maximum expiry
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
expires 1y;
add_header Cache-Control public;
# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
listen 443 ssl; # managed by Certbot
#ssl stuff
location @app {
proxy_pass http://puma;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 128;
proxy_redirect off;
}
}
这工作正常,但后来我注意到 cdn url 给出了 404,所以我将 cdn 位置更新为此(我添加了 try_files $uri @app;
):
location ~* ^/cdn/ {
add_header Access-Control-Allow-Origin *;
expires 364d;
add_header Pragma public;
add_header Cache-Control "public";
try_files $uri @app;
break;
}
这现在有效,但我收到 CORS 错误,所以似乎 headers 没有设置。
我的猜测是 try_files
忽略了调用之前设置的内容,所以我尝试在 location @app
中设置代理 header 以进行访问控制(通过添加 proxy_set_header Access-Control-Allow-Origin *;
) 但我仍然收到错误。
解决这个问题的正确方法是什么?
尝试使用 proxy_set_header
指令添加响应 headers 是没有意义的 - 它是为 adding/changing headers 设计的被传送到上游。要添加响应 headers,无论是静态位置还是代理位置,请使用 add_header
响应。要有条件地添加 headers,假设根据请求 URI,您可以使用 map
块:
map $uri $expires {
~^/cdn/ 1y;
default off;
}
map $uri $cache_control {
~^/cdn/ public;
# default will be an empty value
}
map $uri $allow_origin {
~^/cdn/ *;
# default will be an empty value
}
然而,就性能而言,由于所有 map
派生的变量在每个请求中只被评估一次,因此只匹配一次正则表达式模式可以稍微提高性能:
map $cache $expires {
1 1y;
default off;
}
map $cache $cache_control {
1 public;
}
map $cache $allow_origin {
1 *;
}
map $uri $cache {
~^/cdn/ 1;
}
接下来,在您的 @app
位置,您可以使用以下内容:
location @app {
proxy_pass http://puma;
expires $expires;
add_header Cache-Control $cache_control;
add_header Access-Control-Allow-Origin $allow_origin;
# ... proxy_set_... and other upstream setup here
}
如果 add_header
指令中使用的评估变量为空,nginx 将不会添加具有空值的 header - 相反它不会添加这样的 header完全没有。
关于您当前配置的几点注意事项:
使用像 location ~ ^/cdn/ { ... }
或 location ~ ^/assets/ { ... }
这样的正则表达式位置来支持前缀位置 location /cdn/ { ... }
或 location /assets/ { ... }
是没有意义的,只是性能影响(由于在不需要时涉及 PCRE 库)。
静态位置末尾的 break
指令不执行任何操作,因为重写模块中没有任何应该停止执行的指令。
所以我用 Puma 替换了 Passenger 作为 Rails 应用程序,我刚刚注意到我现在的 cdn 资产有问题,它们现在给出 CORS 错误。
当我使用 Passenger 时,我对 Nginx 进行了以下配置:
server {
server_name mysite.com;
root /var/www/mysite.com/public;
client_max_body_size 4000M;
passenger_enabled on;
rails_env production;
location ~* ^/cdn/ {
add_header Access-Control-Allow-Origin *;
expires 364d;
add_header Pragma public;
add_header Cache-Control "public";
break;
}
location ~* ^/assets/ {
# Per RFC2616 - 1 year maximum expiry
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
expires 1y;
add_header Cache-Control public;
# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
listen 443 ssl; # managed by Certbot
#the rest of the certbot ssl stuff
}
然后我将配置更改为此,使其适用于 Puma 和 unix 套接字:
upstream puma {
server unix:///var/www/mysite.com/shared/sockets/puma.sock;
}
server {
server_name mysite.com;
root /var/www/mysite.com/public;
client_max_body_size 4000M;
location / {
try_files $uri @app;
}
location ~* ^/cdn/ {
add_header Access-Control-Allow-Origin *;
expires 364d;
add_header Pragma public;
add_header Cache-Control "public";
break;
}
location ~* ^/assets/ {
# Per RFC2616 - 1 year maximum expiry
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
expires 1y;
add_header Cache-Control public;
# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
listen 443 ssl; # managed by Certbot
#ssl stuff
location @app {
proxy_pass http://puma;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 128;
proxy_redirect off;
}
}
这工作正常,但后来我注意到 cdn url 给出了 404,所以我将 cdn 位置更新为此(我添加了 try_files $uri @app;
):
location ~* ^/cdn/ {
add_header Access-Control-Allow-Origin *;
expires 364d;
add_header Pragma public;
add_header Cache-Control "public";
try_files $uri @app;
break;
}
这现在有效,但我收到 CORS 错误,所以似乎 headers 没有设置。
我的猜测是 try_files
忽略了调用之前设置的内容,所以我尝试在 location @app
中设置代理 header 以进行访问控制(通过添加 proxy_set_header Access-Control-Allow-Origin *;
) 但我仍然收到错误。
解决这个问题的正确方法是什么?
尝试使用 proxy_set_header
指令添加响应 headers 是没有意义的 - 它是为 adding/changing headers 设计的被传送到上游。要添加响应 headers,无论是静态位置还是代理位置,请使用 add_header
响应。要有条件地添加 headers,假设根据请求 URI,您可以使用 map
块:
map $uri $expires {
~^/cdn/ 1y;
default off;
}
map $uri $cache_control {
~^/cdn/ public;
# default will be an empty value
}
map $uri $allow_origin {
~^/cdn/ *;
# default will be an empty value
}
然而,就性能而言,由于所有 map
派生的变量在每个请求中只被评估一次,因此只匹配一次正则表达式模式可以稍微提高性能:
map $cache $expires {
1 1y;
default off;
}
map $cache $cache_control {
1 public;
}
map $cache $allow_origin {
1 *;
}
map $uri $cache {
~^/cdn/ 1;
}
接下来,在您的 @app
位置,您可以使用以下内容:
location @app {
proxy_pass http://puma;
expires $expires;
add_header Cache-Control $cache_control;
add_header Access-Control-Allow-Origin $allow_origin;
# ... proxy_set_... and other upstream setup here
}
如果 add_header
指令中使用的评估变量为空,nginx 将不会添加具有空值的 header - 相反它不会添加这样的 header完全没有。
关于您当前配置的几点注意事项:
使用像
location ~ ^/cdn/ { ... }
或location ~ ^/assets/ { ... }
这样的正则表达式位置来支持前缀位置location /cdn/ { ... }
或location /assets/ { ... }
是没有意义的,只是性能影响(由于在不需要时涉及 PCRE 库)。静态位置末尾的
break
指令不执行任何操作,因为重写模块中没有任何应该停止执行的指令。