スタッフブログ

こんにちわ。 なおとです。
開発では、なにごともやってみて初めて分かるということがあるものです。 今回は、あるコンテンツに対して「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";
以上です。
トラックバック



