ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
エラーの典型例
Warning: file_get_contents(https://example.com/api):
failed to open stream: HTTP request failed!
HTTP/1.1 503 Service Unavailable
in /var/www/html/fetch.php on line 12
file_get_contents() や fopen() で外部 URL を読もうとした際、HTTP ステータスが 503 で返ったときの警告です。「ストリームを開けなかった」と書かれていますが、原因はHTTP レイヤの 503 です。
原因の切り分け
| 原因 | 判定方法 | 主な対処 |
|---|---|---|
| ① 一時的なメンテ・過負荷 | ブラウザで開いてみる、curl コマンドで再現 | 時間を置く、相手に問い合わせ |
| ② Bot 検出(Cloudflare 等) | ブラウザは OK でスクリプトのみ 503、レスポンスに cf-ray ヘッダ | User-Agent / Referer / Cookie を設定 |
| ③ レート制限 | 連続アクセス時のみ発生 | 間隔を空ける、指数バックオフ |
| ④ DNS 障害・SSL 問題 | エラー文言を確認 | DNS / 証明書を確認 |
| ⑤ 自サーバ側ファイアウォール | 同じ URL を別ホストから叩くと OK | 送信元 IP / IPS を確認 |
対処1: User-Agent を指定する(最頻出)
file_get_contents のデフォルト UA は PHP/8.x となり、これだけで多くの CDN が Bot 判定で 503 を返します。stream_context_create で UA とヘッダを補います:
$context = stream_context_create([
'http' => [
'method' => 'GET',
'header' => implode("\r\n", [
'User-Agent: Mozilla/5.0 (compatible; MyBot/1.0; +https://example.com/bot)',
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: ja,en;q=0.9',
'Referer: https://example.com/',
]),
'timeout' => 10,
'ignore_errors' => true, // 4xx/5xx でも例外的に body を取りたい場合
],
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
],
]);
$body = @file_get_contents('https://example.com/api', false, $context);
// $http_response_header に HTTP ヘッダ一覧が入る
// 例: HTTP/1.1 503 Service Unavailable
if (isset($http_response_header[0])
&& preg_match('#\bHTTP/\S+ (\d+)#', $http_response_header[0], $m)
) {
$status = (int) $m[1];
if ($status >= 400) {
throw new RuntimeException("HTTP $status: $body");
}
}
対処2: cURL に切り替える(強く推奨)
file_get_contents はリトライ・タイムアウト制御・詳細エラーが弱いです。外部 HTTP は cURL かライブラリ経由に切り替えるのが本筋:
function fetch(string $url): string
{
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => 'Mozilla/5.0 MyBot/1.0',
CURLOPT_HTTPHEADER => [
'Accept: text/html,*/*;q=0.8',
'Accept-Language: ja,en;q=0.9',
],
]);
$body = curl_exec($ch);
if ($body === false) {
$err = curl_error($ch);
curl_close($ch);
throw new RuntimeException("cURL: $err");
}
$status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 400) {
throw new RuntimeException("HTTP $status returned");
}
return $body;
}
対処3: リトライ + 指数バックオフ
503 はしばしば一時的なので、少し待って再試行すれば成功します。指数バックオフ(1s → 2s → 4s …)で実装するのが定石:
function fetchWithRetry(string $url, int $maxRetry = 4): string
{
$attempt = 0;
while (true) {
$attempt++;
try {
return fetch($url);
} catch (RuntimeException $e) {
if (strpos($e->getMessage(), 'HTTP 503') === false
&& strpos($e->getMessage(), 'HTTP 429') === false) {
throw $e; // 503 / 429 以外はリトライしない
}
if ($attempt >= $maxRetry) throw $e;
$sleep = min(2 ** ($attempt - 1), 30); // 1, 2, 4, 8, ... 最大 30 秒
error_log("HTTP 503: retry in {$sleep}s (attempt $attempt)");
sleep($sleep);
}
}
}
対処4: Retry-After ヘッダを尊重する
多くのサーバは 503 / 429 と一緒に Retry-After ヘッダで「N 秒後に再試行してね」を伝えます:
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
]);
$response = curl_exec($ch);
$status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
$hSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$rawH = substr($response, 0, $hSize);
$body = substr($response, $hSize);
curl_close($ch);
if ($status === 503 || $status === 429) {
if (preg_match('/^Retry-After:\s*(\d+)/mi', $rawH, $m)) {
$wait = (int) $m[1];
sleep(min($wait, 60));
// 再試行
}
}
対処5: allow_url_fopen が無効化されている可能性
共有レンタルサーバや一部の本番環境では allow_url_fopen = Off になっています。この場合 file_get_contents 自体が URL を開けず、別エラーになります:
ini_get('allow_url_fopen'); // "1" なら有効
// 確認用 PHP コマンド
// php -i | grep allow_url_fopen
無効ならば cURL 一択です。OS / ホスティング会社の設定で変更不可のことが多いため、移植時の前提として扱います。
対処6: Laravel / Guzzle で書き直す
// Laravel
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'User-Agent' => 'MyApp/1.0',
])
->timeout(15)
->retry(3, 1000) // 1 秒間隔で 3 回
->get('https://example.com/api');
if ($response->successful()) {
$data = $response->json();
}
// Guzzle
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
$stack = HandlerStack::create();
$stack->push(Middleware::retry(
function ($retries, $request, $response = null, $exception = null) {
return $retries < 3 && $response && $response->getStatusCode() === 503;
},
function ($retries) {
return 1000 * (2 ** $retries); // 指数バックオフ (ms)
}
));
$client = new Client(['handler' => $stack, 'timeout' => 15]);
$res = $client->get('https://example.com/api');
本当に「相手が落ちている」場合の見分け方
# ターミナルから直接 curl
curl -v -A "Mozilla/5.0" https://example.com/api
# ステータスだけ
curl -s -o /dev/null -w "%{http_code}\n" -A "Mozilla/5.0" https://example.com/api
# 別ホストから(自宅 / モバイル回線 / クラウド)でも 503 なら相手側障害
# 自サーバからだけ 503 なら IP ブロック / FW / Bot 検知
FAQ
Q: 警告だけ消したい
A: @file_get_contents() で抑制可能だが、根本対処にならない。ステータスを $http_response_header で確認して例外化するべき。
Q: Cloudflare の保護を突破できる?
A: 規約上の問題が出るため避けるべき。相手に API 連携を依頼するか、相手が提供する正規エンドポイントを使う。
Q: 503 が永続的に出続ける
A: 相手側が IP ブロックしている可能性。送信元 IP の見直し、もしくは契約サポート窓口へ問い合わせ。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
- Error 400 : Bad Request Parameter Operation is missing
- MissingParameter. The request must contain the parameter Signature.
- RequestThrottled. AWS Access Key ID: ... . You are submitting requests too quickly
- SignatureDoesNotMatch. The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
- failed to open stream: HTTP request failed! HTTP/1.1 503 Service Unavailable
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Laravel キャッシュクリア完全ガイド(cache:clear / config:clear / 2026-05-18 07:42:07
- プロジェクトの作成と削除 2026-05-18 07:42:07
- インストール直後にNetbeansが反応しない 2026-05-18 07:42:07
- 動画やチャンネルの検索 2026-05-18 07:42:07
- APIキー取得方法 2026-05-18 07:42:07
- チャンネル情報の取得 2026-05-18 07:42:07
- API 入門 — Web API(REST / GraphQL / gRPC / 2026-05-18 07:42:07
- インストール(eclipseプラグイン) 2026-05-18 07:42:07
- Laravel「Dotenv values containing spaces must be surrounded 2026-05-18 07:42:07
- エラー一覧 2026-05-18 07:42:07
- curl: (51) SSL: certificate subject name '~' does not match 2026-05-18 07:42:07
- インストール方法(Windows版) 2026-05-18 07:42:07
- JSONから配列に変換 2026-05-18 07:42:07
- 処理を一定時間待つ 2026-05-18 07:42:07
- A non well formed numeric value encountered 2026-05-18 07:42:07
コメントを削除してもよろしいでしょうか?