Wie man Nginx umschreibt, um eine saubere URL von Seitenzahlen zu erhalten

Jan 15 2020

Vor kurzem sind wir von Apache zu Nginx gewechselt. Unter Apache war es früher sehr einfach, einfach ein paar Sachen auf .htaccess zu setzen und fertig.

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]

Das oben genannte diente dazu, die URL zu bereinigen und index.php alle Anfragen bearbeiten zu lassen. In Nginx mussten wir jedoch jede eindeutige URL im Standortblock neu schreiben. Dies ist jedoch nicht "automatisch" wie Apache.

Nur wenige Beispiele für unseren Standortblock zum Umschreiben

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;
}

Das obige macht gute Arbeit in sauberen URLs, aber wenn wir zum Beispiel Seiten bekommen müssen

/ p / all_articles / user / ABC / page / 2

/index.php?p=all_articles&user=ABC&page=2

Wir haben es versucht

rewrite ^/p/all_articles/user/(.*)/pg(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&pg=$2 last;

Dies funktioniert nur, wenn wir in einem separaten Standortblock platzieren

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;
}

und wenn es so wäre, würde es nicht zulassen

/ p / all_articles / user / ABC

Laden.

Außerdem würden Suchergebnisseiten überhaupt nicht funktionieren.


Ein weiteres Problem, auf das wir gestoßen sind, ist der Ordner .htaccess

Order deny,allow
Deny from all
Options -Indexes

Unter Apache würde dies jeglichen Zugriff auf diesen Ordner und diese Dateien mit Ausnahme des PHP-Skripts verhindern. Wir haben es versucht,

location /(data|img)/ {
   deny all;
   return 404;
}

Der Zugriff auf Ordner wird zwar blockiert, aber wenn Sie den Dateinamen angeben, wird er weiterhin bereitgestellt, ohne beispielsweise den Zugriff zu verweigern.

/data/backup_01012020.zip unter apache .htaccess durften nur bestimmte Benutzer darauf zugreifen, während sie angemeldet waren. und außerhalb davon wird Apache jeglichen Zugriff verweigern. Unter nginx gibt es jedoch 404, wenn versucht wird, auf / data / zuzugreifen. Selbst wenn Sie nicht angemeldet sind, wird die Datei backup_01012020.zip sofort bereitgestellt.

Jetzt können wir nicht herausfinden, was wir tun können, was früher ein Kinderspiel mit Apache war. Unsere Anwendung basiert auf PHP und index.php kann alle sauberen URL-Anfragen verarbeiten. Es hätte großartig sein können, wenn Nginx einfach alle Anforderungen an den Index übergeben und es verarbeiten lassen würde, anstatt viele Umschreibungen und Standortblöcke. Jede Hilfe wäre großartig.

Antworten

2 PiotrP.Karwasz Jan 15 2020 at 07:07

Die Fragen mit dem Tag zum Umschreiben könnten Sie interessieren , da es viele Variationen Ihres Problems enthält.

Ihre Apache-Umschreiberegel:

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

Hängt den gesamten Anforderungs-URI an an /index.php. In Nginx ist der Pfad des URI (normalisiert) in der Variablen $ uri verfügbar . Wenn Sie auch die Abfrageargumente benötigen, können Sie stattdessen $ request_uri verwenden.

Eine strikte Übersetzung Ihrer Umschreiberegeln wäre daher:

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;
}

Ihre denyAnweisung zum /(data|img)/Speicherort funktioniert nicht, da Sie anstelle einer Regex-Übereinstimmung eine Präfixübereinstimmung verwenden:

location ~ ^/(data|img)/ {
   # Only one is required
   deny all;
   # return 404;
}
HelenSaepp Jan 17 2020 at 00:04

Lösung zum Umschreiben

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;
}

Beachten Sie, dass ich nur die Leitungen vertauscht habe. Dank an Richard Smith


Dank Piotr P. Karwasz für die andere Lösung könnte es jemandem helfen, dessen Skript zu 100% kompatibel ist, saubere URLs selbst zu verarbeiten.

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;
}

Die obige Lösung ist ein Weg, solange Ihr Skript zu 100% mit einer sauberen URL funktioniert. Hier müssen Sie nicht Hunderte von Standortblöcken zum Umschreiben einfügen, und nginx hängt den gesamten Anforderungs-URI an /index.php an, was sehr interessant und hilfreich ist. Wahrscheinlich ist dies die eigentliche Lösung, aber in meinem Fall war mein Skript nicht 100 % kompatibel damit. Trotzdem ist dies eine gute Hackmesserlösung.


Soution zur Verhinderung des Zugriffs auf Ordner und Dateien

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

Dank an Piotr P. Karwasz , der deny alldurch etwas überschrieben wurde, löste das Problem nach einem sauberen Serverblock . Stellen Sie außerdem sicher, dass Sie entweder deny all;oder return 404;aber nicht zusammen verwenden.