HTTP requests with file_get_contents, getting the response code
Solution 1
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);
Solution 2
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.
Solution 3
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 @)
georg
Hi, I'm Georg. I do mostly python (geodata / bigdata), (type | java)script and some (objective) C. work :: gws | datafeedr fun :: copytables | chartreux | slon | jadzia
Updated on July 08, 2022Comments
-
georg almost 2 years
I'm trying to use
file_get_contents
together withstream_context_create
to make POST requests. My code so far:$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);
It works fine, however, when an HTTP error occurs, it spits out a warning:
file_get_contents(...): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request
and returns false. Is there a way to:
- 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
-
georg about 11 yearsFor those wondering, the answer to the first question is to add
'ignore_errors' => TRUE
to$options
. -
Nico Haase almost 6 yearsAnd how does this solve the question? Can you explain how to get the response code?
-
Admin almost 6 years@Nico What do you think about my solution?
-
Nico Haase almost 6 yearsIt's still a bad one, as you parse a JSON result not and read a random field named
status
- it has no connection to the HTTP status code for the API call -
Admin almost 6 yearsIt's obvious that the RESTful API I connect to returns a JSON response and that what I need to know for my purpose (200 or 400) is contained in the "status" field. That's all I need and that's all I get. If you need to know the HTTP status code, just do this: return $http_response_header[0]; But note that it doesn't work with @file_get_contents.
-
Nico Haase almost 6 yearsAnd how does this answer the original question? Why do you think that
$http_response_header[0]
, a highly upvoted answer, does not work withfile_get_contents
? -
Admin almost 6 yearsIt doesn't work with @file_get_contents (NOT with file_get_contents). Just try it!
-
MLK.DEV almost 5 years@Besen the
->status
is not always an option as it's not part of the spec. That is a property being exposed by whatever stream you are tapping as a courtesy (which is nice) but not standard. If the stream does not explicitly define this property your answer does not provide a viable solution. -
at54321 almost 3 yearsThat's great! But I wonder: isn't there a less-hacky way to directly get the status code as an integer value?
-
mindplay.dk almost 3 years@at54321 not with
file_get_contents
, that's how it was designed (back in the deep, dark ages of PHP) but in my own client I ended up usingfopen
instead, which avoids this weird, magical API - you can see here how to do that. -
GPHemsley over 2 yearsDocumentation for $http_response_header, which does indeed materialize itself after the call to file_get_contents().
-
Liglo App about 2 years"$http_response_header materializes out of thin air" deserves an upvote, PHP for allowing this a downvote for the language design.
-
mindplay.dk about 2 years@LigloApp "language design" 😂
-
Your Common Sense almost 2 years@FluorescentGreen5 with your recommendation you are ruining many programmers experience. Please do not recommend anything that will result in the very bad experience.