スタッフブログ

  • 最新配信
  • RSS

リダイレクトとget_headers()の返り値

naoto : 技術全般 2009/10/13 17:00

Blogger's Avatar

こんにちわ。 なおとです。

開発では、なにごともやってみて初めて分かるということがあるものです。 今回は、あるコンテンツに対して「HEADリクエストを送って存在確認をする」、というスクリプトを(PHPで)書いた時の話です。

マニュアルにはレスポンスが正常な場合(200 OK)の例が掲載されています。 これが、リダイレクトするコンテンツの場合には、少々様子が異なってきます。

結果を書いてしまうと、「get_headers()はリダイレクトを辿って複数のリクエストを行う」ということを知りました。 私は「HTTP HEADの結果に係わらず、1回だけリクエストして、その結果を返す」という動作を(勝手に)想像していたのですが、違いました。

動作を確認するために以下のような、リダイレクトを数回繰り返すサンプルを用意しました。(redirect.php)

<?php
$req = $res = $_SERVER['REQUEST_URI'];
if (preg_match('/[^\w\:\/\.]/i', $req)) {
    echo 'wrong request.';
} else {
    if (strpos($req, '.php') === (strlen($req) - 4)) {
        $res = $res . '/';
    }
    if (!strpos($req, '1111')) {
        $res = $res . '1';
        header('Location: ' . $res);
    } else {
        echo htmlspecialchars($req, ENT_QUOTES, 'UTF-8');
    }
}

これを、get_headers()を使って結果を見ます。(別のスクリプトです)

<?php
var_dump(get_headers('http://localhost/redirect.php', 1));

その結果が以下になります。
※分かりやすくするために、一部を編集しました

array
  0 => string 'HTTP/1.1 302 Found' (length=18)
  1 => string 'HTTP/1.1 302 Found' (length=18)
  2 => string 'HTTP/1.1 302 Found' (length=18)
  3 => string 'HTTP/1.1 302 Found' (length=18)
  4 => string 'HTTP/1.1 200 OK' (length=15)
  'Date' =>
    array
      0 => string 'Tue, 13 Oct 2009 06:38:51 GMT' (length=29)
      1 => string 'Tue, 13 Oct 2009 06:38:51 GMT' (length=29)
      2 => string 'Tue, 13 Oct 2009 06:38:51 GMT' (length=29)
      3 => string 'Tue, 13 Oct 2009 06:38:51 GMT' (length=29)
      4 => string 'Tue, 13 Oct 2009 06:38:51 GMT' (length=29)
  'Server' =>
    array
      0 => string 'Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.7 with Suhosin-Patch' (length=xxx)
      1 => string 'Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.7 with Suhosin-Patch' (length=xxx)
      2 => string 'Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.7 with Suhosin-Patch' (length=xxx)
      3 => string 'Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.7 with Suhosin-Patch' (length=xxx)
      4 => string 'Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.7 with Suhosin-Patch' (length=xxx)
  'X-Powered-By' =>
    array
      0 => string 'PHP/5.2.4-2ubuntu5.7' (length=20)
      1 => string 'PHP/5.2.4-2ubuntu5.7' (length=20)
      2 => string 'PHP/5.2.4-2ubuntu5.7' (length=20)
      3 => string 'PHP/5.2.4-2ubuntu5.7' (length=20)
      4 => string 'PHP/5.2.4-2ubuntu5.7' (length=20)
  'Location' =>
    array
      0 => string '/redirect.php/1' (length=15)
      1 => string '/redirect.php/11' (length=16)
      2 => string '/redirect.php/111' (length=17)
      3 => string '/redirect.php/1111' (length=18)
  'Content-Length' =>
    array
      0 => string '0' (length=1)
      1 => string '0' (length=1)
      2 => string '0' (length=1)
      3 => string '0' (length=1)
      4 => string '18' (length=2)
  'Connection' =>
    array
      0 => string 'close' (length=5)
      1 => string 'close' (length=5)
      2 => string 'close' (length=5)
      3 => string 'close' (length=5)
      4 => string 'close' (length=5)
  'Content-Type' =>
    array
      0 => string 'text/html' (length=9)
      1 => string 'text/html' (length=9)
      2 => string 'text/html' (length=9)
      3 => string 'text/html' (length=9)
      4 => string 'text/html' (length=9)

get_headers()の第2引数に「1」をセットしなかった場合は、もっと混沌とした結果になっていましたが、省略します。

それと今回は、自分自身にリダイレクトするスクリプトで実験しました。 異なるサーバ/スクリプトに跨ってリダイレクトを辿った場合は、レスポンス・ヘッダーの内容も異なると思われますので、もう少し複雑な結果になります。

これを受けて、「Locationの結果、行き着くコンテンツ」は次のように取得できることがわかります。 ただし、URLの解決(絶対URLに直す処理)は端折っています。 あと実際のコードでは、エラー処理など適宜しています。

<?php
$url = 'http://localhost/redirect.php';
$headers = get_headers($url, 1);
$location = $headers['Location'];
if (is_array($location)) {
    $location = array_pop($location);
}
if (
    (strpos('/', $location) === false)
    and
    (strpos('http', $location) === false)
    ) {
    $location = dirname($url) . '/' . $location;
}

echo "original: {$url} \n redirected: {$location} \n";

以上です。

トラックバック

スタッフブログ最新
カテゴリ一覧

〒104-0061 東京都中央区銀座1丁目3番3号 G1ビル7階
お問い合わせ TEL 03-3524-8860

Copyright(c) 2012 RYUS.All Rights Reserved.