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

ページ番号のクリーンな 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 では、location ブロック内のすべての一意の 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/すべての記事/ユーザー/ABC/ページ/2

/index.php?p=すべての記事&ユーザー=ABC&ページ=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/すべての記事/ユーザー/ABC

ロードします。

また、検索結果ページはまったく機能しなくなります。


私たちが遭遇したもう一つの問題は、フォルダ.htaccessに関するものです。

Order deny,allow
Deny from all
Options -Indexes

Apacheでは、PHPスクリプト以外のフォルダとファイルへのアクセスを禁止します。私たちは試しました。

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

フォルダーへのアクセスはブロックされますが、ファイル名を指定すると、アクセスを拒否することなく引き続き機能します。たとえば、

apache .htaccess の下の /data/backup_01012020.zip では、ログインしている特定のユーザーのみがアクセスを許可されています。それ以外の場合、apache はすべてのアクセスを拒否します。ただし、nginx では、/data/ にアクセスしようとすると 404 が返されます。ログインしていない場合でも、backup_01012020.zip ファイルがすぐに提供されます。

今では、Apache では簡単だったことが、私たちには何ができるのかわかりません。私たちのアプリケーションは PHP ベースで、index.php はすべてのクリーンな URL リクエストを処理できます。Nginx がすべてのリクエストをインデックスに渡して、大量の書き換えやロケーション ブロックの代わりに処理させてくれたら、最高だったでしょう。どんな助けでも大歓迎です。

答え1

あなたは以下の質問に興味があるかもしれません書き換えタグ問題のさまざまなバリエーションが含まれているためです。

Apache 書き換えルール:

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

リクエストURI全体を に追加します/index.phpnginxパスURI(正規化)は、$uri変数。クエリ引数も必要な場合は、$リクエスト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;
}

注意してください、私がしたのはセリフの交換だけです。リチャード・スミス


感謝ピオトル・P・カルワス他の解決策としては、スクリプトが 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;
}

上記の解決策は、スクリプトが 100% クリーンな URL で動作する限り、実行できる方法です。ここでは、何百もの書き換え場所ブロックを配置する必要はなく、nginx はリクエスト URI 全体を /index.php に追加します。これは非常に興味深く、役立ちます。おそらくこれが実際の解決策ですが、私の場合、スクリプトはこれと 100% 互換性がありませんでした。それでも、これは優れた賢い解決策です。


フォルダ、ファイルへのアクセスを防止するソリューション

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

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

関連情報