6

There is a redirect to server for information and once response comes from server, I want to check HTTP code to throw an exception if there is any code starting with 4XX. For that I need to know how can I get only HTTP code from header? Also here redirection to server is involved so I afraid curl will not be useful to me.

So far I have tried this solution but it's very slow and creates script time out in my case. I don't want to increase script time out period and wait longer just to get an HTTP code.

Thanks in advance for any suggestion.

Community
  • 1
  • 1
CM.
  • 670
  • 1
  • 6
  • 25
  • 2
    cURL can follow redirects just fine. You could read it in the documentation instead of fearing your assumptions: http://php.net/manual/en/function.curl-setopt.php , look for `CURLOPT_FOLLOWLOCATION` – Piskvor left the building Sep 27 '11 at 08:33
  • I tried curl with CURLOPT_FOLLOWLOCATION option. Thing is it fetched a page to my local server and when I enter username/password on the page which I get from server, server gets confused in redirection. How to solve this? – CM. Sep 27 '11 at 17:15

3 Answers3

9

Your method with get_headers and requesting the first response line will return the status code of the redirect (if any) and more importantly, it will do a GET request which will transfer the whole file.

You need only a HEAD request and then to parse the headers and return the last status code. Following is a code example that does this, it's using $http_response_header instead of get_headers, but the format of the array is the same:

$url = 'http://example.com/';

$options['http'] = array(
    'method' => "HEAD",
    'ignore_errors' => 1,
);

$context = stream_context_create($options);

$body = file_get_contents($url, NULL, $context);

$responses = parse_http_response_header($http_response_header);

$code = $responses[0]['status']['code']; // last status code

echo "Status code (after all redirects): $code<br>\n";

$number = count($responses);

$redirects = $number - 1;

echo "Number of responses: $number ($redirects Redirect(s))<br>\n";

if ($redirects)
{
    $from = $url;

    foreach (array_reverse($responses) as $response)
    {
        if (!isset($response['fields']['LOCATION']))
            break;
        $location = $response['fields']['LOCATION'];
        $code = $response['status']['code'];

        echo " * $from -- $code --> $location<br>\n";
        $from = $location;
    }
    echo "<br>\n";
}

/**
 * parse_http_response_header
 *
 * @param array $headers as in $http_response_header
 * @return array status and headers grouped by response, last first
 */
function parse_http_response_header(array $headers)
{
    $responses = array();
    $buffer = NULL;
    foreach ($headers as $header)
    {
        if ('HTTP/' === substr($header, 0, 5))
        {
            // add buffer on top of all responses
            if ($buffer) array_unshift($responses, $buffer);
            $buffer = array();

            list($version, $code, $phrase) = explode(' ', $header, 3) + array('', FALSE, '');

            $buffer['status'] = array(
                'line' => $header,
                'version' => $version,
                'code' => (int) $code,
                'phrase' => $phrase
            );
            $fields = &$buffer['fields'];
            $fields = array();
            continue;
        }
        list($name, $value) = explode(': ', $header, 2) + array('', '');
        // header-names are case insensitive
        $name = strtoupper($name);
        // values of multiple fields with the same name are normalized into
        // a comma separated list (HTTP/1.0+1.1)
        if (isset($fields[$name]))
        {
            $value = $fields[$name].','.$value;
        }
        $fields[$name] = $value;
    }
    unset($fields); // remove reference
    array_unshift($responses, $buffer);

    return $responses;
}

For more information see: HEAD first with PHP Streams, at the end it contains example code how you can do the HEAD request with get_headers as well.

Related: How can one check to see if a remote file exists using PHP?

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • Related: [PHP: get_headers set temporary stream_context](http://stackoverflow.com/questions/8429342/php-get-headers-set-temporary-stream-context) – hakre Sep 01 '12 at 11:14
  • add user_agent in options $options['http'] = array( 'method' => "HEAD", 'user_agent'=> "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36", // Have to act as browser, or some servers reject 'ignore_errors' => 1, ); – Adam Pery Jun 04 '18 at 13:42
  • Hi Hakre, can you help me with related to your solution problem? https://stackoverflow.com/questions/50742294/http-response-code-after-redirect-to-non-ascii-domain-name – Adam Pery Jun 08 '18 at 06:35
6

Something like:

  $ch = curl_init(); 
  $httpcode = curl_getinfo ($ch, CURLINFO_HTTP_CODE );

You should try the HttpEngine Class. Hope this helps.

--

EDIT

$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, $your_agent_variable);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_REFERER, $your_referer);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpcode ...)
John Smith
  • 808
  • 3
  • 9
  • 20
  • sorry I am not aware of HttpEngine class. Can you provide me some info on that? – CM. Sep 27 '11 at 15:50
  • No problem. Well, i don't remember where I got this class... So I uploaded this one here: http://pastebin.ca/2083612 tell me if you need any help! – John Smith Sep 28 '11 at 06:57
  • I looked into class file but not sure how it is going to help here. It uses curl and using curl when I make CURLOPT_FOLLOWLOCATION to true for redirect, GET method is fetching whole page. – CM. Sep 28 '11 at 07:58
  • TIMEOUT is set but i guess that is not a problem in this case. – CM. Sep 28 '11 at 10:36
0

The solution you found looks good. If the server is not able to send you the http headers in time your problem is that the other server is broken or under very heavy load.

PiTheNumber
  • 22,828
  • 17
  • 107
  • 180