Make HTTP/2 request with PHP
Asked Answered
P

1

11

Is there a way to force PHP to make a HTTP2 connection to another server just to see if that server supports it?

I've tried:

$options = stream_context_create(array(
               'http' => array(
                    'method' => 'GET',
                    'timeout' => 5,
                    'protocol_version' => 1.1
                )
              ));
$res = file_get_contents($url, false, $options);
var_dump($http_response_header);

And tried:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTP_VERSION, 3);
$response = curl_exec($ch);
var_dump($response);
curl_close($ch);

But both ways give me a HTTP1.1 response if I use the following URL https://www.google.com/#q=apache+2.5+http%2F2

I'm sending the request from a HTTP/2 + SSL enabled domain. What am I doing wrong?

Pastorship answered 10/5, 2016 at 14:0 Comment(3)
which version of php are you using ? take a look here blog.cloudflare.com/…Volvox
have you tried: This AnswerSchlicher
is your libcurl version built to support HTTP/2?Gangplank
P
17

As far as I'm aware, cURL is the only transfer method in PHP that supports HTTP 2.0.

You'll first need to test that your version of cURL can support it, and then set the correct version header:

if (
    defined("CURL_VERSION_HTTP2") &&
    (curl_version()["features"] & CURL_VERSION_HTTP2) !== 0
) {
    $url = "https://www.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,
    ]);
    $response = curl_exec($ch);
    if ($response !== false && str_starts_with($response, "HTTP/2")) {
        echo "HTTP/2 support!";
    } elseif ($response !== false) {
        echo "No HTTP/2 support on server.";
    } else {
        echo curl_error($ch);
    }
    curl_close($ch);
} else {
    echo "No HTTP/2 support on client.";
}
Pretrice answered 10/5, 2016 at 18:45 Comment(10)
Depending on your platform/versions, it might need a few tweaks to get it done, as it did with me: [https://mcmap.net/q/1016335/-php-7-1-no-curl-with-http-2]Krissie
Any ideas why CLI requests such as curl --http2 -I https://nghttp2.org/ do work in HTTP2 mode but when switching to PHP, they are sent as HTTP 1.1 instead? I've tested your code and it still doesn't work in HTTP2 mode. I have PHP 5.6 and curl 7.54.Spittle
@Andrew Because the curl you’re using in the command line isn’t necessarily the same on that’s complied into PHP for its curl support.Pretrice
The minor version (2.0) was dropped from HTTP2. http2.github.io/faq/#is-it-http20-or-http2Fusion
Thanks for the edit @Ryre. This code will, of course, continue to work with older servers still sending "2.0" as well.Pretrice
The first line of this answer doesn't work. Should be if ( !empty(@constant('CURL_VERSION_HTTP2')) ) {Patriciate
@Patriciate 1) the constant can be defined without the feature being available 2) don't use the error suppression operator, it's an ugly hack; use defined() to test 3) if you're running a PHP version so old that the constant isn't defined, you've got bigger problems than an undefined constant notice.Pretrice
I would suggest trying your code out on a client server that does not support HTTP/2, and you will see that it does not work. My correction does work. This isn't a function of old PHP, but old Apache -- which is much more common than Apache which supports HTTP/2.Patriciate
Well, don't know what to tell you. Running this on my server with PHP 7.3 results in this: Warning: Use of undefined constant CURL_VERSION_HTTP2 - assumed 'CURL_VERSION_HTTP2' (this will throw an Error in a future version of PHP) in /home/server/public_html/test.php on line 10 Warning: Use of undefined constant CURL_HTTP_VERSION_2_0 - assumed 'CURL_HTTP_VERSION_2_0' (this will throw an Error in a future version of PHP) in /home/server/public_html/test.php on line 18 No HTTP/2 support on server. At the very least, indicating that it didn't trigger the "else" clause.Patriciate
@Patriciate ok when in doubt, go to the source. It looks like I was wrong about the constant always being defined; there is a version check on the library done before the constant is defined. You can check your server's version with echo curl_version()['version'];. I've updated the code to check for the constant. Thanks for pushing back!Pretrice

© 2022 - 2024 — McMap. All rights reserved.