nginx:在重写位置块中指定自定义标头

nginx:在重写位置块中指定自定义标头

location我正在尝试仅为nginx 中的特定块设置一些标头。

我遇到的问题是这些location块包含rewrite语句,这些语句显然会删除自定义标题。

在此示例中,我想要两条规则:

  • 里面的文件/static应该有expires max;(设置标题Cache-Control: max-age=some huge valueExpires: some future date really far off),并且它们的名称被重写为不包含的内容/static
  • 其他地方的文件都应该有Cache-Control: public(没有max-age

这是我尝试过的配置:

server {
    listen [::]:80;
    root /somepath;
    location /static {
        expires max;
        rewrite /static(.*) /whatever$1;
    }
    add_header Cache-Control public;
}

并具有以下目录结构:

/somepath
/somepath/f1.txt
/somepath/static/f2.txt

然后我们得到以下信息:

  • f1.txt: Cache-Control: public,无Expires标题
  • f2.txt: Cache-Control: public,无Expires标题

这对于 有效,f1.txt但不是f2.txt。我希望它是这样的:

  • f1.txt: Cache-Control: public,无Expires标题
  • f2.txtCache-Control: max-age=some huge valueExpires: some future date really far off

我认为问题出在这rewrite /static(.*) /whatever$1;行代码中,它使得 nginx 取消了迄今为止添加的标头,然后再次添加它们(从而重新添加Cache-Control)。因此,一个简单的解决方法是:

server {
    listen [::]:80;
    root /somepath;
    location /static {
        rewrite /static(.*) /whatever$1;
    }
    location /whatever {
        expires max;
    }
    add_header Cache-Control public;
}

问题是,在我的实际配置文件中,rewrite看起来并不那么友好。重写的 URL 是不容易匹配在某种程度上,它也不会匹配一些不应该匹配的文件expires max,所以我无法真正使用这种解决方法。

有没有办法让这些标题在之后保留下来rewrite

编辑:我的真实 URL 如下:

location ~ /(?:posts-)?img/.*-res- {
    access_log               off;
    expires                  max;
    rewrite                  "/img/(.*)-res-.{8}(.*)" /img/$1$2;
    rewrite                  "/posts-img/(.*)-res-.{8}(.*)" /posts/$1$2;
}

虽然我可以添加一个location块来/img处理使用第一条rewrite规则重写的文件,但我无法为第二条规则添加一个块(/posts),因为中的一些文件/posts不是可缓存的资源,因此不应该有expires max

编辑2:完整配置(或至少包含所有相关部分):

server {
    listen [::]:80;
    root /somepath;
    server_name domain.tld;
    location ~ /(?:posts-)?img/.*-res- {
        access_log               off;
        expires                  max;
        rewrite                  "/img/(.*)-res-.{8}(.*)" /img/$1$2;
        rewrite                  "/posts-img/(.*)-res-.{8}(.*)" /posts/$1$2;
    }
    add_header Cache-Control public;
}

目录结构:

/somepath
/somepath/img/f1.png
/somepath/posts/post1.html
/somepath/posts/d1/f2.png
/somepath/posts/d2/f2.png

根据 HTTP 请求的预期行为:

  • GET /somepath:/somepath搭配Cache-Control: public
  • GET /somepath/img/f1.png:/somepath/img/f1.png搭配Cache-Control: public
  • GET /somepath/img/f1-res-whatever.png/somepath/img/f1.png使用发送的标头提供服务expires max
  • GET /somepath/posts/post1.html:/somepath/posts/post1.html搭配Cache-Control: public
  • GET /somepath/posts/d1/f2.png:/somepath/posts/d1/f2.png搭配Cache-Control: public
  • GET /somepath/posts-img/d1/f2-res-whatever.png/somepath/posts/d1/f2.png使用发送的标头提供服务expires max

答案1

这应该可以工作(不过,我使用稍微简单的配置验证了这一点)。顺便说一句,Igor Sysoev 建议尽可能少地使用正则表达式位置。

    location /img {
        if ($arg_max) { expires max; }
        ...
    }

    location /posts-img {
        if ($arg_max) { expires max; }
        ...
    }

    location ~ /(?:posts-)?img/.*-res- {
        access_log               off;
        expires                  max;
        rewrite                  "/img/(.*)-res-.{8}(.*)" /img/$1$2?max=1;
        rewrite                  "/posts-img/(.*)-res-.{8}(.*)" /posts/$1$2?max=1;
    }

答案2

对于不区分大小写位置匹配

location ~* /static/

不区分大小写删除“ ***** ”

location ~* /static/

源 Nginx 位置指令文档

相关内容