web-dev-qa-db-ja.com

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

最近、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がすべてのリクエストをインデックスに渡して、大量の書き換えの代わりに処理させることができれば素晴らしいと思います。と場所のブロック。どんな助けも素晴らしいでしょう。

1
HelenSaepp

書き換えの解決策

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

クレジット Piotr P. Karwasz 指摘されたように、deny allは何かによって上書きされていましたが、クリーンなサーバーブロックで問題は解決しました。また、必ずdeny all;またはreturn 404;のいずれかを使用してください。ただし、一緒に使用しないでください。

0
HelenSaepp

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

Apacheの書き換えルール:

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

リクエストURI全体を_/index.php_に追加します。 nginxでは、URI(正規化)の path$ 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;
}
_

正規表現の一致の代わりにプレフィックスの一致を使用しているため、/(data|img)/の場所のdenyディレクティブは機能しません。

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