HTTPリダイレクト

Updated / Published

HTML文書の head要素内で meta要素http-equiv属性の値に"refresh" を記述し、content属性にUAが文書を読み込んでから何秒後に指定の URI文書を表示するように働きかける設定であるクライアントプルと呼ばれる技術があります。

<meta http-equiv="refresh" content="10;url=/new/">

この設定によって、別のリソース(情報資源)へと移動させるリダイレクト(ある URI から他の URI に転送させること)が可能になりますが、この方法は移動を通知するページ数が多い場合には手間がかかり、実用的ではありません。そこで、ファイルが多数あるディレクトリごと移動した場合であっても、ユーザが移動前のリソースのURI へアクセスすると自動的に移動後のリソースへと誘導することができる HTTPリダイレクトを紹介します。

HTTPリダイレクトを使う

Redirect permanent /old/ http://w3g.jp/new/

これは「old」というディレクトリ以下のファイルにアクセスがあった場合に、自動的に「new」というディレクトリ以下にある同じファイル名をもつファイルへと HTTPリダイレクトさせます。HTTPリダイレクトとは、ウェブサーバとUAの間で交わされるメッセージであるHTTPを用いたリダイレクトです。ウェブブラウザや検索エンジンのロボットなどの UA がウェブサーバに対してリソースをリクエスト(要求)した際のメッセージをHTTPリクエストヘッダと言い、このリクエストに対してウェブサーバが返すメッセージをHTTPレスポンスヘッダと言います。このHTTPレスポンスヘッダ内に指定のURI が別のURIに変更されたことを通知します。UA はウェブサーバからの「この URI は変更されました」というメッセージの通知を受けて、リダイレクト先のURIのウェブサーバにリクエスト(要求)しなおします。

