<-
Apache > HTTP サーバ > ドキュメンテーション > バージョン 2.5 > Rewrite

mod_rewrite によるリダイレクトとリマッピング

翻訳済み言語:  de  |  en  |  es  |  fr  |  ja  |  ko  |  tr  |  zh-cn 

このドキュメントは mod_rewrite リファレンスドキュメントを補足するものです。 mod_rewrite を使用してリクエストをリダイレクトおよびリマッピング する方法を説明します。mod_rewrite の一般的な使用例を多数含んでおり、 それぞれの動作についての詳細な説明も含まれています。

これらの例の多くは、特定のサーバ設定ではそのまま 動作しないことに注意してください。そのため、単にコピー&ペーストするのではなく、 内容を理解することが重要です。

参照

top

旧 URL から新 URL へ (内部)

説明:

最近ページ foo.htmlbar.html に リネームし、後方互換性のために旧 URL も提供したいとします。 ただし、旧 URL のユーザにはページがリネームされたことを 気づかせたくありません - つまり、ブラウザのアドレスが 変更されないようにします。

解決方法:

以下のルールで旧 URL を内部的に新しいものに書き換えます:

RewriteEngine  on
RewriteRule    "^/foo\.html$"  "/bar.html" [PT]
top

旧 URL から新 URL への書き換え (外部)

説明:

再び、最近ページ foo.htmlbar.html にリネームし、後方互換性のために旧 URL を提供したいとします。 しかし今回は、旧 URL のユーザに新しい URL を知らせたい、 つまりブラウザの Location フィールドも変更されるようにしたいとします。

解決方法:

新しい URL への HTTP リダイレクトを強制し、ブラウザと ユーザの表示を変更します:

RewriteEngine  on
RewriteRule    "^/foo\.html$"  "bar.html"  [R]
議論

この例では、上記の内部の例と 対比して、単純に Redirect ディレクティブを使用できます。 mod_rewrite は、前の例でクライアントからリダイレクトを 隠すために使用されました:

Redirect "/foo.html" "/bar.html"
top

リソースの別サーバへの移動

説明:

リソースが別のサーバに移動した場合、人々がブックマークを 更新する間、旧サーバでも URL がしばらく機能し続けるように したいとします。

解決方法:

mod_rewrite を使用してこれらの URL を新しいサーバに リダイレクトできますが、Redirect や RedirectMatch ディレクティブの 使用も検討してください。

#With mod_rewrite
RewriteEngine on
RewriteRule   "^/docs/(.+)"  "http://new.example.com/docs/$1"  [R,L]
#With RedirectMatch
RedirectMatch "^/docs/(.*)" "http://new.example.com/docs/$1"
#With Redirect
Redirect "/docs/" "http://new.example.com/docs/"
top

静的から動的へ

説明:

静的ページ foo.html を動的バリアント foo.cgi にシームレスに、つまりブラウザ/ユーザに 気づかれずに変換するにはどうすればよいでしょうか。

解決方法:

URL を CGI スクリプトに書き換え、ハンドラを cgi-script に強制して、CGI プログラムとして 実行されるようにします。 これにより、/~quux/foo.html へのリクエストは 内部的に /~quux/foo.cgi の呼び出しに つながります。

RewriteEngine  on
RewriteBase    "/~quux/"
RewriteRule    "^foo\.html$"  "foo.cgi"  [H=cgi-script]
top

ファイル拡張子変更の後方互換性

説明:

document.YYYY から document.XXXX への 移行後、例えば .html ファイル群を .php に 変換した後に、URL の後方互換性 (仮想的にまだ存在する状態) を どのように保つことができるでしょうか?

解決方法:

URL は旧拡張子から新拡張子に書き換えられますが、新拡張子の ターゲットファイルが存在し、かつ旧拡張子の元のファイルが 存在しない場合のみです。それ以外の場合、URL はそのまま 変更されません。

#   backward compatibility ruleset for
#   rewriting document.html to document.php
#   when and only when document.php exists
<Directory "/var/www/htdocs">
    RewriteEngine on
    RewriteBase   "/var/www/htdocs"

    RewriteCond   "$1.php"           -f
    RewriteCond   "$1.html"          !-f
    RewriteRule   "^(.*).html$"      "$1.php"
</Directory>
議論

この例では、mod_rewrite のあまり知られていない 機能を利用しています。ルールセットの実行順序を活用しています。 具体的には、mod_rewrite は RewriteCond ディレクティブを 評価する前に RewriteRule の左辺を評価します。 そのため、RewriteCond ディレクティブが評価される時点で $1 はすでに定義されています。これにより、同じベースファイル名を使用して 元のファイル (document.html) とターゲットファイル (document.php) の存在を確認できます。

このルールセットはディレクトリ単位のコンテキスト (<Directory> ブロックまたは .htaccess ファイル内) で 使用するよう設計されているため、-f チェックは 正しいディレクトリパスを参照します。作業しているディレクトリベースを 指定するために RewriteBase ディレクティブを設定する必要があるかもしれません。

