まとメモ

29才でエンジニアに転職したエンジニアのメモ

PHP URLの存在確認

URLの存在確認

  • 下記コードは、httpのリクエストを送信してURLにアクセス可能かどうか確認している。
  • 確認する方法はいくつかある

    • file_get_contents
    • fopen
    • get_headers
  • 現状のコード

## URLのチェック
$text = "チェックするURL"
public static function validation_site_url($text)
{
  // プロトコルがない場合
  if(!preg_match('/^https?:\/\//', $text)) $text = 'http://'.$text;
  if($fp = @fopen($text, 'r')){
    fclose($fp);
    return true;
  }
  else
  {
    return false;
  }
}

参考 【php】 URLが存在するかどうか確認する at softelメモ

fopen()の返り値

成功した場合はファイルポインタを返します。失敗した場合はFALSEを返し、E_WARNINGレベルでエラーを発します。エラー制御演算子(@)が使用可能です。通常はこのファイルポインタを用いて、ファイル操作を行います。 PHP関数講座:fopen | そふぃのphp入門

ブラウザではアクセスできるのに、上記のコードでfalseが返ってくるURLがある


対策その1
  • fopen()ではない処理を試す

get_headersを使ってみる

get_headersの返り値

数値添字配列あるいは連想配列でヘッダを返します。 失敗した場合は FALSE を返します。 PHP関数 - HTTPヘッダーを取得 - get_headers() - PHP入門 - Webkaru

問題のURLで試してみる

$url = "問題のURL";
$http_header = get_headers($url);
var_dump($http_header);

array(6) {
  [0]=>
  string(22) "HTTP/1.1 403 Forbidden"
  [1]=>
  string(35) "Date: Mon, 24 Dec 2018 17:03:33 GMT"
  [2]=>
  string(14) "Server: Apache"
  [3]=>
  string(19) "Content-Length: 328"
  [4]=>
  string(17) "Connection: close"
  [5]=>
  string(43) "Content-Type: text/html; charset=iso-8859-1"
}

HTTPステータスコード403が返って来た

なぜブラウザでは200が返って来るのに、get_headersでは403が返ってくるのか

原因

fopenget_headersではUser-Agentヘッダーが送信されていないので、User-Agentヘッダーをチェックしているサイトでは期待する値を取得できない

対策

User-Agentヘッダーを送信する

User-Agentヘッダーとは

HTTPではUser-Agentヘッダーが定義されている。 クライアントはサーバーにリクエストを送る際に、ユーザーエージェントの情報をUser-Agentヘッダーとして送信する。User-Agentヘッダーには、アプリケーション名、バージョン、ホストオペレーティングシステムや言語といった情報が含まれる。 ユーザーエージェント - Wikipedia

取得してみる

var_dump($_SERVER['HTTP_USER_AGENT'])

string(120) "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"

このUser-Agentヘッダーをfopenget_headersの前にini_setでセットする

ini_set ('user_agent', $_SERVER['HTTP_USER_AGENT']); 

現状のコードを修正する

## URLのチェック
public static function validation_site_url($text)
{
  // プロトコルがない場合
  if(!preg_match('/^https?:\/\//', $text)) $text = 'http://'.$text;
  ini_set ('user_agent', Input::server('HTTP_USER_AGENT'));  //追記コード
  if($fp = @fopen($text, 'r')){
    fclose($fp);
    return true;
  }
  else
  {
    return false;
  }
}

fopenステータスコード1xx,4xx,5xxではfalseを返す

PHP: fopen - Manual

参考 get headers - PHP - get_headers returns "400 Bad Request" and "403 Forbidden" for valid URLs? - Stack Overflow

ファイルのオープンとクローズ(fopen, fclose) - ファイル関数 - PHP関数

PHPにおいてファイルの入出力 - Qiita

[メモ] PHPのfile_get_contentsを、HTTPリクエストに使うときのTIPS ::ハブろぐ

404エラーとは〜今さら聞けない基礎知識と原因の対処方法を解説|ferret [フェレット]

PHP、URLの存在チェックを行うついでに「get_headers()」関数で遊んでみる。|マコトのおもちゃ箱 ~ぼへぼへ自営業者の技術メモ~

ユーザーエージェント とは 意味/解説/説明 【User Agent, UA】 | Web担当者Forum

UserAgentからOS/ブラウザなどの調べかたのまとめ - Qiita