HTTP 请求和 file_get_content,获取响应代码

我正在尝试使用 file_get_contentsstream_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。有没有办法:

  • 禁止显示警告(我计划在失败的情况下抛出自己的异常)
  • 从流中获取错误信息(至少是响应代码)
120679 次浏览

http://php.net/manual/en/reserved.variables.httpresponseheader.php

$context = stream_context_create(['http' => ['ignore_errors' => true]]);
$result = file_get_contents("http://example.com", false, $context);
var_dump($http_response_header);

Adding few more lines to the accepted response to get the http code

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);

to hide the error output both comments are ok, ignore_errors = true or @ (I prefer @)

@file_get_contents and ignore_errors = true are not the same: the first doesn't return anything; the second suppresses error messages, but returns server response (e.g. 400 Bad request).

I use a function like this:

$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;

It returns 200 (Ok) or 400 (Bad request).

It works perfectly and it's easier than cURL.

None of the answers (including the one accepted by OP) actually satisfy the two requirements:

  • suppress a warning (I'm planning to throw my own exception in case of failure)
  • obtain the error information (at least, the response code) from the stream

Here's my take:

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;
}

This will throw for a non-200 response, but you can easily work from there, e.g. add a simple Response class and return new Response((int) $status, $response); if that fits your use-case better.

For example, to do a JSON POST to an API endpoint:

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

Note the use of "ignore_errors" => true in the http context map - this will prevent the function from throwing errors for non-2xx status codes.

This is most likely the "right" amount of error-suppression for most use-cases - I do not recommend using the @ error-suppression operator, as this will also suppress errors like simply passing the wrong arguments, which could inadvertently hide a bug in calling code.

I go to this page with kind of a different issue, so posting my answer. My problem was that I was just trying to suppress the warning notification and display a customized warning message for the user, so this simple and obvious fix helped me:

// Suppress the warning messages
error_reporting(0);


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

And if needed, turn back error reporting after that:

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