我已经研究了这个问题好几个小时了,但还是找不到一个干净的解决方案。
基本上,我有一个 nginx 代理设置,它工作得很好,但我想手动处理一些 URL。具体来说,有 2-3 个位置我想将 proxy_ignore_headers 设置为 Set-Cookie 以强制 nginx 缓存它们(nginx 不会按照http://wiki.nginx.org/HttpProxyModule#proxy_ignore_headers)。
因此对于这些地点,我只想设置proxy_ignore_headers Set-Cookie;
除了设置和复制每个配置值之外,我尝试了所有我能想到的方法,但都没有任何效果。
我试过:
- 嵌套位置指令,希望与我的文件匹配的内部位置只会设置此值并继承其余值,但事实并非如此 - 它似乎忽略了在外部位置设置的任何内容,最明显的是,
proxy_pass
我最终得到了 404)。 - 在 if 块中指定
proxy_cache_valid
与 $request_uri 匹配的指令,但 nginx 抱怨说不允许(proxy_cache_valid
这里不允许使用“ ”指令)。 - 在 if 块中指定一个等于“Set-Cookie”的变量,然后尝试稍后将 proxy_cache_valid 设置为该变量,但 nginx 不允许在这种情况下使用变量并抛出。
它应该很简单——修改/附加一些请求的单个指令,但我还无法让 nginx 做到这一点。
我在这里遗漏了什么?
是否有一种方法可以将常用指令包装在可重用的块中,并在添加各自独特的位后让多个位置块引用它?
谢谢。
仅供参考,主要位置/块包含在下面,以及我针对特定 URI 失败的 proxy_ignore_headers 指令。
location / {
# Setup var defaults
set $no_cache "";
# If non GET/HEAD, don't cache & mark user as uncacheable for 1 second via cookie
if ($request_method !~ ^(GET|HEAD)$) {
set $no_cache "1";
}
if ($http_user_agent ~* '(iphone|ipod|ipad|aspen|incognito|webmate|android|dream|cupcake|froyo|blackberry|webos|s8000|bada)') {
set $mobile_request '1';
set $no_cache "1";
}
# feed crawlers, don't want these to get stuck with a cached version, especially if it caches a 302 back to themselves (infinite loop)
if ($http_user_agent ~* '(FeedBurner|FeedValidator|MediafedMetrics)') {
set $no_cache "1";
}
# Drop no cache cookie if need be
# (for some reason, add_header fails if included in prior if-block)
if ($no_cache = "1") {
add_header Set-Cookie "_mcnc=1; Max-Age=17; Path=/";
add_header X-Microcachable "0";
}
# Bypass cache if no-cache cookie is set, these are absolutely critical for Wordpress installations that don't use JS comments
if ($http_cookie ~* "(_mcnc|comment_author_|wordpress_(?!test_cookie)|wp-postpass_)") {
set $no_cache "1";
}
if ($request_uri ~* wpsf-(img|js)\.php) {
proxy_ignore_headers Set-Cookie;
}
# Bypass cache if flag is set
proxy_no_cache $no_cache;
proxy_cache_bypass $no_cache;
# under no circumstances should there ever be a retry of a POST request, or any other request for that matter
proxy_next_upstream off;
proxy_read_timeout 86400s;
# Point nginx to the real app/web server
proxy_pass http://localhost;
# Set cache zone
proxy_cache microcache;
# Set cache key to include identifying components
proxy_cache_key $scheme$host$request_method$request_uri$mobile_request;
# Only cache valid HTTP 200 responses for this long
proxy_cache_valid 200 15s;
#proxy_cache_min_uses 3;
# Serve from cache if currently refreshing
proxy_cache_use_stale updating timeout;
# Send appropriate headers through
proxy_set_header Host $host;
# no need for this proxy_set_header X-Real-IP $remote_addr;
# no need for this proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Set files larger than 1M to stream rather than cache
proxy_max_temp_file_size 1M;
access_log /var/log/nginx/androidpolice-microcache.log custom;
}
答案1
在尝试了 10 种不同的方法并咨询了 Fenn Bailey 之后http://fennb.com,我不得不求助于包含解决方案,这似乎是唯一可以避免代码重复并且真正有效的方法。
我将所有指令从 location / {} 移到它们自己的文件中,然后执行以下操作:
location / {
include /etc/nginx/vhosts/androidpolice-root.conf;
}
location ~* wpsf-(img|js)\.php {
include /etc/nginx/vhosts/androidpolice-root.conf;
proxy_ignore_headers "Set-Cookie" "Cache-Control";
}
在这一点上,我对 nginx 在 if 和条件方面的不灵活性感到非常震惊 —— 这些事情应该是如此微不足道,但事实并非如此。
顺便说一下,我使用的是最新版的 nginx 1.1.17。