![nginx:在重写位置块中指定自定义标头](https://linux22.com/image/797832/nginx%EF%BC%9A%E5%9C%A8%E9%87%8D%E5%86%99%E4%BD%8D%E7%BD%AE%E5%9D%97%E4%B8%AD%E6%8C%87%E5%AE%9A%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%87%E5%A4%B4.png)
location
我正在尝试仅为nginx 中的特定块设置一些标头。
我遇到的问题是这些location
块包含rewrite
语句,这些语句显然会删除自定义标题。
在此示例中,我想要两条规则:
- 里面的文件
/static
应该有expires max;
(设置标题Cache-Control: max-age=some huge value
和Expires: 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.txt
:Cache-Control: max-age=some huge value
,Expires: 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;
}