web-dev-qa-db-ja.com

NGINXは.html拡張子を削除します

だから、私は自分のページから.html拡張子を削除する答えを見つけました、それはこのコードでうまくいきます:

server {
    listen 80;
    server_name _;
    root /var/www/html/;
    index index.html;

    if (!-f "${request_filename}index.html") {
        rewrite ^/(.*)/$ /$1 permanent;
    }

    if ($request_uri ~* "/index.html") {
        rewrite (?i)^(.*)index\.html$ $1 permanent;
    }   

    if ($request_uri ~* ".html") {
        rewrite (?i)^(.*)/(.*)\.html $1/$2 permanent;
    }

    location / {
        try_files $uri.html $uri $uri/ /index.html;
    }
}

しかし、mypage.comを開くと、mypage.com/indexにリダイレクトされます
これは、index.htmlをインデックスとして宣言することで修正されませんか?どんな助けでもありがたいです。

16
SkyGuardian42

NGINXで「.html」を削除するための「聖杯」ソリューション:

更新された回答:この質問は私の好奇心を刺激し、私はNginxの.htmlリダイレクトの「聖杯」解決策をさらに詳細に検索しました。私が自分で考え出さなかったので、ここに私が見つけた答えへのリンクがあります: https://stackoverflow.com/a/32966347/4175718

ただし、例を示し、その仕組みを説明します。これがコードです:

location / {
    if ($request_uri ~ ^/(.*)\.html$) {
        return 302 /$1;
    }
    try_files $uri $uri.html $uri/ =404;
}

ここで起こっているのは、ifディレクティブのかなり独創的な使用法です。 Nginxは受信リクエストの$request_uri部分で正規表現を実行します。正規表現は、URIに.html拡張子があるかどうかを確認し、URIの拡張子のない部分を組み込み変数$1に格納します。

docs から、$1がどこから来たかを理解するのに少し時間がかかったので:

正規表現には、後で$ 1 .. $ 9変数で再利用できるようにするキャプチャを含めることができます。

正規表現は、不要な.htmlリクエストの存在を確認し、URIを効果的にサニタイズして拡張機能が含まれないようにします。次に、単純なreturnステートメントを使用して、リクエストがサニタイズされたURIにリダイレクトされます。サニタイズされたURIは、現在$1に格納されています。

原作者 cnst が説明しているように、これについての最も良い部分は、

$ request_uriはリクエストごとに常に一定であり、他の書き換えの影響を受けないため、実際には無限ループを形成しません。

any.htmlリクエスト(/index.htmlへの非表示の内部リダイレクトを含む)を操作する書き換えとは異なり、このソリューションは、ユーザー。

「try_files」は何をしますか?

それでも、try_filesディレクティブは必要です。そうしないと、Nginxは新しくサニタイズされた拡張機能のないURIをどうするかがわからなくなります。上記のtry_filesディレクティブは、最初に新しいURLを単独で試し、次に ".html"拡張子を付けて試し、次にディレクトリ名として試します。

Nginxのドキュメントでは、デフォルトのtry_filesディレクティブがどのように機能するかについても説明しています。デフォルトのtry_filesディレクティブの順序は上記の例とは異なるため、以下の説明は完全には一致していません。

Nginxは最初に.htmlをURIの末尾に追加し、それを提供しようとします。適切な.htmlファイルが見つかると、そのファイルが返され、拡張子のないURIが維持されます。適切な.htmlファイルが見つからない場合は、拡張子なしのURIを試し、次にそのURIをディレクトリとして試し、最後に404エラーを返します。

更新:正規表現は何をしますか?

上記の答えは正規表現の使用に触れていますが、ここではまだ興味がある人のためのより具体的な説明があります。次の正規表現(regex)が使用されます。

^/(.*)\.html$

これは次のように分類されます。

^:行の始まりを示します。

/:文字「/」と文字どおり一致します。 Nginxではスラッシュをエスケープする必要はありません。

(.*):キャプチャグループ:任意の文字に無制限に一致

\.:文字「。」に一致文字通り。これはバックスラッシュでエスケープする必要があります。

html:文字列「html」に文字通り一致します。

$:行の終わりを示します。

キャプチャグループ(.*)は、URLの ".html"以外の部分を含むものです。これは後で変数$1で参照できます。次にNginxはリクエスト(return 302 /$1;)を再試行するように構成され、try_filesディレクティブは ".html"拡張子を内部的に追加してファイルを見つけられるようにします。

更新:クエリ文字列の保持

.htmlページに渡されたクエリ文字列と引数を保持するには、returnステートメントを次のように変更できます。

return 302 /$1?$args;

これにより、/index.html?testなどのリクエストが、/index?testだけでなく/indexにリダイレクトされるようになります。


これは、 `if`ディレクティブの安全な使用法と見なされることに注意してください。

Nginxページから、Is Is Evilの場合:

ロケーションコンテキストの場合、内部で実行できる唯一の100%安全なものは次のとおりです。

戻る...;

書き換え...最後;


また、「302」リダイレクトを「301」に交換することもできます。

301リダイレクトは永続的であり、Webブラウザーと検索エンジンによってキャッシュされます。検索エンジンによって既にインデックスが作成されているページから.html拡張機能を完全に削除することが目的である場合は、301リダイレクトを使用することをお勧めします。ただし、ライブサイトでテストする場合は、302から始めて、構成が正しく機能していると確信できる場合にのみ301に移動することをお勧めします。

46
Arnon

これも私によく起こりますが、作業時の設定により、ロケーションブロックはせいぜい不明瞭であり、/&.phpブロックはロックされています。つまり、ほとんどの解決策は私にはうまくいきません。

だからここに私が上記の受け入れられた答えから簡略化したものがあります。

rewrite ^/(.*)\.html /$1/ permanent;

基盤となるフレームワークがページを生成しているCMSに最適

1
user1270949