[PHP]Warning: get_headers() [function.get-headers]: This function may only be used against URLs.

Read More

PHPのget_headers()でhttp://でアクセス可能だった場所に、https://でアクセスしたら下記のようなワーニングが出た。

Warning: get_headers() [function.get-headers]: This function may only be used against URLs. in {filepath} on {line}
{}内は適当に読み替え


解決方法は、
php.iniのphp_openssl.dllのエクステンションをコメントアウトを外して有効にする。
■php.ini
// ↓コメントアウトを外す
extension=php_openssl.dll

その後Apacheの再起動。


このときphpinfo()を確認してみると以下の表示が出るようになっていた。



これでget_headers()を使ってもWarningは出ずに、httpと同じように期待する動作をするようになった。
よしよし。




ちなみにphp_openssl.dllのエクステンションを有効にする前にfile_get_contents()を使ってhttpsアクセスしようとしたら以下のワーニングが出てた。
Warning: file_get_contents(https://example.com/test.png) [function.file-get-contents]: failed to open stream: Invalid argument in {filepath} on {line}

こちらもphp_openssl.dllを有効にしたら問題なく動作するようになった。



PHPの関数を使ってssl領域にアクセスすることにphp_openssl.dllというエクステンションが必要ということなのだろう。




--
ここから↓は調べたり実際に試してみたけどよくわからなかったこと。


それは、
cURL関数の挙動がよくわからない


というのもphp_openssl.dllが有効になっていない環境でもhttpsアクセスできるんだなあ。

■cURL関数を使ったコンテンツの取得
<?php
$url='https://example.com/hoge.txt';
$ch = curl_init();
$options = array(
  CURLOPT_URL => $url,
  CURLOPT_HEADER => false,
  CURLOPT_NOBODY => false,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_SSL_VERIFYPEER => false,
);
curl_setopt_array($ch, $options);
$contents = curl_exec($ch);
echo $contents;
?>
※php_curl.dllが有効になっている必要がある

これでコンテンツが取れちゃう
php_openssl.dllを有効にしようがしていまいが関係ない。
とにかく取れる。


これはPHP定数のCURLOPT_SSL_VERIFYPEERがfalseになっているから動くことが確認できた。
CURLOPT_SSL_VERIFYPEERの説明文は以下のようになっている

■PHP定数:CURLOPT_SSL_VERIFYPEER
FALSE を設定すると、cURL はサーバー証明書の検証を行いません。
別の証明書を CURLOPT_CAINFO オプションで 指定するか、CURLOPT_CAPATH オプションで 証明ディレクトリを指定します。
ttp://php.net/manual/ja/function.curl-setopt.php


ん?サーバ証明書の検証を行わないだけでいけんの??
じゃあひょっとしてfile_get_contents()もサーバ証明書の検証を行わなければphp_openssl.dllを有効にしなくてもいけちゃうの!?


ってことで急いで組んでみた。

■file_get_contents()を使ったコンテンツの取得
<?php
$url='https://example.com/hoge.txt';
$options=array(
  'https' => array(
    'method' => 'POST',
    'header' => '',
    'content' => '',
    'ignore_errors' => true, 
    'timeout' => (float)10.5, 
    'verify_peer' => false,
    'allow_self_signed' => true , 
  ),  
);
$context = stream_context_create($options);
$contents = file_get_contents($url, false, $context);
echo $contents;
?>


結果は…ダメでした。
php_openssl.dllを有効にしないとワーニングが出る。



この差はどういうことだろう?

思うにcURL関数の方が挙動として間違っているような気がする。
だってphp_openssl.dllを有効にしてないんだもの。
というかcURL関数の挙動を許しちゃうのならphp_openssl.dllの必要性ないじゃん!


まあ現時点での感想はfile_get_contents()よりcURL関数を使った方が都合がいいってことくらい。
でもその内修正入ったりするのかな。
怖いな。