LoginSignup
1
0

More than 3 years have passed since last update.

file_get_contentsが失敗する

Last updated at Posted at 2020-02-12

以下のサイトのサンプルを自前の環境で実行しようとしました。
https://note.com/kazztech/n/ndb3a5468f299

呼び出しプログラムを実行したところ、以下のエラーになりました。
PHP Warning: file_get_contents(http://192.168.33.10:8000/api.php?num=10): failed to open stream: HTTP request failed!

このURL自体(以下URL)は表示できました。
http://192.168.33.10:8000/api.php?num=10
結果として、{ "status": "yes", "x114": "1140", "x514": "5140" }と表示されました。

なぜエラーになるのでしょうか?

検索したところ、php.iniのallow_url_fopenの値の問題かもしれないとありましたが、これはOnでした。
WebサーバーはPHPのビルトインサーバーです。
PHPは7.1.33です。

補足1
絶対URLがうまく動いていないのかと思い、簡単なHTMLを試してみました。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Absolute URL</title>
</head>
<body>
<a href="http://192.168.33.10:8000/abso.html">test</a>
</body>
</html>

普通にうごきます。(abso.htmlに飛ばされました)

補足2
本丸のapi.phpにしてみました。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Absolute URL</title>
</head>
<body>
<a href="http://192.168.33.10:8000/api.php">test</a>
</body>
</html>

{ "status": "no" }と表示されました。(api.phpに飛ばされました)

絶対URLやapi.phpは問題ではなさそうです。

補足3
<?php
$data = file_get_contents("http://yahoo.co.jp/");
echo $data;

これだとうまくいく。(yahooが表示される)けど・・・
<?php
$data = file_get_contents("http://192.168.33.10:8000/api.php");
echo $data;

これだとダメ。
file_get_contentsは普通に動いているのだけど、PHPビルトインサーバーを指定したときはうまく動かないということなのかな・・・

補足4
こんな記事に行き当たった。
file_get_contents() で HTTP経由でデータを取得しようとしてエラーになったとき
https://qiita.com/matsuoshi/items/60a3240d0667272e0336
相手によってうまくいったり、いかなかったりしたというもの。
yahooはうまくいくけど、自前はうまくいかないというのはそっくり。
ただ、残念なことに?allow_url_fopenはONです。
しかし、相手によってうまくいったり、いかなかったりすることが、自身のphp.iniを更新することで変わるのが理解できない。
セキュリティ上、変なファイルを読み込んだらいけないとかなら、うまくいったり、いかなかったりするはずもなく、うまくいかないハズだ。

補足5
こんな記事に行き当たった。
allow_url_fopenが0のサーバーで外部ファイルを取得する方法
https://masshiro.blog/php-allow-url-fopen/
<?php
$url="http://192.168.33.10:8000/api.php";
$cp = curl_init();
/*オプション:リダイレクトされたらリダイレクト先のページを取得する*/
curl_setopt($cp, CURLOPT_RETURNTRANSFER, 1);
/*オプション:URLを指定する*/
curl_setopt($cp, CURLOPT_URL, $url);
/*オプション:タイムアウト時間を指定する*/
curl_setopt($cp, CURLOPT_TIMEOUT, 30);
/*オプション:ユーザーエージェントを指定する*/
curl_setopt($cp, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
$data = curl_exec($cp);
curl_close($cp);
echo $data;

コンソールにエラーは表示されないけど、api.phpからの返答は表示されない。
30秒待って呼び出し元とapi.phpの読み込みログが表示されるだけでした。
var_dumpしたら、bool(false)と表示された。
サーバーが原因と絞り込んでもよさそう・・・。

補足6
こんな記事に行き当たった。
PHPでURLが実際に存在するか確認する で、いろいろ勉強したのでメモ
http://blog.doli.jp/blog/2012/post473/
image.png
LocalもONでした・・・。

補足7
この記事をもとに試してみました。
https://www.sejuku.net/blog/24113
<?php
//コンテキストを設定
\$con = stream_context_create(array('http' => array('ignore_errors' => true)));
//URLを指定してレスポンスを取得する
$http = file_get_contents('http://192.168.33.10:8000/api.php', false, \$con);
//ステータスコードを取得する
\$code = substr($http_response_header[0], 9, 3);

var_dump($code);
bool(false)と表示されました。
原因が絞り込めないから絞り込めるようにしましょう。という記事なのに、残念です。

補足8
思考がハマってるっぽいので、根本から変えてみました。
絶対パスをやめて、相対パスで呼び出し。かつ、返却を簡素に。
〇呼び出し元
<?php
\$data = file_get_contents(dirname(__FILE__) . "/api.php");
var_dump($data);
〇api.php
<?php
print "response";
結果は、string(26) "と表示されました。ソース表示で確認すると、
string(26) "<?php
print "response";
"
こう表示されてました。
ソースがそのまま読み込まれてました。こんな仕様だとセキュリティ的におかしいと思うので、相対パスだから、こうなったのだと思います。
思考が切り替わらないという結果になりました。

補足9
そもそもの参考サイトに立ち返ってみました。
大本のサイトはapi.phpをlocalhost/api.phpとして呼び出しています。
私は192.168.33.10で呼び出しました。
VirtualBoxの呼び出し元を呼ぶときはこのアドレスで良いけど、file_get_contentsを使用するときは、このアドレスだとダメだという気がします。
かと言って、Localhostで呼べるように設定するのは大変そうです。
相対パスでは読み込めているので、相対パスありきで考えてみます。

1
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0