HTTP_REFERER の挙動を探る

SPECIAL


序論

ASP でいろいろとプログラミングしていたときのこと。とある理由から HTTP_REFERER を利用して訪問者がどこからやってきたのか、そしてそれに応じた処理をしようということになりました。

ASP において、HTTP_REFERER を取得したのは Session On Start 、つまりセッション開始直後の取得です。

基本的に作成環境は Internet Explorer 5.01 なので、そちらで動作チェックをして無事成功しました。そして、Netscape Navigator 4.7 で動作確認をしてみると・・・。

なんだかよからぬ動きをしてしまいました。どうやら IE と NN とでは情報に若干の食い違いがあるようです。

そこで、いろいろと調べてみた結果をまとめてみました。

 

HTTP_REFERER とは

HTTP_REFERER とは、ブラウザが Web サーバに対して送る情報のひとつで、どこからリンクをたどって、Web サーバのページへ来たかという情報です。

たとえば http://www.yahoo.co.jp/ から http://www.ez-net.jp/ へとリンクをたどってきたと仮定しましょう。

その場合、HTTP_REFERER には http://www.yahoo.co.jp/ という値が設定されます。

注意することは、ブラウザによっては HTTP_REFERER を Web サーバへ送ってこない場合があるということです。つまり、HTTP_REFERER をみればどこから来たかが確実にわかる、というわけではないので注意してください。

一般によく知られているブラウザは対応しているようですが・・・。

 

実際の挙動

HTTP_REFERER に対応している Netscape Navigator 4.7 と Internet Explorer 5.01 を用いて、実際に HTTP_REFERER にどのようなデータが渡されてくるかを調べてみました。

実際にどこかの Web ページのリンク <A HREF=""> をクリックしてきた場合には、<A> が記述されているページの URL が HTTP_REFERER に渡されてきます。

メールに書かれたリンクや、ブックマーク、アドレスの欄への URL の手入力の場合は HTTP_REFERER の情報が送られてこないようです。

また、ディスクに保存されている HTML 文書をブラウザで開いて、そのなかにかかれているリンク <A> をクリックした場合も、HTTP_REFERER には情報は送られてきません。

 

つまり、Web サーバから Web サーバ(同一サーバも含む)へリンクをたどる場合にのみ、HTTP_REFERER が次の Web サーバへ伝えられるようです。

 

フレームにおける挙動の違い

さて、フレーム内でもリンクは利用します。ただし <FRAME SRC=""> と、通常のリンクとは違ってきますが。

このフレームにおけるリンクで、Internet Explorer と Netscape Navigator とで HTTP_REFERER に大きな違いが現れます。

 

Internet Explorer の場合、<FRAME> タグで呼ばれたページに対して、<FRAME> が記述されているページの URL を HTTP_REFERER として Web サーバへ渡します。

つまり、フレーム内の各ページの HTTP_REFERER は親フレームの URL ということになります。

 

Netscape Navigator の場合、<FRAME> タグで呼ばれたページには、親フレームが受け取った HTTP_REFERER の内容が渡されます。

よって、フレーム内の各ページの HTTP_REFERER は親フレームの URL ではなく、親フレームへのリンク元の URL が渡されます。

 

Netscape の大きな落とし穴

Internet Explorer の場合は、HTTP_REFERER は直感的な伝え方をするのでわかりやすいのですが、Netscape Navigator はやや不思議な伝え方をします。

もう一度整理をしますと、<A> によってリンクした場合は <A> がおいてある URL が HTTP_REFERER に伝えられます。

<FRAME> によってリンクしている場合は、<FRAME> が記述されているページに渡された HTTP_REFERER が次の HTTP_REFERER にそのまま渡されます。つまり、親フレームのリンク元がフレーム内のページへ渡されます。

 

ここまでは何とかわかるのですが、問題は <A> と <FRAME> を両方使用した場合です。この場合、かなり思いがけないことが起こります。

 

まず、いわゆるメニューページ (MENU) から選択して、コンテンツページ (CONTENT) にその内容を表示させるというページを考えてみましょう。

EZ-NET (このサイト)のトップページもそうなっています。

 

この場合、MENU CONTENT があるわけですので、親フレーム (TOP) も存在します。

 

ちょっと複雑になってきますが、ここへ REFERER というページからリンクしてjきたとします。

 

まず、TOP へ来た時点で、

HTTP_REFERER @ TOP = REFERER
HTTP_REFERER @ MENU = REFERER
HTTP_REFERER @ CONTENT = REFERER

となっています。

 

MENU の中には、いろいろなページへのリンク <A> が張られています。

ここで、MENU の中のページをひとつ選択したとします。すると、CONTENT のフレームに新しいページが読み込まれます。

 

<A> の性質上、<A> の張られているページの URL が HTTP_REFERER として渡されるので、

HTTP_REFERER @ TOP = REFERER
HTTP_REFERER @ MENU = REFERER
HTTP_REFERER @ CONTENT = MENU

というように、CONTENT ページの HTTP_REFERER が MENU ページの URL に変化します。

 

通常はこの程度で推測が立たなくもないのですが、問題は MENU のリンク先のページがまたフレームを使っている場合です。

 

上記の非フレームの例で考えると、MENU から選択したページの HTTP_REFERER にはちゃんと MENU の URL がついています。

つまり MENU のリンクから表示されたことが伝わっています。

 

しかし MENU から再びフレームページを読み込むと推測しにくい状況になります。

とりあえず、メニュー (CONTENT_MENU) と内容 (CONTENT_CONTENT) とで構成されるフレームページ (CONTENT_TOP) が呼び出されることにします。

 

結論から言いますと、

HTTP_REFERER @ TOP = REFERER
HTTP_REFERER @ MENU = REFERER
HTTP_REFERER @ CONTENT_TOP = REFERER
HTTP_REFERER @ CONTENT_MENU = REFERER
HTTP_REFERER @ CONTENT_CONTENT = REFERER

という状況になります。

 

CONTENT_TOP は、MENU の <A> リンクから読み込まれています。

ですので、CONTENT_TOP の HTTP_REFERER は MENU の URL になってもいいはずです。さらに、<FRAME> リンクの性質から、CONTENT_MENU CONTENT_CONTENT の HTTP_REFERER も MENU の URL になるはずです。

 

しかし結果から見ると、すべての HTTP_REFERER が根本のフレームページが呼ばれたときの HTTP_REFERER という状況です。

 

よって、フレーム内にまたフレームページを読み込んだ場合には、リンク元の情報が少しあやふやになってしまいます。

 

ただし、フレーム内からのリンクでも _parent によって親フレームへ <A> リンクを張っている場合は、直感的な動作を見せてくれます。

MENU から _parent によって CONTENT_TOP が呼ばれる場合、

HTTP_REFERER @ CONTENT_TOP = MENU
HTTP_REFERER @ CONTENT_MENU = MENU
HTTP_REFERER @ CONTENT_CONTENT = MENU

というようになります。