nginx 尝试服务 .rss/.json 本身而不是让 rails/unicorn 服务它
nginx tries to serve .rss/.json itself rather than letting rails/unicorn serve it
我的 rails 应用程序在使用 nginx 和 unicorn 的生产环境中运行良好,除了一件事:
请求 /articles.rss
和 /articles.json
会导致 404,并在 nginx 日志中显示请求的文件不存在的错误。要求例如/articles?format=rss
有效。所以看起来 .rss 导致 nginx 认为这是一个静态文件而不是动态生成的内容。在开发中(使用 rails 的内置服务器)这工作正常。
我使用 h5bp config files for nginx,这是我的站点配置(域名已替换):
# www to non-www redirect -- duplicate content is BAD:
# https://github.com/h5bp/html5-boilerplate/blob/5370479476dceae7cc3ea105946536d6bc0ee468/.htaccess#L362
# Choose between www and non-www, listen on the *wrong* one and redirect to
# the right one -- http://wiki.nginx.org/Pitfalls#Server_Name
upstream app {
server unix:/var/www/rails-cms/shared/tmp/sockets/rails-cms.unicorn.sock fail_timeout=0;
}
server {
# don't forget to tell on which port this server listens
listen [::]:80;
listen 80;
# listen on the www host
server_name www.<my domain>;
# and redirect to the non-www host (declared below)
return 301 $scheme://<my domain>$request_uri;
}
server {
# listen [::]:80 accept_filter=httpready; # for FreeBSD
# listen 80 accept_filter=httpready; # for FreeBSD
# listen [::]:80 deferred; # for Linux
# listen 80 deferred; # for Linux
listen [::]:80;
listen 80;
# The host name to respond to
server_name <my domain>;
# Path for static files
root /var/www/rails-cms/current/public;
try_files $uri/index.html $uri @app;
location @app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app;
}
#Specify a charset
charset utf-8;
# Custom 404 page
error_page 404 /404.html;
# Include the basic h5bp config set
include h5bp/basic.conf;
}
发生这种情况是因为您包含 h5bp/basic.conf
文件,而该文件又包含 h5bp/location/expires.conf
文件。看一下后一个文件的内容:
# cache.appcache, your document html and data
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
expires -1;
access_log logs/static.log;
}
# Feed
location ~* \.(?:rss|atom)$ {
expires 1h;
add_header Cache-Control "public";
}
看到了吗?第一个 location
拦截 .json
请求,第二个 .rss
请求,因此您的应用永远不会捕获这些请求。
如果您希望您的应用程序处理这些请求,您应该完全拒绝 h5bp
,或者只注释掉上述 location
s.
在这两种情况下,您的应用都应该发送缓存 headers 本身,当然如果您需要的话。
编辑:
但是由于您的 json
和 rss
内容是动态生成的,我不建议使用缓存 headers。
我的 rails 应用程序在使用 nginx 和 unicorn 的生产环境中运行良好,除了一件事:
请求 /articles.rss
和 /articles.json
会导致 404,并在 nginx 日志中显示请求的文件不存在的错误。要求例如/articles?format=rss
有效。所以看起来 .rss 导致 nginx 认为这是一个静态文件而不是动态生成的内容。在开发中(使用 rails 的内置服务器)这工作正常。
我使用 h5bp config files for nginx,这是我的站点配置(域名已替换):
# www to non-www redirect -- duplicate content is BAD:
# https://github.com/h5bp/html5-boilerplate/blob/5370479476dceae7cc3ea105946536d6bc0ee468/.htaccess#L362
# Choose between www and non-www, listen on the *wrong* one and redirect to
# the right one -- http://wiki.nginx.org/Pitfalls#Server_Name
upstream app {
server unix:/var/www/rails-cms/shared/tmp/sockets/rails-cms.unicorn.sock fail_timeout=0;
}
server {
# don't forget to tell on which port this server listens
listen [::]:80;
listen 80;
# listen on the www host
server_name www.<my domain>;
# and redirect to the non-www host (declared below)
return 301 $scheme://<my domain>$request_uri;
}
server {
# listen [::]:80 accept_filter=httpready; # for FreeBSD
# listen 80 accept_filter=httpready; # for FreeBSD
# listen [::]:80 deferred; # for Linux
# listen 80 deferred; # for Linux
listen [::]:80;
listen 80;
# The host name to respond to
server_name <my domain>;
# Path for static files
root /var/www/rails-cms/current/public;
try_files $uri/index.html $uri @app;
location @app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app;
}
#Specify a charset
charset utf-8;
# Custom 404 page
error_page 404 /404.html;
# Include the basic h5bp config set
include h5bp/basic.conf;
}
发生这种情况是因为您包含 h5bp/basic.conf
文件,而该文件又包含 h5bp/location/expires.conf
文件。看一下后一个文件的内容:
# cache.appcache, your document html and data
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
expires -1;
access_log logs/static.log;
}
# Feed
location ~* \.(?:rss|atom)$ {
expires 1h;
add_header Cache-Control "public";
}
看到了吗?第一个 location
拦截 .json
请求,第二个 .rss
请求,因此您的应用永远不会捕获这些请求。
如果您希望您的应用程序处理这些请求,您应该完全拒绝 h5bp
,或者只注释掉上述 location
s.
在这两种情况下,您的应用都应该发送缓存 headers 本身,当然如果您需要的话。
编辑:
但是由于您的 json
和 rss
内容是动态生成的,我不建议使用缓存 headers。