Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect if a site supports HTTP/2 in PHP

Is there a simple way in PHP to test if a URL supports HTTP/2? I tried checking for connection upgrade or h2 in curl_setopt($curl, CURLOPT_HEADER, true) as per HTTP/2 identification in the specs . There are many sites where you can add a URL and it will tell if the site supports HTTP/2 or not. Just wondering how they are testing it and if something similar can be done in PHP. On command line I can do something like $ curl -vso --http2 https://www.example.com/

like image 827
Vinit Avatar asked Nov 17 '17 18:11

Vinit


People also ask

How can I tell if http 2 is supported?

Google Chrome offers a quick and easy way to check if HTTP/2 is supported on your SSL-enabled site. First, visit your site in Chrome over HTTPS. There you'll see your site listed with protocol h2, confirming your site works over HTTP/2.

Does PHP support http2?

From now, we also support HTTP/2 with PHP, this is not for your web site loading but for PHP to perform HTTP/2 requests to remote servers via cURL functionality. This will add another layer of protection and also speedup the process using the next generation http protocol.

Is http 2 enabled by default?

HTTP/2 is enabled by default and requires an SSL certificate at Cloudflare's edge network. Configure HTTP/2 and HTTP/3 via the Cloudflare Network app. Domains on Free plans cannot disable HTTP/2. A browser and web server automatically negotiate the highest protocol available.


1 Answers

Update 2021-02-25:
As mentioned by djdance, HTTP/2.0 has been HTTP/2 for some time now. Therefore, you should really check against HTTP/2 (and HTTP/3 for the upcoming HTTP 3).

If you do not want to use strpos, you can now also use str_starts_with($response, "HTTP/2") when using PHP 8. Otherwise you can use substr($response, 0, 6) === "HTTP/2" for PHP 7.

For PHP 7.3 and cURL 7.50.0, curl_getinfo now also supports CURLINFO_HTTP_VERSION:

echo curl_getinfo($ch, CURLINFO_HTTP_VERSION);
// 3 for HTTP/2

The values which may be returned by CURLINFO_HTTP_VERSION (as of PHP 7.3):

CURL_HTTP_VERSION_NONE              === 0
CURL_HTTP_VERSION_1_0               === 1
CURL_HTTP_VERSION_1_1               === 2
CURL_HTTP_VERSION_2                 === 3
CURL_HTTP_VERSION_2_0               === 3
CURL_HTTP_VERSION_2TLS              === 4
CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE === 5

This means you can check for a specific (e.g., CURL_HTTP_VERSION_2TLS, which is HTTP/2 over TLS):

if (
    $response !== false
    && curl_getinfo($ch, CURLINFO_HTTP_VERSION) === CURL_HTTP_VERSION_2TLS
) {
    // The connection was established using HTTP/2 over TLS
    // if the server does not support TLS HTTP/1.1 will be used.
}

Original:
Both your server and your installation of cURL need to support HTTP/2.0. After that you can just make a normal cURL request and add the CURLOPT_HTTP_VERSION parameter which will make cURL try to make an HTTP/2.0 request. After that you'll have to check the Headers from the request to check if the server does indeed support HTTP/2.0.

Example:

$url = "https://google.com";
$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL            => $url,
    CURLOPT_HEADER         => true,
    CURLOPT_NOBODY         => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_2_0, // cURL will attempt to make an HTTP/2.0 request (can downgrade to HTTP/1.1)
]);
$response = curl_exec($ch);

Now you'll need to check if cURL did indeed make an HTTP/2.0 request:

if ($response !== false && strpos($response, "HTTP/2.0") === 0) {
    echo "Server of the URL has HTTP/2.0 support."; // yay!
} elseif ($response !== false) {
    echo "Server of the URL has no HTTP/2.0 support."; // nope!
} else {
    echo curl_error($ch); // something else happened causing the request to fail
}
curl_close($ch);
like image 159
Tom Udding Avatar answered Sep 18 '22 13:09

Tom Udding