Как переписать Nginx, чтобы получить чистый URL-адрес номеров страниц

Как переписать Nginx, чтобы получить чистый URL-адрес номеров страниц

Недавно мы перешли с 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;но не вместе.

Связанный контент