nginx:如何仅为匹配 URI 设置 proxy_* 指令?

nginx:如何仅为匹配 URI 设置 proxy_* 指令?

我已经研究了这个问题好几个小时了,但还是找不到一个干净的解决方案。

基本上,我有一个 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。

相关内容