HTTP requests with file_get_contents, getting the response code

PhpFileHttpStream

Php Problem Overview


I'm trying to use file_get_contents together with stream_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

Php Solutions


Solution 1 - Php

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

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

Solution 2 - Php

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 - Php

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

Solution 4 - Php

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

Solution 5 - Php

@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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongeorgView Question on Stackoverflow
Solution 1 - PhpAllesView Answer on Stackoverflow
Solution 2 - Phpmindplay.dkView Answer on Stackoverflow
Solution 3 - Phphamboy75View Answer on Stackoverflow
Solution 4 - PhpKaarelView Answer on Stackoverflow
Solution 5 - PhpBesenView Answer on Stackoverflow