リクエストURIの書き換えとリダイレクトの設定(rewriteディレクティブ)

広告

rewrite ディレクティブは、正規表現にマッチしたリクエスト URI を書き換えたり、別の URL へリダイレクトを行うためのディレクティブです。 URL の構造を変更したり、古い URL から新しい URL へ転送する場合によく使用されます。ここでは Nginx における rewrite ディレクティブの使い方について解説します。

rewriteディレクティブの書式

rewrite ディレクティブは、正規表現にマッチしたリクエスト URI を書き換えたり、別の URL へリダイレクトを行うためのディレクティブです。 rewrite ディレクティブの書式は次の通りです。

Syntax:   rewrite regex replacement [flag];
Default:  —
Context:  server, location, if

rewrite ディレクティブは serverlocation コンテキスト、および if ディレクティブ内で使用できます。一番目の引数に正規表現、二番目の引数に置換後の文字列またはリダイレクト先の URL を指定します。また置換後の動作を指定するフラグを指定できます。

リクエスト URI を書き換える場合は次のように行います。

server {
  location /images/ {
    rewrite 正規表現 置換後の文字列 [フラグ];
  }
}

URI を書き換える場合のフラグについては次のどちらかを指定できます。

last
URI を書き換えたあと、現在の location 内での処理は中止し、新しい URI で再び location の評価を行います

break
URI を書き換えたあと、 location の再評価は行わず、現在の location 内で処理を継続します

※ URI を書き換える場合、フラグを指定しない場合は、書き換え後の URI をもとに再度 location の評価が行われます(last と同様の動作となります)。

リダイレクトを行う場合は次のように行います。

server {
  location /images/ {
    rewrite 正規表現 リダイレクト先のURL [フラグ];
  }
}

リダイレクトを行う場合のフラグについては次のどちらかを指定できます。

redirect
302リダイレクトを行います

permanent
301リダイレクトを行います

※なお、置換後の文字列が http://https:// で始まる場合は、フラグを指定しなくてもリダイレクトになります。この場合、フラグを省略すると 302 リダイレクトとなります。

それでは、それぞれの具体的な利用方法について順に見ていきます。

rewriteを使ったURIの書き換え

URI の書き換えでは、正規表現の後方参照を使用します。正規表現の中で括弧 () を使ってキャプチャした部分(正規表現とマッチした部分)は、置換後の文字列の中で $1$2 を使って参照することができます。

$1 : 1番目のキャプチャ
$2 : 2番目のキャプチャ
$3 : 3番目のキャプチャ

次の例を見てみましょう。

rewrite ^/old/(.*)$ /new/$1;

リクエスト URI が 正規表現とマッチした場合、正規表現の (.*) の部分にマッチした内容が、置換後の文字列の中で $1 として参照できます。

置換後の文字列は、 "/new/" のあとに $1 となっているので、結果として、URI の /old/ の部分が /new/ に書き換えられます。

書き換え前:
/old/doc/index.html

書き換え後:
/new/doc/index.html

※ 上記の赤字の部分があとから $1 で参照できる部分です。

別の例も見てみましょう。

rewrite ^(\d{4})-(\d{2})-(\d{2}).html$ $2-$3-$1.html;

正規表現を使って 4 桁、 2 桁、 2 桁の数値をそれぞれキャプチャしています。置換後の文字列では、キャプチャした値の順番を入れ替えたものとなっています。

書き換え前:
1992-09-14.html

書き換え後:
09-14-1992.html

クエリ文字列に関する注意点

なお rewrite ディレクティブで指定する正規表現は、リクエスト URI のパス部分だけが対象で、クエリ文字列は対象外となり、そのまま置換後の URI に引き継がれます。

例えば rewrite を次のように設定した場合で考えてみます。

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

リクエスト URI が /old/hello.html?q=123 だった場合でも正規表現にはマッチし、置換後の URI は /new/hello.html?q=123 となります。

置換後の URI でクエリ文字列を削除したい場合は置換後の文字列の最後に ? を付けてください。

rewrite ^/old/(.*)\.html$ /new/$1.html?;

今度はリクエスト URI が /old/hello.html?q=123 だった場合、置換後の URI は /new/hello.html となります。

フラグの設定と注意点

URI を書き換える場合のフラグについては、 last または break を指定します。(フラグを省略した場合は last と同様に書き換え後の URI をもとに再度 location の評価が行われます)。

lastフラグの場合

フラグに last を指定した場合、 URI を書き換えたあと、現在の location 内での処理は中止し、新しい URI で再び location の評価を行います。次の例を見てください。

