
Недавно мы перешли с Apache на Nginx. Раньше при использовании Apache это было очень просто: просто добавляли что-нибудь в .htaccess и все.
RewriteEngine on
RewriteBase /
# only rewrite if the requested file doesn't exist
RewriteCond %{REQUEST_FILENAME} !-s
# pass the rest of the request into index.php to handle
RewriteRule ^(.*)$ /index.php/$1 [L]
Вышеуказанное отлично послужило для очистки URL и позволило index.php обрабатывать все запросы. Но в Nginx нам нужно было переписать каждый уникальный URL в блоке местоположения. Однако это не «автоматически», как в Apache.
Несколько примеров нашего блока переписывания местоположения
location / {
try_files $uri $uri/ /index.php;
}
location /p {
rewrite ^/p(?:/([a-z_]+))?$ /index.php?p=$1 last;
rewrite ^/p/all_articles/user/(.*)?$ /index.php?p=all_articles&user=$1 last;
try_files $uri $uri/ /index.php;
}
location /about_us {
rewrite ^/about_us /index.php?about_us last;
try_files $uri $uri/ /index.php;
}
location /search {
rewrite ^/search/(.*) /index.php?search=$1;
rewrite ^/search/(.*)/page/(.*)?$ /index.php?search=$1&page=$2 last;
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
Вышеуказанное хорошо работает в чистом URL, но когда нам нужно получить страницы, например
/p/all_articles/user/ABC/page/2
/index.php?p=all_articles&user=ABC&page=2
мы пробовали
rewrite ^/p/all_articles/user/(.*)/pg(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&pg=$2 last;
это работает только когда мы размещаем в отдельном блоке локации
location /page/all_articles {
rewrite ^/p/all_articles/user/(.*)/pg(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&pg=$2 last;
try_files $uri $uri/ /index.php;
}
и когда это было сделано, он не позволил
/p/all_articles/user/ABC
загружать.
кроме того, страницы результатов поиска вообще не работали бы.
Еще одна проблема, с которой мы столкнулись, связана с папкой .htaccess.
Order deny,allow
Deny from all
Options -Indexes
Под apache это предотвратит любой доступ к этой папке и файлам, за исключением php-скрипта. Мы пробовали,
location /(data|img)/ {
deny all;
return 404;
}
Он блокирует доступ к папке, но если указать имя файла, он все равно будет обслуживаться, не запрещая, например, доступ;
/data/backup_01012020.zip в apache .htaccess, только определенным пользователям был разрешен доступ к этому, пока вы вошли в систему. и вне ее, apache запретит любой доступ. Но в nginx, даже несмотря на то, что он выдает 404 при попытке доступа к /data/. Даже если вы не вошли в систему, он сразу же отдаст файл backup_01012020.zip.
Теперь мы не можем понять, что мы можем сделать, что раньше было проще простого с Apache. Наше приложение основано на PHP, а index.php способен обрабатывать все чистые URL-запросы. Было бы здорово, если бы Nginx просто передавал все запросы в index и позволял ему обрабатывать их вместо множества перезаписей и блокировок местоположения. Любая помощь была бы полезна.
решение1
Вас могут заинтересовать вопросы спереписать тег, так как он содержит множество вариаций вашей проблемы.
Ваше правило перезаписи Apache:
RewriteRule ^(.*)$ /index.php/$1 [L]
добавляет весь URI запроса к /index.php
. Вnginx the путьURI (нормализованный) доступен в$uriпеременная. Если вам также нужны аргументы запроса, вы можете использовать$request_uriвместо.
Строгий перевод ваших правил переписывания будет следующим:
location / {
# Size zero static files are served.
# I don't believe that is an issue.
try_files $uri /index.php$request_uri;
}
# If no other .php files are accessible a prefix location of '/index.php/'
# is safer.
location /index.php/ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
# Probably duplicates the contents of fastcgi-php.conf
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# include fastcgi_params;
}
Ваша deny
директива по /(data|img)/
местоположению не работает, поскольку вы используете префиксное соответствие вместо регулярного выражения:
location ~ ^/(data|img)/ {
# Only one is required
deny all;
# return 404;
}
решение2
Решение для переписывания
location /search {
rewrite ^/search/(.*)/page/(.*)?$ /index.php?search=$1&page=$2 last;
rewrite ^/search/(.*) /index.php?search=$1 last;
try_files $uri $uri/ /index.php;
}
location /p/all_articles {
rewrite ^/p/all_articles/user/(.*)/page(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&page=$2 last;
rewrite ^/p/all_articles/user/(.*)?$ /index.php?p=all_articles&user=$1 last;
try_files $uri $uri/ /index.php;
}
Заметьте, я просто поменял местами строки. КредитыРичард Смит
БлагодаряПётр П. Карваш, что касается другого решения, то оно может помочь тому, чей скрипт на 100% совместим, самостоятельно обрабатывать чистые URL.
location / {
# Size zero static files are served.
# I don't believe that is an issue.
try_files $uri /index.php$request_uri;
}
# If no other .php files are accessible a prefix location of '/index.php/'
# is safer.
location /index.php/ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
# Probably duplicates the contents of fastcgi-php.conf
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# include fastcgi_params;
}
вышеприведенное решение является способом пойти, пока ваш скрипт работает с чистым URL 100%. Здесь вам не нужно помещать сотни блоков rewrite location, и nginx добавит весь URI запроса в /index.php, что очень интересно и полезно, возможно, это реальное решение, но в моем случае мой скрипт не был на 100% совместим с этим. Тем не менее, это хорошее, умное решение.
Решение для предотвращения доступа к папкам и файлам
location ~ ^/(data|img)/ {
# Only one is required
deny all;
# return 404;
}
Кредиты дляПётр П. Карвашуказал, что deny all
переопределялось чем-то, после чистого блока сервера это решило проблему. Также убедитесь, что используете либо deny all;
, либо, return 404;
но не вместе.