11

This is my code

$url = 'http://www.wikipedia.com';  // URL WITH HTTP
$hurl = str_replace("http", "https", $url); // URL WITH HTTPS

$urlheads = get_headers($url, 1);   
$surlheads = get_headers($hurl, 1);     
$urlx = false;
$surlx = false;

foreach ($urlheads as $name => $value) 
{
    if ($name === 'Location') 
    {
        $urlx=$value;   
    }
    else{

    }
}
print_r($urlx);

And this is error I'm getting:

Warning: get_headers(): Peer certificate CN=`*.wikipedia.org' did not match expected CN=`www.wikipedia.com' in....

Warning: get_headers(): Failed to enable crypto in....

Warning: get_headers(https://www.wikipedia.com): failed to open stream:     operation failed in .....
Array ( [0] => http://www.wikipedia.org/ [1] => https://www.wikipedia.org/ )

Why is this happening and what is proper way to get headers from https page without errors (without curl). Also, when I try on some other https site everything is ok

1 Answer 1

31

The issue is down to the server certificate being presented as a wildcard * so it can allow all sub-domains under the same certificate, but for some strange reason the wildcard * is used literally during the SSL verify leading to failure. To get around this, use stream_context_set_default() to set the SSL verification as false.

stream_context_set_default( [
    'ssl' => [
        'verify_peer' => false,
        'verify_peer_name' => false,
    ],
]);

$url = 'https://www.wikipedia.com';  // URL WITH HTTPS

$headers = get_headers($url, 1);

var_dump($headers);

Output

array(25) {
    [0] => string(30)
    "HTTP/1.1 301 Moved Permanently" ["Date"] => array(2) {
        [0] => string(29)
        "Sun, 27 Nov 2016 15:44:44 GMT" [1] => string(29)
        "Sun, 27 Nov 2016 15:44:44 GMT"
    }["Content-Type"] => array(2) {
        [0] => string(29)
        "text/html; charset=iso-8859-1" [1] => string(9)
        "text/html"
    }["Content-Length"] => array(2) {
        [0] => string(3)
        "234" [1] => string(5)
        "80740"
    }["Connection"] => array(2) {
        [0] => string(5)
        "close" [1] => string(5)
        "close"
    }["Server"] => array(2) {
        [0] => string(18)
        "mw1174.eqiad.wmnet" [1] => string(18)
        "mw1175.eqiad.wmnet"
    }["X-Powered-By"] => array(2) {
        [0] => string(17)
        "HHVM/3.3.0-static" [1] => string(17)
        "HHVM/3.3.0-static"
    }["Location"] => string(26)
    "https://www.wikipedia.org/" ["Cache-Control"] => array(2) {
        [0] => string(15)
        "max-age=2592000" [1] => string(45)
        "s-maxage=86400, must-revalidate, max-age=3600"
    }["Expires"] => string(29)
    "Wed, 21 Dec 2016 14:55:26 GMT" ["Vary"] => array(2) {
        [0] => string(34)
        "X-Forwarded-Proto, Accept-Encoding" [1] => string(15)
        "Accept-Encoding"
    }["X-Varnish"] => array(2) {
        [0] => string(60)
        "252832401 234761536, 189834925 105479673, 503055844 58285403" [1] => string(57)
        "815608054 810788132, 143499750 28230570, 504104889 557059"
    }["Via"] => array(2) {
        [0] => string(46)
        "1.1 varnish-v4, 1.1 varnish-v4, 1.1 varnish-v4" [1] => string(46)
        "1.1 varnish-v4, 1.1 varnish-v4, 1.1 varnish-v4"
    }["Age"] => array(2) {
        [0] => string(6)
        "521357" [1] => string(5)
        "59119"
    }["X-Cache"] => array(2) {
        [0] => string(41)
        "cp1053 hit/4, cp3032 hit/9, cp3030 hit/17" [1] => string(46)
        "cp1054 hit/8, cp3032 hit/33, cp3030 hit/531848"
    }["X-Cache-Status"] => array(2) {
        [0] => string(3)
        "hit" [1] => string(3)
        "hit"
    }["Set-Cookie"] => array(4) {
        [0] => string(88)
        "WMF-Last-Access=27-Nov-2016;Path=/;HttpOnly;secure;Expires=Thu, 29 Dec 2016 12:00:00 GMT" [1] => string(76)
        "GeoIP=GB:WLS:Ammanford:51.79:-3.99:v4; Path=/; secure; Domain=.wikipedia.com" [2] => string(88)
        "WMF-Last-Access=27-Nov-2016;Path=/;HttpOnly;secure;Expires=Thu, 29 Dec 2016 12:00:00 GMT" [3] => string(76)
        "GeoIP=GB:WLS:Ammanford:51.79:-3.99:v4; Path=/; secure; Domain=.wikipedia.org"
    }["X-Analytics"] => array(2) {
        [0] => string(19)
        "https=1;nocookies=1" [1] => string(19)
        "https=1;nocookies=1"
    }["X-Client-IP"] => array(2) {
        [0] => string(13)
        "81.129.193.46" [1] => string(13)
        "81.129.193.46"
    }[1] => string(15)
    "HTTP/1.1 200 OK" ["ETag"] => string(23)
    "W/"
    13 b64 - 541e8 ad5dab71 "" ["Last-Modified"] => string(29)
    "Tue, 22 Nov 2016 19:21:20 GMT" ["Backend-Timing"] => string(24)
    "D=213 t=1479943165198824" ["Strict-Transport-Security"] => string(44)
    "max-age=31536000; includeSubDomains; preload" ["Accept-Ranges"] => string(5)
    "bytes"
}
Sign up to request clarification or add additional context in comments.

3 Comments

This is such a weird problem. It started happening on one of my own servers and domains after a certificate update. I thought it was specific to my domain until I found this, and sure enough Wikipedia also fails. However, this only happens on one specific box, others (with different PHP versions) work fine. I'd really like to get to the bottom of this.
This answer is close, but also quite far - doing that will make any further HTTPS calls insecure! DON'T DO THAT Use stream_context_create instead of stream_context_set_default and pass the returned context to get_headers or whichever function you want.
To be fair: the $context argument was added to get_headers() in PHP 7.1. You could use try..finally to avoid the aforementioned problems though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.