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

1

12

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/

Bluefield answered 17/11, 2017 at 18:56 Comment(0)
R
20

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);
Rectocele answered 21/11, 2017 at 11:13 Comment(3)
pay attention, this URL (google.com) is answering by "HTTP/2" (without point-zero), so crop it from strposKoerner
@Koerner Thanks for letting me know! I have updated the answer to reflect this and changes in the latest PHP versions, as you can now use curl_getinfo() to check the HTTP version the request used.Rectocele
You are a star. all of a sudden none of the API request for the API key in the header ere being recognised, so after reading your post, I realised we were checking for API key with upper case, so revised my code to check for both and worked again. A+++Drawing

© 2022 - 2024 — McMap. All rights reserved.