URLリライトの復習とIE11のUser-Agent
以前の関連する記事:UbuntuサーバのApache2でURLリライトを試してみる
以前の記事でURLリライトの設定を書いた。最初書いた設定は想定とは異なるURLに書き換えられてしまい、修正して想定どおりのURL書き換えがされるようになった。しかし、どういう仕組みで動作が変わったのか理解していなかった。
あれからもう少し調べて、自分なりの解釈をまとめてみた。リファレンスに書いてある「事実」と自分なりの「解釈」がごっちゃになっていて信頼性は低い。
リダイレクトとURLリライトの違い・使い分け
URLが指し示している内容と違うものを返す方法には、URLリライトの他にリダイレクトがある。
リダイレクトは、例えばサイト全体が www.newsite.jp に移転したので前のサイトに来たアクセスを新しいサイトの方に転送した場合には次のように書く。
Redirect permanent / http://www.newsite.jp/
リダイレクトとURLリライトについて、表にしてみた。
リダイレクト | URLリライト | |
---|---|---|
URL | 書き換えられる。ブラウザのアドレスバーのURLは最終的にアクセスした先のURLになる。 | 書き換えられない。ブラウザのアドレスバーのURLは変わらない。(設定によっては書き換えられる) |
レスポンス | ステータスコードは301(Moved Permanently)。ヘッダーのLocationに転送先のURLが入る。 | ステータスコード、メッセージはURLリライトで書き換えられた最終的なURLのものとなる。 |
mod_rewrite | mod_rewriteがなくても利用できる。 | インストールされて有効になっていなければ使えない。 |
条件の設定 | 出来ない。 | 出来る。かなり複雑な条件も設定できる。 |
URLリライトというのはmod_rewriteの機能の事だから、mod_rewriteがなければ使えないのは当然。
mod_rewrite がインストールされていなければリダイレクトを使うしかない。また、サイトをファイル名・ディレクトリ構成をそっくりそのまま移転した場合もリダイレクトを使うのが簡単。
それ以外の場合、例えば色々条件を付けて転送したい場合はURLリライトを使う。
なぜURLリライトが無限ループしなくなったのか
まず、言葉の定義。
.htaccess や apache2 設定ファイルの "<Directory>" 内に書かれた一連の書き換えルールを「ルールセット」と呼ぶ。<br />
RewriteRuleの末尾に "[" と "]" に囲まれてRとかLとか書いてあるのがRewriteRuleのフラグ。フラグの個々の意味は後で説明する。
次にURLリライトの動作について。
URLリライトはルールセットを使用して次のように動作する。
- 書き換え前のURLに書き換えルールを順番に適用して書き換えを試みる。
- ルールにマッチするものがなく、URLが書き換えられなかった場合、書き換えは終了。
- 書き換えによって外部サイトに転送される場合、書き換えは終了。
- それ以外、つまりURLが元のURLと同じサイト内のURLに書き換えられた場合、書き換え後のURLを書き換え前のURLとして1に戻る。
つまり、外部サイトに転送されるか、URLがルールにマッチせずに書き換えの必要がなくなるまで何度もルールセットが適用される。
上記を踏まえて、前の記事で書いたURLリライトの設定が以下である。
RewriteEngine on RewriteBase /test/rewrite/ RewriteRule ^top.html - [L] RewriteRule ^index.html$|^$ top.html [L] RewriteRule ^y.*$ http://www.yahoo.co.jp/ [R,L] RewriteCond %{HTTP_USER_AGENT} MSIE RewriteRule ^.+$ ie.html [L]
最初に書いた設定は4行目のルールがなかったために、思ったような書き換えにならなかった。
IEで "http://<ホスト名>/test/rewrite/index.html" にアクセスした場合、/test/rewrite/top.html が表示されると想定していたが、実際には /test/rewrite/ie.html が表示された。
なぜ4行目のルールがあると想定通りの動きになるのか。
ポイントは4行目のルールにある "-" である。"-" はURLのマッチングだけを行い置換は行わないという特殊な置換対象である。
URLリライトは以下のように行われる。
1回目のルールセット適用:6行目の index.html が top.html に書き換えられる。このルールにはLフラグがあるのでルールセット適用はここで終了する。
2回目のルールセット適用:4行目のルールに top.html がマッチするが、置換対象が "-" なのでURLは書き換えられない。このルールにはLフラグがあるのでルールセット適用はここで終了する。今回のルールセット適用ではURLの書き換えは起こらなかったので、URLリライト自体が終了する。
最終的にURLは "http://<ホスト名>/test/rewrite/top.html" に書き換えられる。
もし4行目がコメントアウトされていると、2回目のルールセット適用において、ブラウザがIEなので9,10行目のルールによって top.html が ie.html に書き換えられてしまう。
ちなみに IE11からUser-Agentに "MSIE" というのが含まれなくなった(参考14)ので、上記のRewriteCondの条件はIE11では使えない。
RewriteRuleの書式
RewriteRuleの書式は以下である。
RewriteRule パターン 置換対象 [[フラグ]]
フラグを複数指定する場合はカンマで区切って指定する。
フラグの一部を下表に示す。
フラグ | 説明 |
---|---|
L | ここで書き換え処理を中止し、後続のルールによってそれ以上書き換えられることを防止する。 |
R[=code] | 外部サイトにリダイレクトする。codeはレスポンスコード。省略された場合は302(Found)。 |
NC | 大文字小文字を区別しない。 |
ページを外部サイトに移転した場合、RewriteRuleに "R=301" というフラグを付けてレスポンスコードを301(Moved Permanently)とするとよい。
上記以外のフラグは参考1,2などを参照。
RewriteCond
RewriteCondディレクティブはRewriteRuleの条件を定義する。RewriteCondの直後のRewriteRuleの条件となる。複数のRewriteCondはフラグでORを指定しなければANDで結合される。
書式は以下である。
RewriteCond テスト文字列 条件パターン [[フラグ]]
テスト文字列には "%{変数名}" の形式で変数を使うことが出来る。この前記や下記のルールセットのRewriteCondではHTTPヘッダのUser-Agentを "%{HTTP_USER_AGENT}" として使用している。その他の変数については参考1,2,10などを参照。
また、RewriteRuleと同様にフラグが指定可能である。書き方も同様で "[" と "]" の間に、数のフラグを書く場合はカンマ区切りで書く。
フラグ | 説明 |
---|---|
NC | 大文字小文字を区別しない。 |
OR | 条件をORで結合する。 |
RewrteCondを使ったルールセットの例を下記に示す。実用を考えたものではない。
RewriteEngine on RewriteRule ^bbb.html - [L] RewriteRule ^ccc.html - [L] RewriteCond %{HTTP_USER_AGENT} "Windows NT" [NC] RewriteCond %{HTTP_USER_AGENT} Trident [NC] RewriteRule ^.*a.html$ bbb.html RewriteRule ^.*b.html$ ccc.html
上記のルールセットにおいて、1つめのルールはRewriteCondによってブラウザがWindowsのIE(IE8以降)であることが条件となる。RewriteCondは直後のRewriteRuleにのみ係るので、2つ目のルールはRewriteCondによる条件は適用されない。
よってIE8以降のIEで "/xxa.html" とアクセスした場合、"xxa.html" → "bbb.html" → "ccc.html" と書き換えられる。
他のブラウザの場合は "/xxa.html" は書き換えられない
参考ページ:
・RedirectとURLリライトの違い・使い分け
1..htaccessによるリダイレクト徹底解説 - Cherry Pie Weblog
2.Rewrite/Redirect - Yuta.Kikuchiの日記
・リダイレクトについて
3.htaccess解説/リダイレクト(サイトの引越し)
・mod_rewriteのリファレンス
4.mod_rewrite - Apache HTTP Server
5.Apache module mod_rewrite
・URLリライトの設定について
6.mod_rewriteの考え方。 - こせきの技術日記
…一部リンクが切れているが、RewriteRuleとRewriteCondの関係の説明がわかりやすい。
7.Apache Rewrite 設定のサンプル(1) : 個別のURLを転送する | OSCALOG
8..htaccess ファイルで mod_rewrite の設定をする時の注意点 | ミヤビッチの穴
9., mod_rewriteによるURLの書換えに関するメモ - 忘れたときに備えた記録(2007-07-18)
・RewriteCondについて
10.Apache RewriteCond の基礎知識 | WEB ARCH LABO
・RewriteCondによる条件の例
11.htaccessによるPC・スマートフォンの振り分け転送
12.Apache でアクセスを制限する時間帯を設定する | ポンタの技術日記
13.ApacheウェブサーバーのRewrite設定で使える正規表現サンプル集 | Web担当者Forum
・IE11のUser-Agentについて
14.IE11のユーザエージェント問題 - 開発者側でできる対策 (判定方法の変更/互換性モードの利用) - ふろしき.js
« PHPメモ038:PHPのswitchの比較は厳密な比較ではない | Main | 2014年初釣り »
「プログラミング、技術情報」カテゴリの記事
- PHPStorm 2018.1.7 に更新(2018.12.09)
- 技術メモをQiitaに移行(2016.01.24)
- 正規表現メモ:ものぐさ(最小)マッチング(2015.11.29)
- BASE64にエンコード/デコードするバッチファイル(2015.11.23)
- Windows7の検索ボックスの検索条件指定(フォルダの除外など)(2015.08.16)
「Linux」カテゴリの記事
- CakePHPのインストール(2015.06.14)
- PHPからPDOでPostgreSQLに接続する(2015.06.09)
- Laravel4のインストール(2015.05.06)
- URLリライトの復習その2(2015.04.07)
- composerのインストール(2015.04.01)
The comments to this entry are closed.
Comments