NGINXリダイレクト完全ガイド:301/302/307/308の意味と実践設定、SEO対策とトラブルシューティングを徹底解説

はじめに — 「nginx リダイレクト」とは何か

Webサーバー nginx における「リダイレクト」は、クライアント(ブラウザやボット)からのあるリクエストに対して、別の URL(場所)へ HTTP レスポンスで指示(Location ヘッダ)を返すことを指します。SEO や HTTP/HTTPS 移行、ドメイン正規化、パスの変更など運用上必須の処理であり、nginx では複数の方法(ディレクティブ)で実現できます。本稿では、リダイレクトの基本概念から nginx の具体設定、よく使うパターン、トラブルシューティング、注意点までを詳しく解説します。

HTTP リダイレクトの基本(ステータスコード)

  • 301 Moved Permanently — 恒久的な移動。検索エンジンは新しい URL をインデックス化する傾向がある。ブラウザや中間キャッシュにより長期的にキャッシュされる可能性あり。
  • 302 Found(旧称)/ 307 Temporary Redirect — 一時的な移動。307 はメソッド(POST など)を保存する点で 302 と異なる。
  • 308 Permanent Redirect — 301 の「メソッド保存」版。PUT/POST などメソッドを保持したまま恒久移動する。

選択するステータスコードは、クライアントや検索エンジンの挙動に影響するため慎重に決めます。一般的には URL の恒久変更なら 301、一時的な移転であれば 302/307 を使います。

nginx でのリダイレクト実現方法

nginx では主に以下の方法があります。

  • return:単純で効率的。即座にレスポンスを返す。例:return 301 https://$host$request_uri;
  • rewrite:正規表現による URL 書き換えと(必要に応じた)リダイレクト。より複雑なルールに向く。例:rewrite ^/old/(.*)$ /new/$1 permanent;
  • try_files と組み合わせた内部リダイレクト/外部リダイレクト制御(存在しないなら別の場所へリダイレクト)
  • proxy_redirect:バックエンドから返される Location ヘッダを調整するためのディレクティブ(リダイレクト要請をプロキシが調整するケース)

一般に、単純な HTTP→HTTPS やドメイン正規化などは return を使うのが簡潔で高速です。複雑なパターンマッチやグルーピングが必要なときに rewrite を使います。

よく使う設定例(実践)

1) HTTP → HTTPS の強制(全てのリクエスト)

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

$request_uri はクエリ文字列を含むリクエストパス(例:/path?x=1)を返します。$uri は内部正規化されたパス(エンコードや index などにより変わり得る)なので、原則リダイレクトでは $request_uri を使うことが多いです。

2) www → 非 www(またはその逆)の正規化

server {
    listen 80;
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}

$scheme を使うとオリジナルのスキーム(http/https)を残せますが、HTTPS にまとめたい場合は上の HTTP→HTTPS ルールと併用します。

3) パス単位でのリダイレクト(キャプチャ利用)

server {
    server_name example.com;
    location /old-path/ {
        rewrite ^/old-path/(.*)$ /new-path/$1 permanent;
    }
}

rewrite のキャプチャ(括弧)を用いて、部分一致を新しいパスに引き渡す例です。

4) クエリ文字列を保持してリダイレクト

return 301 https://example.com/new-path?$args;

$args はクエリ文字列(キー=値&...)を表します。return に直接クエリを付ける場合、手動で ?$args をつけないとクエリが失われることがあります。$request_uri を使えば ? を含めた元のクエリをそのまま保持できます。

5) トレーリングスラッシュの追加/削除

  • スラッシュを付ける(例:/foo → /foo/)
  • if ($request_uri ~ ^(.+[^/])$) {
        return 301 $1/;
    }
  • スラッシュを外す(例:/index.html → /)
  • rewrite ^/index\.html$ / permanent;

ただし nginx の if は注意して使う(公式ドキュメントの「if is evil」節を参照)。可能なら location や try_files と組み合わせて実装することが望ましいです。

rewrite と return の違い(内部挙動と推奨)

  • return:指定したステータスと Location を即時返す。シンプルで高効率。
  • rewrite:URI 書き換えを行い、必要に応じて内部リダイレクト(last)や外部リダイレクト(redirect/permanent)を行う。後続の location 検査をトリガーすることがある。

シンプルなリダイレクトは return を推奨します。複雑な正規表現マッチや内部ルーティングが必要な場合に rewrite を用います。

よくある落とし穴と対処法

  • リダイレクトループ — 同一条件でリダイレクトを返し続ける。$scheme, $host, 条件ロジックをチェックして発生源を特定する。
  • クエリが消える — return で ? を付け忘れるか、rewrite の書き方で引き継がれない場合がある。$request_uri や $args を使って明示的に扱う。
  • プロキシ経由の Location 書き換え — バックエンドが絶対 URL を返していると、そのままクライアントに返るので proxy_redirect を使用するかバックエンド側を調整する。
  • ステータスコードの誤選択 — 恒久移転なのに 302 を返すと検索エンジンが旧 URL を保持することがある。慎重に選ぶ。
  • 正規表現の優先順位・location の順序 — nginx の location マッチングルール(正確な prefix → longest prefix → regex)が複雑なので、意図しないルール適用を避けるため公式仕様を理解する。

テストとデバッグ方法

  • nginx 設定検査:nginx -t で構文チェック。その後 nginx -s reload で反映。
  • curl を使った確認:curl -I -L -v https://example.com/path でステータスと Location ヘッダ、リダイレクト経路を確認。
  • ブラウザのキャッシュに注意:301 はブラウザやプロキシにキャッシュされるため、テスト時はキャッシュをクリアするか別ブラウザで試す。
  • アクセスログとエラーログを活用:どの location がマッチしたか、ループの痕跡があるかをログで確認。

パフォーマンスとセキュリティ上の考慮

  • return の方が内部処理が少なく高速。大量アクセスが想定される場合は簡潔な return を優先。
  • HTTPS へリダイレクトする場合、HSTS(Strict-Transport-Security)ヘッダを検討。ただし HSTS は一度有効化すると解除が難しいため、事前に影響範囲を検討する。
  • 外部入力をそのままリダイレクト先に使うとオープンリダイレクト脆弱性になる可能性がある。信頼できない値を Location に直接埋め込まない。

まとめ

nginx のリダイレクトは、単純な URL 移行から複雑なパス置換まで幅広く使われる重要な機能です。シンプルなケースでは return を使い、正規表現や内部書き換えが必要なケースで rewrite を使うのが基本的な考え方です。301/302/307/308 の意味を理解して適切なステータスコードを選び、クエリ文字列や HTTP メソッドの保持、ループの回避などの運用面にも注意してください。

参考文献