top

正規ホスト名

説明:
このルールの目的は、同じサイトに到達するために使用される 可能性のある他のホスト名よりも、特定のホスト名の使用を強制 することです。例えば、example.com の代わりに www.example.com の使用を強制したい場合は、 以下のレシピのバリアントを使用できます。
解決方法:

最善の方法は mod_rewrite をまったく使わず、 非正規のホスト名用のバーチャルホストに配置した Redirect ディレクティブを使用する ことです。

<VirtualHost *:80>
  ServerName undesired.example.com
  ServerAlias example.com notthis.example.com

  Redirect "/" "http://www.example.com/"
</VirtualHost>

<VirtualHost *:80>
  ServerName www.example.com
</VirtualHost>

あるいは、<If> ディレクティブを使用して実現することもできます: (2.4 以降)

<If "%{HTTP_HOST} != 'www.example.com'">
    Redirect "/" "http://www.example.com/"
</If>

あるいは、例えばサイトの一部を HTTPS にリダイレクトするには、 以下のようにします:

<If "%{SERVER_PROTOCOL} != 'HTTPS'">
    Redirect "/admin/" "https://www.example.com/admin/"
</If>

何らかの理由でまだ mod_rewrite を使用したい場合 - 例えば、より大きな RewriteRule のセットと組み合わせる必要がある場合 - 以下のレシピのいずれかを使用できます。

ポート 80 以外で実行されているサイトの場合:

RewriteCond "%{HTTP_HOST}"   "!^www\.example\.com" [NC]
RewriteCond "%{HTTP_HOST}"   "!^$"
RewriteCond "%{SERVER_PORT}" "!^80$"
RewriteRule "^/?(.*)"        "http://www.example.com:%{SERVER_PORT}/$1" [L,R,NE]

ポート 80 で実行されているサイトの場合:

RewriteCond "%{HTTP_HOST}"   "!^www\.example\.com"       [NC]
RewriteCond "%{HTTP_HOST}"   "!^$"
RewriteRule "^/?(.*)"        "http://www.example.com/$1" [L,R,NE]

すべてのドメイン名に対してこれを汎用的に行いたい場合 - つまり、example.com のすべての可能な値に対して example.comwww.example.com にリダイレクトしたい場合 - 以下のレシピを使用できます:

RewriteCond "%{HTTP_HOST}" "!^www\."                    [NC]
RewriteCond "%{HTTP_HOST}" "!^$"
RewriteRule "^/?(.*)"      "http://www.%{HTTP_HOST}/$1" [L,R,NE]

これらのルールセットは、メインサーバ設定ファイルまたはサーバの DocumentRoot に配置した .htaccess ファイルのいずれでも動作します。

top

複数のディレクトリでのページ検索

説明:

特定のリソースが複数の場所に存在する可能性があり、 リクエスト時にそれらの場所でリソースを検索したいとします。 おそらく最近ディレクトリ構造を再編成し、コンテンツを 複数の場所に分割したためです。

解決方法:

以下のルールセットは 2 つのディレクトリでリソースを検索し、 どちらにも見つからない場合は、リクエストされた場所からそのまま 提供しようとします。

RewriteEngine on

#   first try to find it in dir1/...
#   ...and if found stop and be happy:
RewriteCond         "%{DOCUMENT_ROOT}/dir1/%{REQUEST_URI}"  -f
RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/dir1/$1"  [L]

#   second try to find it in dir2/...
#   ...and if found stop and be happy:
RewriteCond         "%{DOCUMENT_ROOT}/dir2/%{REQUEST_URI}"  -f
RewriteRule "^(.+)" "%{DOCUMENT_ROOT}/dir2/$1"  [L]

#   else go on for other Alias or ScriptAlias directives,
#   etc.
RewriteRule "^"     "-"                                          [PT]
top

地理的に分散されたサーバへのリダイレクト

説明:

ウェブサイトの多数のミラーがあり、アクセス元の国に最も近い ミラーにリダイレクトしたいとします。

解決方法:

リクエスト元のクライアントのホスト名を参照して、どの国から アクセスしているかを判定します。IP アドレスの検索ができない場合は、 デフォルトサーバにフォールバックします。

使用したいサーバのリストを構築するために RewriteMap ディレクティブを 使用します。

HostnameLookups on
RewriteEngine on
RewriteMap    multiplex         "txt:/path/to/map.mirrors"
RewriteCond  "%{REMOTE_HOST}"   "([a-z]+)$"                [NC]
RewriteRule  "^/(.*)$"          "${multiplex:%1|http://www.example.com/}$1"  [R,L]

## map.mirrors -- マルチプレクシングマップ

de http://www.example.de/
uk http://www.example.uk/
com http://www.example.com/
##EOF##

議論
このルールセットは HostNameLookupson に設定されていることに依存しており、 パフォーマンスに大きな影響を与える可能性があります。

RewriteCond ディレクティブは、リクエスト元のクライアントのホスト名の最後の 部分 (国コード) をキャプチャし、後続の RewriteRule はその値を 使用してマップファイルから適切なミラーホストを検索します。

