Existem algumas coisas erradas na sua configuração, sendo as duas mais relevantes:
- Os caminhos dentro de um bloco de localização ainda incluem o caminho correspondente.
- Reescreve com "last" e analisa todos os locais disponíveis para uma partida (eles quebram o bloco de localização atual).
Por exemplo, use o URL example.org/news/test.htm
- O bloco
location /news
corresponderá a ele - O caminho usado é, então,
/news/test.htm
- isso não muda, apenas porque está no bloco de localização - Adicionando o caminho para o document_root, você obtém:
/var/www/vhosts/news/news/test.htm
- Sua declaração
if (!-e $request_filename)
deve capturar este arquivo não existente - Você reescreve o caminho para
/index.php
- Como você está usando
last
, os processos começam de novo (saindo do bloco de localização) -
/index.php
agora é capturado pelolocation /app block
.
O problema mencionado acima, com a diretiva raiz, é combinado quando você vai para o bloco de localização do seu aplicativo. Ao contrário do bloco "news", onde você poderia simplesmente remover "notícias" do caminho (já que ele será adicionado novamente), você não pode fazer isso para o caminho do aplicativo, que termina em "webroot".
A solução está na diretiva alias
. Isso não altera o document_root, mas altera o caminho do arquivo usado para atender à solicitação. Infelizmente, rewrite
e try_files
tendem a se comportar um pouco inesperadamente com alias
.
Vamos começar com um exemplo simples - sem PHP - apenas HTML e seu bloco Perl - mas com uma estrutura de pastas correspondente à sua (testada no 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 = /
- corresponderá apenas ao caminho da raiz -
location ^~ /community
- corresponderá a todos os caminhos que começam com / community -
location ~ \.pl
- corresponderá a todos os arquivos que contiverem .pl -
location ^~ /news
- corresponderá a todos os caminhos iniciados por / news -
location ^~ /app
- corresponderá a todos os caminhos que começam com / app -
location /
- corresponderá a todos os caminhos não correspondidos acima
Você deve conseguir remover o ^~
, mas ele pode oferecer uma pequena melhora de desempenho, pois interrompe a pesquisa depois que uma correspondência é encontrada.
Embora deva ser simples adicionar os blocos do PHP de volta, infelizmente há uma pequena dificuldade - try_files
(e sua reescrita) não acaba passando o caminho desejado para o bloco de localização aninhado - e usar alias
quando somente a extensão é especificada no bloco de localização não funciona.
Uma solução é usar blocos de localização separados que executam uma captura junto com a diretiva de alias - não é muito elegante, mas pelo que eu sei, funciona (novamente, testado no Nginx 1.0.12, CentOS 6 - Claro, eu não configurei o CakePHP, Wordpress e Perl - eu usei apenas alguns arquivos PHP e HTML em cada pasta)
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;
}
}
A configuração acima, pega a simples acima, e faz duas alterações:
- Adicione dois blocos de localização:
-
location ~* ^/news/(.*\.php)$
- corresponderá a todos os arquivos terminados em .php, com caminhos começando com / news / -
location ~* ^/app/(.*\.php)$
- corresponderá a todos os arquivos terminados em .php, com caminhos começando com / app /
-
- Remova a
^~
matching - isso é necessário para que os dois blocos de localização adicionados possam corresponder aos caminhos (caso contrário, a correspondência seria interrompida nos blocos / news ou / app).
Deve notar-se que a encomenda da correspondência de localização é muito importante aqui:
- Correspondências exatas primeiro (usando
=
) - Corresponde a
^~
segundo - Correspondência de blocos de expressão regular
- Strings convencionais - somente se nenhuma regex correspondente for encontrada
Um regex correspondente substituirá uma string reta!
Um ponto importante de menção é que quando as capturas são usadas com alias, a URL inteira é substituída - não apenas a pasta principal. Infelizmente, isso significa que $fastcgi_script_name
está vazio - por isso, usei $1
acima.
Tenho certeza de que você precisará fazer algumas alterações, mas a premissa básica deve ser funcional. Você deve ser capaz de separar os blocos em vários arquivos, conforme necessário - a ordenação não deve afetar a configuração.