ここでは Redirectディレクティブのpermanentオプション(属性)を使っており、この設定では UA に 301 Moved Permanentlyステータスコードを返します。301 Moved Permanently とは、そのリソースが恒久的に別の場所へ移動したことを伝え、今後は移動先のリソースへと要求するように促します。移動先の URI は絶対URI(http:// からはじまる)で記述します。

たとえば、現在アクセスしているウェブサーバの/old/a.htmlのURIをリクエスト(要求)した場合、UA はサーバからファイルが移転したことの通知を受けて、http://w3g.jp/new/a.html の URI をもつウェブサーバへと要求し、HTTP によって移動前のリソースの URI へのアクセスを自動的に移動後のリソースへとリダイレクトさせることが可能です。

正規表現を使ったHTTPリダイレクト

RedirectMatchディレクティブでは、通常の Redirectディレクティブに加えて正規表現を使った HTTPリダイレクトが可能です。たとえば、今まで HTMLファイル形式で作成していたものを、includeモジュールなどの使える PHP のファイルへと移し変えた場合を想定してみましょう。

RedirectMatch permanent (.*)\.html$ http://w3g.jp$1.php

ここでは「(.*)\.html$ http://w3g.jp$1.php」という記述を行うことで、移転前は URI の最後が ".html" であったファイルが要求された場合に ".html" に代わって ".php" の拡張子をもつファイルを要求するように設定しています。RedirectMatchディレクティブの後にある permanentオプション(属性)は、そのリソースが永久的に移動したことを示すステータスを返します(オプションは次の項目にまとめています)。このように正規表現のパターンマッチ(任意の文字列に文字列のパターンをマッチさせること)を使うことでファイル名はそのままで拡張子だけを変えてHTTPリダイレクトさせたり、特定のファイルだけを HTTPリダイレクトさせることも可能です。

ただし、RedirectMatchディレクティブを同一サーバ内でリダイレクトさせるのに使用する際には、ディレクトリ名が重複する場合があるので注意が必要です。

RedirectMatch permanent /old/(.*) http://w3g.jp/new/old/$1

この例では、リダイレクト先の URI に転送元のディレクトリ名と同じ文字列が含まれているために無限ループ(循環)という事態に陥ります。このため同一サーバ内において HTTPリダイレクトを使用する場合は、転送先と転送元のディレクトリ名が被ることのないように注意してください。

HTTPリダイレクトとステータスコード

人間であればテキストで「このリソースは、こちらの URI へ移動しました」と記されていれば、それを理解することができますが、ウェブブラウザや検索エンジンのロボットなどを含める UA に対してリソースが移動したことを知らせるには、HTTPリダイレクトを使って通知しなければなりません。HTTPリダイレクトには、恒久的にリソースが移転したことを示す 301 Moved Permanentlyステータスコードを返す permanentオプション以外にも、次のようなオプション(属性)があります。

Redirect
どのステータスを返すかのオプション部分を省略した表記。デフォルトの Redirectディレクティブに tempオプションを指定した場合と同じ 302 Moved Temporarilyステータスコードを返す。オプションをつける場合は permanent, temp, seeother, gone の4つがある。
Redirect permanent
301 Moved Permanentlyステータスコードを返す。要求されたリソースが、永久(恒久的)に別の場所へ移動したことを伝え、今後はそちらをリクエスト(要求)するように UA へ促す。
Redirect temp
Redirectディレクティブの初期値。302 Moved Temporarilyステータスコードを返す。要求されたリソースが、一時的に指定の場所へ移動していることを UA に伝える。
Redirect seeother
303 See Otherステータスコードを返す。要求されたリソースが他の別のリソースで置き換えられたことを UA に伝える。
Redirect gone
410 Goneステータスコードを返す。要求されたリソースが永久に削除されたことを UA に伝える。goneオプションの場合は、値に URI を記述してはいけない(記述する必要がない)。

さらに、Redirectディレクティブのオプションを指定することなく同じステータスコードを返すディレクティブもあります。

RedirectPermanent
Redirectディレクティブの permanentオプションを指定した場合と同じ、301 Moved Permanentlyステータスコードを返す。要求されたリソースが、永久(恒久的)に別の場所へ移動したことを伝え、今後はそちらへリクエストするよう UA に促す。
RedirectTemp
Redirectディレクティブ、または Redirectディレクティブの tempオプションを指定した場合と同じ、302 Moved Temporarilyステータスコードを返す。要求されたリソースが、一時的に指定の場所へ移動していることを UA に伝える。

これらはウェブサイトの管理者として是非知っておきたい知識です。Googleなどの検索エンジンのロボットにおいて移動先のリソースの URI を通知する場合には、リソースが恒久的に別の場所へ移動したことを伝え、今後は移動先のリソースへと要求するように促す 301 Moved Permanentlyステータスコードを返す方法がガイドラインで推奨されています。なぜならこの方法であれば、たとえ URI が変わっても、もとの URI に張られていたリンクなどのリンク元情報(リンクの質と量であるリンクポピュラリティも含む)を新しい URI に継承させることができるからです。

このように SEO の観点からも HTML文書などのリソースを移動させた場合には、meta要素を使ったクライアントプルなどによるリダイレクトではなく、ウェブブラウザや検索エンジンロボットなどを含めた UA にリソースが移動したことを通知できる HTTPリダイレクトを使うようにしましょう。また、その際に検索エンジンのガイドラインで推奨されている 301 Moved Permanentlyステータスコードを返すようにしておくのが最適な設定です。302 Moved Temporarilyステータスコードも同じようなものですが、その微妙な違いは最新版の URI が常に変化しており、移動したリソースが恒久的に固定された URI ではない場合などに適しているといえます。

mod_rewrite によるリダイレクト

RedirectディレクティブやRedirectMatchディレクティブ以外にURL書き換えエンジンのmod_rewriteモジュールを使っても同じようにHTTPリダイレクトが実現可能です。特にmod_rewriteモジュールは同一サーバ内のURIを正規化する場合に有効です。mod_rewriteモジュールと各ディレクティブについての解説はここでは割愛しますが、httpまたはhttpsへの統一、wwwあり・なしの統一、index.htmlあり・なしの統一、など実用的なものにおけるmod_rewriteモジュールを用いた301 Moved Permanentlyステータスコードを返す例を示します。ウェブサイトの管理者としては是非抑えておきたい知識です。

RewriteEngine on|off
RewriteCond テスト文字列 条件パターン
RewriteRule パターン 置換対象 [フラグ]

上記が基本形です。301 Moved Permanentlyステータスコードを返すには、フラグの部分で必ずR=301のコードを入れる必要があるます。コードが省略されている場合は、302 Moved Temporarilyステータスコードが返されることになり、意味が変わってくるので注意してください。

httpsスキームに統一

RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

httpスキームに統一

RewriteEngine on
RewriteCond %{HTTPS} on
RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

wwwサブドメインに統一

RewriteEngine on
RewriteCond %{HTTP_HOST} ^w3g\.jp$
RewriteRule ^(.*)$ http://www.w3g.jp/$1 [R=301,L]

wwwサブドメインなしに統一

RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.w3g\.jp$
RewriteRule ^(.*)$ http://w3g.jp/$1 [R=301,L]

index.htmlありに統一

RewriteEngine on
RewriteRule ^$ http://%{HTTP_HOST}/index.html [R=301,L]
RewriteCond %{THE_REQUEST} ^.*/
RewriteRule ^(.*)/$ http://%{HTTP_HOST}/$1/index.html [R=301,L]

index.htmlなしに統一

RewriteEngine on
RewriteCond %{THE_REQUEST} ^(.*)/index\.html
RewriteRule ^(.*)/index\.html$ http://%{HTTP_HOST}/$1 [R=301,L]