【问题标题】:PHP 7.1: no cURL with HTTP/2PHP 7.1:没有使用 HTTP/2 的 cURL
【发布时间】:2017-12-12 05:45:37
【问题描述】:

我的问题不是要找出服务器是否支持 HTTP/2(他们都支持),而是如何确保 PHP 使用 HTTP/2 以及 CentOS 中最新 PHP 版本的正确 cURL 设置(从 Remi 的存储库构建)。我自己的回答解决了一些与此相关的奇怪问题。

借助以下精美指南,我已将 CentOS 7 服务器设置为支持 HTTP/2:Setting up HTTP/2 on your web server

所以我已经获得了最新版本,编译并安装了它们,一切正常。页面提供 HTTP/2 标头,完全符合其应有的要求。

现在我想在我的 PHP 脚本中使用 HTTP/2 功能。主要是通过以 HTTP/2 方式进行 cURL 调用。我发现我需要升级 libcurl 并使用特定的 HTTP/2 支持构建和编译它。经历了一些挫折,我得到了它的工作。

所以curl -V 告诉我:

curl 7.55.0-DEV (x86_64-unknown-linux-gnu) libcurl/7.55.0-DEV OpenSSL/1.1.0f zlib/1.2.7 nghttp2/1.23.1
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 
Features: IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy 

太棒了!

phpinfo() 为我提供了与新安装的 OpenSSL 相同的版本 (7.55.0-DEV),即:

OpenSSL 1.1.0f 25 May 2017

还有 Apache,顺便说一句:

Server version: Apache/2.4.26 (Unix)
Server built:   Jul  7 2017 09:47:22

但是,当我编写一个带有 cURL 调用并将 CURLOPT_HTTP_VERSION 选项设置为 CURL_HTTP_VERSION_2_0 的简单 PHP 脚本时,如本示例中所述:https://stackoverflow.com/a/37146586/1005334,它告诉我服务器不支持 HTTP/2 ...

这怎么可能?

我注意到的一件事是,phpinfo() 中关于 OpenSSL 模块的部分仍然提到了我的旧 OpenSSL 版本(OpenSSL 1.0.1e-fips),尽管 cURL 模块中提到的 OpenSSL 版本声明了 OpenSSL 1.1.0f。

我已经从 Remi 的存储库安装了 PHP 7.1(它目前的版本是 7.1.7),它是不是针对旧的 OpenSSL 版本构建的,所以它不能与我的新版本一起使用?我还阅读了 PHP 7 中对 HTTP/2 的支持不是很明显,但我想这应该不是问题,对吧?

或者 OpenSSL 不是问题,我应该看看别处,也许从源代码编译 PHP 并带有一些预期的标志?

【问题讨论】:

标签: curl libcurl centos7 php-openssl php-7.1


【解决方案1】:

经过一番摆弄,我似乎可以通过使用 Remi 的 PHP 包和新构建的 cURL/OpenSSL 调用 PHP cURL 获得 HTTP/2 响应。

我正在使用这段代码进行测试(取自here):

if (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 && strpos($response, "HTTP/2.0") === 0) {
        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.";
}

所需的调整是:

CURLOPT_HTTP_VERSION => 3

...和:

if ($response !== false && strpos($response, "HTTP/2") === 0)

因此,我在 cURL 选项中使用 3,而不是 CURL_HTTP_VERSION_2_0 作为 HTTP 版本,这应该意味着相同,但显然 PHP 在使用 CURL_HTTP_VERSION_2_0 时没有获取正确的值。

查看这给出的原始响应,我注意到 Google 发回的是 HTTP/2 而不是 HTTP/2.0

我希望这可以帮助别人!

【讨论】:

    【解决方案2】:

    我的存储库中的包是针对标准基础存储库构建的,因此 OpenSSL 1.0.1e 和 Curl 7.29.0(使用 NSS)。

    所以你必须重建所有使用这些库的东西以利用新功能(包括 PHP)

    【讨论】:

    • 我正在考虑它,但希望没有必要,因为我已经使用了 Apache、cURL 和 OpenSSL。但是,似乎可以做到(请参阅我对自己问题的回答)。
    猜你喜欢
    • 1970-01-01
    • 2016-07-25
    • 2015-12-19
    • 2014-11-16
    • 2012-04-01
    • 2023-03-08
    • 2019-03-20
    • 1970-01-01
    • 2016-04-07
    相关资源
    最近更新 更多