server {
  location /old/ {
    rewrite ^/old/(.*)$ /new/$1 last;
    return 200 "Ok [location /old/]";
  }

  location /new/ {
    return 200 "Ok [location /new/]";
  }
}

リクエスト URI が "/old/index.html" だった場合、最初の location にマッチし、ブロック内で rewrite を使ったリクエスト URI の書き換えが行われて "/new/index.html" となります。

このときフラグとして last が指定されているので、ブロック内の残りの処理は行われず、新しいリクエスト URI であらためて location とマッチするか評価されます。

新しいリクエスト URI は 2 番目の location にマッチするので、ブロック内にある return 200 "Ok [location /new/]"; が実行されます。

breakフラグの場合

次にフラグに break を指定した場合、 URI を書き換えたあと、 location の再評価は行わず、現在の location 内で処理を継続します。次の例を見てください。

server {
  location /old/ {
    rewrite ^/old/(.*)$ /new/$1 break;
    return 200 "Ok [location /old/]";
  }

  location /new/ {
    return 200 "Ok [location /new/]";
  }
}

リクエスト URI が "/old/index.html" だった場合、最初の location にマッチし、ブロック内で rewrite を使ったリクエスト URI の書き換えが行われて "/new/index.html" となります。

このときフラグとして break が指定されているので、 location の再評価は行わず、ブロック内の残りの処理が実行されるため return 200 "Ok [location /old/]"; が実行されます。

rewriteの繰り返しによるループに関する注意

フラグとして last を指定している場合、 rewrite の繰り返しによるループにならないように注意が必要です。

server {
  location /old/ {
    rewrite ^/old/(.*)$ /old/back/$1 last;
  }
}

rewrite で書き換えられた新しいリクエスト URI であらためて location の評価が行われますが、新しい URI は同じ location に再びマッチするため、rewrite が繰り返し実行されます。

その結果何度も書き換えが行われてしまい最終的にエラーとなります。。フラグに last を指定する場合は、書き換えがループしないように十分注意してください。

rewriteを使ったリダイレクト

rewrite を使ったリダイレクトは、リクエスト URI が正規表現にマッチした場合に、301 リダイレクト(フラグに permanent を指定)または 302 リダイレクト(フラグに redirect を指定)を行います。

次の例を見てみましょう。

rewrite ^/old/(.*)$ https://old.exaple.com/$1 permanent;

リクエスト URI が 正規表現とマッチした場合、別のサイトへ 301 リダイレクトしています。このとき、正規表現の後方参照を使い、 (.*) の部分にマッチした内容を、リダイレクト先の URL の一部として $1 を使って参照できます。

またフラグを redirect に変更すると、 302 リダイレクトとなります。

rewrite ^/old/(.*)$ https://old.example.com/$1 redirect;

なお 301 リダイレクトと 302 リダイレクトの違いは、 301 リダイレクトは恒久的な URL の変更を表し、 302 リダイレクトはメンテナンスなど一時的に別の URL へリダイレクトしたい場合に使用します。

※ 単純なリダイレクトを行う場合は、rewrite よりも return ディレクティブの方が簡潔に記述できます。 return ディレクティブについては「ステータスコードとレスポンスを返す(returnディレクティブ)」を参照されてください。

動作確認

それでは実際に rewrite ディレクティブの動作を確認してみます。 Nginx の設定ファイルである nginx.conf ファイルで http コンテキストに次のように設定しました。(必要な部分のみの抜粋です)。

http {
    server {
        root  html;

        location /old/ {
            rewrite ^/old/(.*)\.html$ /new/$1.html last;
        }
    }
}

rewrite ディレクティブを使用して、リクエスト URI が /old/ で始まり、正規表現にマッチした場合、リクエスト URI の中の /old/ の部分を /new/ に書き換えます。

ブラウザを起動し、次の URL へアクセスします。

http://localhost/old/index.html

/new/index.html に書き換えられたリクエストが処理され、対応するファイルがクライアントへ返されます。

rewriteディレクティブ(1)

このように rewrite ディレクティブを使用することで、正規表現にマッチしたリクエスト URI を書き換えることができます。

-- --

Nginx における rewrite ディレクティブの使い方について解説しました。

( Written by Tatsuo Ikura )

プロフィール画像

著者 / TATSUO IKURA

これから IT 関連の知識を学ばれる方を対象に、色々な言語でのプログラミング方法や関連する技術、開発環境構築などに関する解説サイトを運営しています。