ページ番号のクリーンURLを取得するためにNginxを書き換える方法

Jan 15 2020

最近、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の下では、/ data /にアクセスしようとすると404が返されます。ログに記録されていない場合でも、すぐにbackup_01012020.zipファイルが提供されます。

今では、Apacheを使ったケーキであった私たちに何ができるのか理解できません。私たちのアプリケーションはPHPに基づいており、index.phpはすべてのクリーンURLリクエストを処理できます。Nginxがすべてのリクエストをインデックスに渡して、大量の書き換えやロケーションブロックの代わりに処理させることができれば、すばらしいことでした。どんな助けでも素晴らしいでしょう。

回答

2 PiotrP.Karwasz Jan 15 2020 at 07:07

問題のバリエーションが多数含まれているため、rewriteタグを使用した質問に興味があるかもしれません。

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 ~ ^/(data|img)/ {
   # Only one is required
   deny all;
   # return 404;
}
HelenSaepp Jan 17 2020 at 00:04

書き換えの解決策

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

注意してください、私がしたのはラインを交換することだけでした。リチャード・スミスのクレジット


Piotr P. Karwaszのおかげで、他の解決策として、スクリプトが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%機能する限り実行する方法です。ここでは、何百もの書き換えロケーションブロックを配置する必要はなく、nginxはリクエストURI全体を/index.phpに追加します。これは非常に興味深く、役立つでしょう。おそらくこれが実際の解決策ですが、私の場合、スクリプトは100ではありませんでした。 %これと互換性があります。それでも、これは優れたクリーバーソリューションです。


フォルダ、ファイルへのアクセスを防ぐための解決策

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

クレジットピョートルP. Karwaszは、指摘deny all、それは問題を解決しましたクリーンなサーバブロック時に、何かによって上書きされていました。また、どちらかを使用するかdeny all;return 404;一緒に使用しないでください。