file_get_contentsを使用したHTTPリクエスト、応答コードの取得


87

file_get_contents一緒に使用stream_context_createしてPOSTリクエストを作成しようとしています。これまでの私のコード:

    $options = array('http' => array(
        'method'  => 'POST',
        'content' => $data,
        'header'  => 
            "Content-Type: text/plain\r\n" .
            "Content-Length: " . strlen($data) . "\r\n"
    ));
    $context  = stream_context_create($options);
    $response = file_get_contents($url, false, $context);

正常に動作しますが、HTTPエラーが発生すると、警告が表示されます。

file_get_contents(...): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request

そしてfalseを返します。次の方法はありますか?

  • 警告を抑制します(失敗した場合に独自の例外をスローする予定です)
  • ストリームからエラー情報(少なくとも応答コード)を取得します

回答:



19

(OPによって受け入れられたものを含む)どの回答も実際には2つの要件を満たしていません。

  • 警告を抑制します(失敗した場合に独自の例外をスローする予定です)
  • ストリームからエラー情報(少なくとも応答コード)を取得します

これが私の見解です:

function fetch(string $method, string $url, string $body, array $headers = []) {
    $context = stream_context_create([
        "http" => [
            // http://docs.php.net/manual/en/context.http.php
            "method"        => $method,
            "header"        => implode("\r\n", $headers),
            "content"       => $body,
            "ignore_errors" => true,
        ],
    ]);

    $response = file_get_contents($url, false, $context);

    /**
     * @var array $http_response_header materializes out of thin air
     */

    $status_line = $http_response_header[0];

    preg_match('{HTTP\/\S*\s(\d{3})}', $status_line, $match);

    $status = $match[1];

    if ($status !== "200") {
        throw new RuntimeException("unexpected response status: {$status_line}\n" . $response);
    }

    return $response;
}

これは無200応答をスローしますが、そこから簡単に作業できます。たとえば、単純なResponseクラスを追加し、return new Response((int) $status, $response);それがユースケースにより適している場合などです。

たとえばPOST、APIエンドポイントに対してJSONを実行するには:

$response = fetch(
    "POST",
    "http://example.com/",
    json_encode([
        "foo" => "bar",
    ]),
    [
        "Content-Type: application/json",
        "X-API-Key: 123456789",
    ]
);

コンテキストマップ"ignore_errors" => trueでの使用に注意してください。httpこれにより、関数が2xx以外のステータスコードに対してエラーをスローするのを防ぐことができます。

これは、ほとんどのユースケースで「適切な」量のエラー抑制である可能性があります。エラー@抑制演算子を使用することはお勧めしません。これにより、誤った引数を渡すなどのエラーも抑制され、誤ってバグが隠される可能性があります。呼び出しコード。


5

受け入れられた応答にさらに数行を追加して、httpコードを取得します

function getHttpCode($http_response_header)
{
    if(is_array($http_response_header))
    {
        $parts=explode(' ',$http_response_header[0]);
        if(count($parts)>1) //HTTP/1.0 <code> <text>
            return intval($parts[1]); //Get code
    }
    return 0;
}

@file_get_contents("http://example.com");
$code=getHttpCode($http_response_header);

エラー出力を非表示にするには、両方のコメントに問題はありません。ignore_errors= trueまたは@(@が好きです)


-1

別の問題でこのページにアクセスしたので、回答を投稿します。私の問題は、警告通知を抑制し、ユーザー向けにカスタマイズされた警告メッセージを表示しようとしていたことでした。そのため、この単純で明白な修正が役に立ちました。

// Suppress the warning messages
error_reporting(0);

$contents = file_get_contents($url);
if ($contents === false) {
  print 'My warning message';
}

そして、必要に応じて、その後エラー報告を元に戻します。

// Enable warning messages again
error_reporting(-1);

-2

@file_get_contentsignore_errors = true同じではありません。最初のものは何も返しません。2つ目はエラーメッセージを抑制しますが、サーバー応答(400 Bad requestなど)を返します。

私は次のような関数を使用します:

$result = file_get_contents(
  $url_of_API, 
  false, 
  stream_context_create([
    'http' => [
      'content' => json_encode(['value1' => $value1, 'value2' => $value2]), 
      'header' => 'Authorization: Basic XXXXXXXXXXXXXXX', 
      'ignore_errors' => 1, 
      'method' => 'POST', 
      'timeout' => 10
    ]
  ])
);

return json_decode($result)->status;

200(OK)または400(Badリクエスト)を返します。

それは完璧に機能し、cURLよりも簡単です。


そして、これはどのように問題を解決しますか?応答コードの取得方法を説明できますか?
ニコハース2018

@Nico私のソリューションについてどう思いますか?
18

JSONの結果を解析せず、という名前のランダムなフィールドを読み取らないため、これはまだ悪い問題ですstatus。API呼び出しのHTTPステータスコードとは関係ありません
Nico Haase 2018

接続するRESTfulAPIがJSON応答を返すこと、および目的のために知る必要があること(200または400)が「ステータス」フィールドに含まれていることは明らかです。それが私が必要とするすべてであり、それが私が得るすべてです。HTTPステータスコードを知る必要がある場合は、次のようにします。return$ http_response_header [0]; ただし、@ file_get_contentsでは機能しないことに注意してください。
18

そして、これは元の質問にどのように答えますか?$http_response_header[0]非常に賛成の答えであるが、うまくいかないと思うのはなぜfile_get_contentsですか?
ニコハーゼ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.