【PHP】URLを渡すとヘッダー情報を見てステータスを返すやつ書いた

投稿日:

例えば、あのURLはきちんと301されているだろうかとか、リンク先とか画像が404になっていないだろうかとか気になって夜も眠れない日は誰にでもあるはずです。唐突。

そんなわけで簡単にではありますがURLを渡すとヘッダー情報(get_headers)を見て、参照先URLのステータスを返す関数を書いてみました。
※ タイトルはキリッとしてますが大したものじゃありません
http://jp2.php.net/manual/ja/function.get-headers.php#119497 のほぼ完コピです。すいません。

2017/08/16 追記 クラスにしてみました

【PHP】URLを渡すとヘッダー情報を見てステータスを返すクラスを書いた | Shimabox Blog

ソースはこちら。

ソース

<?php
/**
* URLのステータスを返す
*
* <code>
* $ret = getUrlStatus($url);
*
* $ret->url; // string URL<br>
* $ret->reachedUrl; // string 最後に到達したURL<br>
* $ret->isValid; // bool 有効なURLか<br>
* $ret->redirectedUrls; // array リダイレクトがあった際のURL<br>
* $ret->redirectedCode; // array リダイレクト時のHTTPステータスコード<br>
* $ret->code; // int 最終的なHTTPステータスコード<br>
* $ret->is200; // bool HTTPステータスコードが200かどうか<br>
* $ret->is403; // bool HTTPステータスコードが403かどうか<br>
* $ret->is404; // bool HTTPステータスコードが404かどうか<br>
* $ret->is500; // bool HTTPステータスコードが500かどうか<br>
* </code>
*
* @param string $url
* @param array $streamContextOptions stream_context_set_defaultを呼びます(GETリクエスト以外とか指定したい場合など)
* @return stdClass
* @see http://jp2.php.net/manual/ja/function.get-headers.php#119497
*/
function getUrlStatus($url, array $streamContextOptions = null)
{
$ret = new stdClass();
$ret->url = $url;
$ret->reachedUrl = '';
$ret->isValid = false;
$ret->redirectedUrls = [];
$ret->redirectedCode = [];
$ret->code = 0;
$ret->is200 = false;
$ret->is403 = false;
$ret->is404 = false;
$ret->is500 = false;
if ($streamContextOptions !== null) {
stream_context_set_default($streamContextOptions);
}
$headers = @get_headers($url);
if ($headers === false) {
return $ret;
}
// redirectedCode と redirectedUrlsは対になるようにしたいので
// 一旦redirectedCodeを格納するものを用意する
$_redirectedCode = [];
foreach($headers as $header) {
// リダイレクトされたURL
if (preg_match('/\ALocation:\s(http.+)\z/', $header, $m)) {
$ret->redirectedUrls[] = $m[1];
continue;
}
// HTTPステータスコード
if (preg_match('/\AHTTP.+\s(\d\d\d)\s/', $header, $m)) {
$code = (int)$m[1];
$_redirectedCode[] = $code;
$ret->code = $code;
$ret->isValid = true;
}
}
$redirectedCnt = count($ret->redirectedUrls);
if ($redirectedCnt > 0) {
$ret->reachedUrl = $ret->redirectedUrls[$redirectedCnt - 1];
} else {
$ret->reachedUrl = $url;
}
// redirectedCodeとredirectedUrlsの共通項を取得(redirectedCodeとredirectedUrlsは対になるように)
$ret->redirectedCode = array_intersect_key($_redirectedCode, $ret->redirectedUrls);
$ret->is200 = $ret->code === 200;
$ret->is403 = $ret->code === 403;
$ret->is404 = $ret->code === 404;
$ret->is500 = $ret->code === 500;
return $ret;
}

Example

YahooのURLを渡してみる

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$ret = getUrlStatus('http://m.yahoo.co.jp');
var_dump($ret);
 
/*
object(stdClass)#1 (10) {
  ["url"]=>
  string(20) "http://m.yahoo.co.jp"
  ["reachedUrl"]=>
  string(24) "https://www.yahoo.co.jp/"
  ["isValid"]=>
  bool(true)
  ["redirectedUrls"]=>
  array(2) {
    [0]=>
    string(26) "https://m.yahoo.co.jp:443/"
    [1]=>
    string(24) "https://www.yahoo.co.jp/"
  }
  ["redirectedCode"]=>
  array(2) {
    [0]=>
    int(301)
    [1]=>
    int(302)
  }
  ["code"]=>
  int(200)
  ["is200"]=>
  bool(true)
  ["is403"]=>
  bool(false)
  ["is404"]=>
  bool(false)
  ["is500"]=>
  bool(false)
}
*/

これを見た感じ、http://m.yahoo.co.jp を渡すと、

  • まず、https://m.yahoo.co.jp:443/ に 301 リダイレクト
  • さらに、https://www.yahoo.co.jp/ に 302 リダイレクト
  • そして、HTTPステータスコード200 を返却

されていることがわかります。

適当な画像を指定してみる

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ret = getUrlStatus('https://example.com/hoge.png');
var_dump($ret);
 
/*
object(stdClass)#1 (10) {
  ["url"]=>
  string(28) "https://example.com/hoge.png"
  ["reachedUrl"]=>
  string(28) "https://example.com/hoge.png"
  ["isValid"]=>
  bool(true)
  ["redirectedUrls"]=>
  array(0) {
  }
  ["redirectedCode"]=>
  array(0) {
  }
  ["code"]=>
  int(404)
  ["is200"]=>
  bool(false)
  ["is403"]=>
  bool(false)
  ["is404"]=>
  bool(true)
  ["is500"]=>
  bool(false)
}
*/
 
var_dump($ret->is404 === true); // => true

is404trueとなります。

おまけ (POSTの場合)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
$data = http_build_query(['foo' => 'bar', 'hoge' => 'piyo']);
$header = [
    'Content-Type: application/x-www-form-urlencoded',
    'Content-Length: ' . strlen($data)
];
$options = [
    'http' => [
        'method'  => 'POST',
        'header'  => implode("\r\n", $header),
        'content' => $data
    ]
];
 
$ret = getUrlStatus('http://localhost/post.php', $options);

第二引数にstream_context_set_default()で使うオプションを渡してください。
PHP: stream_context_set_default – Manual

まとめ

冒頭で述べたとおり http://jp2.php.net/manual/ja/function.get-headers.php#119497 をほぼ参考にして書きましたが、うまくPHPUnitseleniumなどと組み合わせるといいかもしれません。

投稿日:
カテゴリー: PHPUnitPHP

作成者: shimabox

Web系のプログラマをやっています。 なるべく楽しく生きていきたい。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

This site uses Akismet to reduce spam. Learn how your comment data is processed.