对于给定的 URL 模式(/scripts/.*\.meta\.js
),我希望有以下行为:
- 如果 URL 包含特定参数(
version
),则将请求交给 Passenger 处理。 - 如果 URL 不包含该特定参数并且存在缓存文件,则提供该文件。
- 如果 URL 不包含该特定参数且缓存文件不存在,则将请求交给 Passenger 处理。
我这样做是为了避免让 Passenger 和其后面的 Rails 应用程序处理这条路径上的大多数请求,从而提高性能。
我的 nginx conf 文件是:
server {
listen 80;
server_name my.site;
root /path/to/rails/public;
passenger_enabled on;
rails_env development;
passenger_min_instances 1;
client_max_body_size 5m;
location ~* /scripts/.*\.meta\.js {
error_page 418 = @noparams;
if ( $arg_version = '' ) {
return 418;
}
}
location @passenger {
root /path/to/rails/public;
proxy_set_header X-Forwarded-Proto http;
passenger_enabled on;
}
location @noparams {
try_files /a$uri @passenger =401;
}
}
我已将测试文件放在 下/path/to/rails/public/a
。这会产生以下行为:
- ✓ 如果URL包含特定参数(
version
),则将请求交给Passenger处理。 - ✓ 如果 URL 不包含该特定参数且存在缓存文件,则提供该文件。
- ❌ 如果 URL 不包含该特定参数且缓存文件不存在,则将请求交给 Passenger 处理。实际行为:HTTP 401。
看来我所拥有的不是引用 Passenger 的正确方法try_files
。我需要做什么才能使其工作?
答案1
我的印象是,这try_files
是要尝试的“事物”列表,您可以将命名位置放在任何位置。正如 Michael Hampton 在评论中指出的那样,这是不正确的。命名位置和 HTTP 代码只能位于 中的最后一个位置try_files
;任何不在最后一个位置的东西都必须是文件路径。所以try_files /a$uri @passenger
它按我的意图工作。
@passenger
由于配置是从块继承而来的,因此也没有必要重复内部配置server
。因此,工作配置是:
server {
listen 80;
server_name my.site;
root /path/to/rails/public;
passenger_enabled on;
rails_env development;
passenger_min_instances 1;
client_max_body_size 5m;
location ~* /scripts/.*\.meta\.js {
error_page 418 = @noparams;
if ( $arg_version = '' ) {
return 418;
}
}
location @passenger { }
location @noparams {
try_files /a$uri @passenger;
}
}