Назад | Перейти на главную страницу

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

Недавно мы перешли на Nginx с Apache, под 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 / пользователь / 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 / пользователь / 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 просто передавал все запросы на индекс и позволял ему обрабатывать вместо множества перезаписей и блоков местоположения. Любая помощь была бы замечательной.

Возможно, вас заинтересуют вопросы с перезаписать тег, поскольку он содержит множество вариантов вашей проблемы.

Правило перезаписи вашего Apache:

RewriteRule ^(.*)$ /index.php/$1 [L]

добавляет весь URI запроса к /index.php. В nginx в дорожка 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 не работает, так как вы используете совпадение префикса вместо совпадения регулярного выражения:

location ~ ^/(data|img)/ {
   # Only one is required
   deny all;
   # return 404;
}

Решение для перезаписи

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%. Здесь вам не нужно помещать 100 блоков местоположения перезаписи, и nginx добавит весь URI запроса в /index.php, что очень интересно и полезно, вероятно, это реальное решение, но в моем случае мой скрипт не был 100 % совместим с этим. Тем не менее, это хорошее, резкое решение.


Soution для предотвращения доступа к папкам, файлам

location ~ ^/(data|img)/ {
   # Only one is required
   deny all;
   # return 404;
}

Кредиты для Петр П. Карваш отметил, что deny all было что-то переопределено, после чистого блока сервера проблема была решена. Также не забудьте использовать либо deny all; или return 404; но не вместе.