使nginx重写相对

使nginx重写相对,nginx,Nginx,我有一个web应用程序(由另一个团队编写),它附带了一个nginx配置代码段来提供重写: rewrite ^list /ctrl/list.php last; rewrite ^new /ctrl/new.php last; 然后,此代码段可以包含在nginx配置的服务器块中: server { server_name ...; include /path/to/snippet; } 不幸的是,只有当应用程序托管在docroot中时,这种方法才有效。即使重写在位置块中 server

我有一个web应用程序(由另一个团队编写),它附带了一个nginx配置代码段来提供重写:

rewrite ^list /ctrl/list.php last;
rewrite ^new /ctrl/new.php last;
然后,此代码段可以包含在nginx配置的服务器块中:

server {
  server_name ...;

  include /path/to/snippet;
}
不幸的是,只有当应用程序托管在docroot中时,这种方法才有效。即使重写在
位置
块中

server {
  server_name ...

  location /subdir/ {
    include /path/to/subdir/snippet
  }
}
。。。它不起作用,因为regex和replacement of
rewrite
仍然是相对于docroot的。当然,由于应用程序文件对
/subdir/
一无所知,因此不能将其包含在重写中

我需要告诉nginx“处理与此子目录相关的以下所有重写”

我可以要求其他团队在重写中包含某种变量,但据我所知,nginx的配置中没有任何宏扩展


当应用程序托管在Apache上时,它可以很好地处理相应的.htaccess文件,因为.htaccess中的重写是相对于.htaccess文件的位置进行的。尽管如此,我还是非常喜欢使用nginx。

为了不重新编译nginx,我想出了一个相当笨拙的解决方法。只有当include实际用于子目录位置时才需要它——当应用程序安装在服务器块的根目录中时,include就可以被包含

其思想是首先将该位置块的每个URI重写为自身,而不使用subdir,然后应用包含的重写规则,最后将其重写回subdir路径:

server {
  server_name ...

  # This has to be a regex check because they run first:
  location ~ ^/subdir/ {
    rewrite ^/subdir/(.*) /$1;

    include /path/to/subdir/snippet
  }
  ...
之后,必须通过在每个最终位置块中进行额外的重写来取消初始重写。此重写设置了
break
标志,以确保不会再次尝试上一个块(导致无限循环运行10次):


我还没有尝试过,但是通过重新编译nginx来添加custome模块(所有nginx模块都是在中编译的),应该可以得到更干净的解决方案。这是

即使不重新编译,也可以使用变量将子目录添加到rewrite指令的替换部分,因此困难的部分是将其添加到正则表达式模式。
ngx_http_rewrite
模块实际上并不执行正则表达式匹配,而只是将其编译为
ngx_http_脚本
模块的指令(
ngx_http_脚本
)。它位于regex结构上,它告诉
ngx\u http\u脚本
模块发送请求

因此,在匹配之前,应该可以将当前位置前缀添加到模式中,或者将其从URI中删除

  location / {
    root   /var/www;

    rewrite ^(.*) /subdir$1 break;
  }

  location ~ \.php$ {
    proxy_pass   http://127.0.0.1;

    rewrite ^(.*) /subdir$1 break;
  }