我目前正尝试将一个存储库中的 3 个应用程序拆分成 3 个,但保留 url 结构,因此基本上同一域下的不同位置必须由不同的应用程序提供。
我所苦苦挣扎的是,其中一个应用程序需要作为不存在的 URL 的后备,因此,如果第一个应用程序不匹配,而第二个应用程序不匹配,那么第三个应用程序应该处理该请求
我得到的结构是:
/etc/nginx/sites-enabled/main_site,在这里,除了 server_name 和 logs 之外include /etc/nginx/subsites-enabled/*
,我还有 3 个配置文件,每个应用程序一个。
这 3 个配置文件各自包含一个位置块。
我尝试过在正则表达式中进行负向前瞻(基本上是尝试对其他应用程序处理的 URL 进行硬编码)但失败了。
总结一下:
/ 和 /community 应该由 /etc/nginx/subsites-enabled/example.org/home 提供(一些 perl 脚本)
/news 应由 /etc/nginx/subsites-enabled/example.org/news (wordpress) 提供
其余所有内容应通过 /etc/nginx/subsites-enabled/example.org/app (cake 应用程序)提供
perl 位工作正常。我遇到的问题是应用程序正在接管新闻(可能是因为它匹配 .*),我尝试了各种选项(我已经尝试了 2 天),但没有一个能解决所有问题(有时静态资产不起作用,等等)。
我的配置是:
/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/subsites-enabled/news
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;
}
}
答案1
您的配置存在一些问题,其中两个相关问题如下:
- 位置块内的路径仍然包含匹配的路径。
- 使用“最后”重写将继续通过查看所有可用位置来查找匹配项(它们会突破当前位置块)。
例如,以 URL example.org/news/test.htm 为例
- 该
location /news
块将匹配它 - 然后使用的路径是
/news/test.htm
- 这不会改变,只是因为它在位置块中 - 将路径添加到 document_root,您将获得:
/var/www/vhosts/news/news/test.htm
- 你的
if (!-e $request_filename)
声明应该捕获这个不存在的文件 - 你重写路径
/index.php
- 由于您正在使用
last
重新开始的流程(突破位置块) /index.php
现已被 捕获location /app block
。
当您转到应用程序位置块时,上述使用 root 指令的问题会变得更加严重。与“news”块不同,在“news”块中,您可以从路径中删除“news”(因为它会重新添加),但您无法对以“webroot”结尾的应用程序路径执行此操作。
解决方案在于alias
指令。这不会更改 document_root,但会更改用于处理请求的文件路径。不幸的是,rewrite
和try_files
往往会对 产生一些意外的影响alias
。
让我们从一个简单的例子开始 - 没有 PHP - 只有 HTML 和你的 Perl 块 - 但有一个与你匹配的文件夹结构(在 Nginx 1.0.12、CentOS 6 上测试):
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 = /
- 仅匹配根路径location ^~ /community
- 将匹配以 /community 开头的每个路径location ~ \.pl
- 将匹配所有包含 .pl 的文件location ^~ /news
- 将匹配以 /news 开头的每个路径location ^~ /app
- 将匹配以 /app 开头的每个路径location /
- 将匹配上面未匹配的所有路径
您应该能够删除^~
- 但它可能会稍微提高性能,因为一旦找到匹配项它就会停止搜索。
虽然重新添加 PHP 块应该是一件简单的事情,但不幸的是,还是有一点困难 - try_files
(并且您的重写)最终没有将所需的路径传递到嵌套的位置块 - 并且alias
当仅在位置块中指定扩展名时使用不起作用。
一种解决方案是使用单独的位置块与别名指令一起执行捕获 - 它不是很优雅,但据我所知,它确实有效(再次在 Nginx 1.0.12、CentOS 6 上测试 - 当然,我没有设置 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;
}
}
上面的配置采用了上面的简单配置,并做了两处更改:
- 添加两个位置块:
location ~* ^/news/(.*\.php)$
- 将匹配所有以 .php 结尾的文件,路径以 /news/ 开头location ~* ^/app/(.*\.php)$
- 将匹配所有以 .php 结尾的文件,路径以 /app/ 开头
- 删除
^~
匹配 - 这是必需的,以便两个添加的位置块可以与路径匹配(否则匹配将停止在/news 或/app 块上)。
需要注意的是,这里位置匹配的顺序非常重要:
- 精确匹配优先(使用
=
) ^~
与第二名匹配- 匹配正则表达式块
- 常规字符串 - 仅当未找到匹配的正则表达式时
匹配的正则表达式将取代直字符串!
需要注意的一点是,当使用别名捕获时,整个 URL 都会被替换 - 而不仅仅是前导文件夹。不幸的是,这意味着$fastcgi_script_name
保留为空 - 因此,我改用$1
上面的方法。
我确信您需要进行一些更改,但基本前提应该是实用的。您应该能够根据需要将块分成多个文件 - 排序不应影响配置。