top

正規 URL

説明:

一部のウェブサーバでは、リソースに対して複数の URL が存在します。 通常、正規の URL (実際に使用および配布される URL) と、単なる ショートカット、内部用の URL 等があります。ユーザがリクエストで どの URL を提供したかに関係なく、最終的にブラウザのアドレスバーに 正規の URL が表示されるようにしたいとします。

解決方法:

すべての非正規 URL に対して外部 HTTP リダイレクトを行い、 ブラウザの表示を修正し、以降のすべてのリクエストに反映させます。 以下のルールセット例では、/puppies/canines を正規の /dogs に 置き換えます。

RewriteRule   "^/(puppies|canines)/(.*)"    "/dogs/$2"  [R]
議論:
これは実際には Redirect または RedirectMatch ディレクティブで 実現すべきです:
RedirectMatch "^/(puppies|canines)/(.*)" "/dogs/$2"
top

DocumentRoot の移動

説明:

通常、ウェブサーバの DocumentRoot は URL "/" に直接対応します。 しかし、このデータが最優先ではない場合も多くあります。例えば、 訪問者がサイトに最初にアクセスしたときに特定のサブディレクトリ /about/ に移動させたい場合があります。これは以下の ルールセットで実現できます:

解決方法:

URL //about/ にリダイレクトします:

RewriteEngine on
RewriteRule   "^/$"  "/about/"  [R]

これは RedirectMatch ディレクティブでも処理できることに注意してください:

RedirectMatch "^/$" "http://example.com/about/"

この例はルート URL のみを書き換えることに注意してください。つまり、 http://example.com/ へのリクエストは書き換えますが、 http://example.com/page.html へのリクエストは書き換えません。 実際にドキュメントルートを変更した場合 - つまり、コンテンツの すべてが実際にそのサブディレクトリにある場合 - URL を 書き換えるよりも、単に DocumentRoot ディレクティブを変更するか、すべてのコンテンツを 1 つ上のディレクトリに 移動する方がはるかに望ましいです。

top

フォールバックリソース

説明:
特定のディレクトリに来るすべてのリクエストを単一のリソース (例えば特定のファイル、index.php など) で処理したいが、 画像や CSS ファイルなどの既存のリソースへのリクエストは そのまま処理したいとします。
解決方法:

バージョン 2.2.16 以降では、このために FallbackResource ディレクティブを 使用してください:

<Directory "/var/www/my_blog">
  FallbackResource index.php
</Directory>

ただし、以前のバージョンの Apache や、これよりも複雑なニーズがある 場合は、以下の書き換えセットのバリエーションを使用して同じことを 実現できます:

<Directory "/var/www/my_blog">
  RewriteBase "/my_blog"

  RewriteCond "/var/www/my_blog/%{REQUEST_FILENAME}" !-f
  RewriteCond "/var/www/my_blog/%{REQUEST_FILENAME}" !-d
  RewriteRule "^"                                    "index.php" [PT]
</Directory>

一方、リクエストされた URI をクエリ文字列引数として index.php に 渡したい場合は、その RewriteRule を以下に置き換えることができます:

RewriteRule "(.*)" "index.php?$1" [PT,QSA]

これらのルールセットは .htaccess ファイルでも <Directory> ブロックでも使用できることに注意してください。

top

クエリ文字列の書き換え

説明:
クエリ文字列から特定の値をキャプチャし、それを置換するか URL の別のコンポーネントに組み込みたいとします。
解決方法:

このセクションの多くの解決方法は同じ条件を使用し、マッチした値を %2 バックリファレンスに残します。%1 はクエリ文字列の先頭 (対象キーまで)、 %3 は残りの部分です。この条件は、柔軟性のため、また置換で二重の '&&' を避けるためにやや複雑です。

  • この方法はマッチするキーと値を削除します:
    # Remove mykey=???
    RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
    RewriteRule "(.*)"            "$1?%1%3"
  • この方法はキャプチャした値を URL 置換で使用し、'?' を追加して 元のクエリの残りを破棄します:
    # Copy from query string to PATH_INFO
    RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
    RewriteRule "(.*)"            "$1/products/%2/?" [PT]
  • この方法は後続の条件でキャプチャした値を確認します:
    # Capture the value of mykey in the query string
    RewriteCond "%{QUERY_STRING}" "(.*(?:^|&))mykey=([^&]*)&?(.*)&?$"
    RewriteCond "%2"              !=not-so-secret-value
    RewriteRule "(.*)"            "-" [F]
  • この方法は前の方法の逆で、URL からパスコンポーネント (おそらく PATH_INFO) をクエリ文字列にコピーします:
    # The desired URL might be /products/kitchen-sink, and the script expects
    # /path?products=kitchen-sink.
    RewriteRule "^/?path/([^/]+)/([^/]+)" "/path?$1=$2" [PT]

翻訳済み言語:  de  |  en  |  es  |  fr  |  ja  |  ko  |  tr  |  zh-cn