Nginx的多个位置问题

我目前正在试图将3个应用程序从一个存储库拆分为3个,但保留了url结构,因此在同一个域中基本上不同的位置必须由不同的应用程序交付。

我正在努力的是,其中一个应用程序需要是不存在的url的后备,所以如果第一个不匹配,第二个不匹配,那么第三个应该处理请求

我得到的结构是:

/ etc / nginx / sites-enabled / main_site,在这里,除了server_name和logs之外,我还有include /etc/nginx/subsites-enabled/* ,其中我有3个configuration文件,每个应用都有一个。

每个configuration文件都包含一个位置块。

我试过在正则expression式(基本上试图硬编码其他应用程序处理的URL)负面的前瞻,但失败了。

所以,总结一下:

/和/社区应该由/etc/nginx/subsites-enabled/example.org/home(几个Perl脚本)

/新闻应通过/etc/nginx/subsites-enabled/example.org/news(wordpress)

其他一切都应该由/etc/nginx/subsites-enabled/example.org/app(蛋糕应用)

perl位工作正常。 我遇到的问题是,应用程序正在接pipe新闻(可能是因为它匹配。*),我已经尝试了各种选项(我已经在这个为期2天),但没有一个解决了所有的问题(有时静态资产将无法工作等)。

我的configuration是:

/etc/nginx/sites-enabled/example.org:

 server { listen 80; server_name example.org; error_log /var/log/nginx/example.org.log; include /etc/nginx/subsites-enabled/example.org/*; } 

/etc/nginx/subsites-enabled/example.org/home:

 location = / { rewrite ^.*$ /index.pl last; } location ~* /community(.*) { rewrite ^.*$ /index.pl last; } location ~ \.pl { root /var/www/vhosts/home; access_log /var/log/nginx/home/access.log; error_log /var/log/nginx/home/error.log; include /etc/nginx/fastcgi_params; fastcgi_index index.pl; fastcgi_param SCRIPT_FILENAME /var/www/vhosts/home$fastcgi_script_name; fastcgi_pass unix:/var/run/fcgiwrap.socket; } 

在/ etc / ngins /启用子网站-/新闻

 location /news { access_log /var/log/nginx/news/access.log; error_log /var/log/nginx/news/error.log debug; error_page 404 = /news/index.php; root /var/www/vhosts/news; index index.php; if (!-e $request_filename) { rewrite ^.*$ /index.php last; } location ~ \.php { include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/vhosts/news$fastcgi_script_name; } } 

在/ etc / nginx的/启用的子网站-/应用:

 location ~ .* { access_log /var/log/nginx/app/access.log; error_log /var/log/nginx/app/error.log; rewrite_log on; index index.php; root /var/www/vhosts/app/app/webroot; if (-f $request_filename) { expires 30d; break; } if (!-e $request_filename) { rewrite ^.*$ /index.php last; } location ~ \.php { include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/vhosts/app/app/webroot$fastcgi_script_name; } } 

你的configuration有几个错误,这两个相关的是:

  1. 位置块内的path仍包含匹配的path。
  2. 用“last”重写,通过查看所有可用位置进行匹配(他们跳出当前位置块)。

例如,采取URL example.org/news/test.htm

  • location /news块将匹配它
  • 使用的path是/news/test.htm – 这不会改变,只是因为它在位置块
  • 将path添加到document_root中,您将获得: /var/www/vhosts/news/news/test.htm
  • 你的if (!-e $request_filename)语句应该捕获这个不存在的文件
  • 您将path重写为/index.php
  • 由于您使用的是last一个进程,所以重新启动(跳出了位置块)
  • /index.php现在被location /app block捕获。

上面提到的问题,根指令,当你去你的应用程序位置块复合。 与“新闻”区块不同的是,您可以从path中删除“新闻”(因为它将被添加回去),所以您无法对以“webroot”结尾的应用程序path执行此操作。

解决scheme在于alias指令。 这不会更改document_root,但会更改用于提供请求的文件path。 不幸的是, rewritetry_files往往会出乎意料try_filesalias

让我们从一个简单的例子开始 – 没有PHP – 只是HTML和Perl块 – 但是与你的文件夹结构相匹配(在Nginx 1.0.12,CentOS 6上testing):

 server { server_name example.org; error_log /var/log/nginx/example.org.error.log notice; access_log /var/log/nginx/example.org.access.log; rewrite_log on; location = / { rewrite ^ /index.pl last; } location ^~ /community { rewrite ^ /index.pl last; } location ~ \.pl { root /var/www/vhosts/home; [fastcgi_stuff...] } location ^~ /news { alias /var/www/vhosts/news; index index.htm; try_files $uri $uri/ /news/index.htm; } location ^~ /app { alias /var/www/vhosts/app/app/webroot; index index.htm; try_files $uri $uri/ /app/index.htm; } location / { rewrite ^/(.*) /app/$1 last; } } 
  • location = / – 只会匹配根path
  • location ^~ /community – 将匹配以/ community开头的每条path
  • location ~ \.pl – 将匹配包含.pl的所有文件
  • location ^~ /news – 将匹配以/ news开始的每条path
  • location ^~ /app – 将匹配以/ app开头的每个path
  • location / – 将匹配上面不匹配的所有path

您应该能够删除^~ – 但它可能会略微提高性能,因为一旦find匹配项就会停止search。

虽然将PHP块添加回来应该是一件简单的事情,但不幸的是,有一点困难 – try_files (和你的重写)最终不会传递所需的path到嵌套的位置块 – 只有当在位置块中指定的扩展名不起作用。

一个解决scheme是使用单独的位置块,与别名指令一起执行捕获 – 它不是很优雅,但据我所知,它工作(再次,在Nginx 1.0.12,CentOS 6上testing)当然,我没有安装CakePHP,Wordpress和Perl – 我只是在每个文件夹中使用了几个PHP和HTML文件)

 server { server_name example.org; error_log /var/log/nginx/example.org.error.log notice; access_log /var/log/nginx/example.org.access.log; rewrite_log on; location = / { rewrite ^ /index.pl last; } location ^~ /community { rewrite ^ /index.pl last; } location ~ \.pl { root /var/www/vhosts/home; access_log /var/log/nginx/home.access.log; error_log /var/log/nginx/home.error.log; include /etc/nginx/fastcgi_params; fastcgi_index index.pl; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/var/run/fcgiwrap.socket; } location /news { access_log /var/log/nginx/news.access.log; error_log /var/log/nginx/news.error.log notice; alias /var/www/vhosts/news; index index.php; try_files $uri $uri/ /news/index.php; } location ~* ^/news/(.*\.php)$ { access_log /var/log/nginx/news.php.access.log; error_log /var/log/nginx/news.php.error.log notice; alias /var/www/vhosts/news/$1; try_files "" /news/index.php; include /etc/nginx/fastcgi_params; fastcgi_index index.php; fastcgi_param SCRIPT_NAME $1; fastcgi_param SCRIPT_FILENAME /var/www/vhosts/news/$1; fastcgi_pass 127.0.0.1:9000; } location /app { alias /var/www/vhosts/app/app/webroot; access_log /var/log/nginx/app.access.log; error_log /var/log/nginx/app.error.log notice; index index.php; try_files $uri $uri/ /app/index.php; } location ~* ^/app/(.*\.php)$ { access_log /var/log/nginx/news.access.log; error_log /var/log/nginx/news.error.log notice; alias /var/www/vhosts/app/app/webroot/$1; try_files "" /app/index.php; include /etc/nginx/fastcgi_params; fastcgi_index index.php; fastcgi_param SCRIPT_NAME $1; fastcgi_param SCRIPT_FILENAME /var/www/vhosts/app/app/webroot/$1; fastcgi_pass 127.0.0.1:9000; } location / { rewrite ^/(.*) /app/$1 last; } } 

上面的configuration,采取上面的简单的一个,并做了两个变化:

  • 添加两个位置块:
    • location ~* ^/news/(.*\.php)$ – 将匹配以.php结尾的所有文件,path以/ news /
    • location ~* ^/app/(.*\.php)$ – 将匹配以.php结尾的所有文件,path以/ app /
  • 删除^~匹配 – 这是必需的,以便两个添加的位置块可以匹配path(否则匹配将停止/新闻或/应用程序块)。

应该指出的是,位置匹配的顺序在这里非常重要:

  • 完全匹配(使用=
  • ^~秒匹配
  • 匹配正则expression式块
  • 常规string – 只有当找不到匹配的正则expression式

一个匹配的正则expression式将取代一个直的string!

需要注意的一点是,当捕获与别名一起使用时,整个URL将被replace,而不仅仅是前导文件夹。 不幸的是,这意味着$fastcgi_script_name是空的 – 所以,我已经使用$1上面的$1

我相信你需要做一些改变,但基本的前提应该是function性的。 您应该能够根据需要将块分成多个文件 – sorting不应该影响configuration。