如何在 PHP 中发送 HTTP/2 POST 请求

Posted

技术标签:

【中文标题】如何在 PHP 中发送 HTTP/2 POST 请求【英文标题】:How do I send a HTTP/2 POST request in PHP 【发布时间】:2016-04-08 23:44:53 【问题描述】:

我在Sending HTTP/2 POST request in Ruby 发现了一个类似的问题 但我想用 php 更新我的服务器

此处描述的新 Apple 推送通知基于 HTTP/2 的 API:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/APNsProviderAPI.html

任何具有 HTTP/2 经验的人都可以帮助我以 PHP 客户端的身份发出请求。

【问题讨论】:

【参考方案1】:

查看我为此目的构建的 Apache 和 CLI PHP Docker 映像,它们将 HTTP/2 支持添加到官方 PHP 5.6 docker 库中。这消除了任何HTTP/2 client preface string missing or corrupt 错误。

一旦你有了合适的环境,在尝试了几个 PHP 的 JWS/JWT 库后,我发现 Spomky-Labs/jose 可以完美地与 APN 配合使用。

【讨论】:

【参考方案2】:

PHP >= 5.5.24 的 CURL 扩展支持 HTTP/2。 (自this commit)

您还需要安装 libcurl(curl 函数使用的底层库)并启用 HTTP/2 支持。这意味着比 7.38.0 更新的 libcurl,但实际上,越新越好。 Libcurl 必须在编译时使用 --with-nghttp2 标志显式启用 HTTP/2 支持。

只需像通常使用的那样使用 curl,并通过传入 CURL_HTTP_VERSION_2_0CURLOPT_HTTP_VERSION 选项设置为使用 HTTP/2。然后你将把请求升级到版本 2如果客户端和服务器都支持它。

在 PHP 5.5.24 之前,如果 libcurl 构建时支持 HTTP/2,您可以显式传入 CURL_HTTP_VERSION_2_0 的 int 值,因为 PHP 仍会将其传递给 libcurl。目前,它的值为3——这不应该改变,但可以

if (!defined('CURL_HTTP_VERSION_2_0')) 
    define('CURL_HTTP_VERSION_2_0', 3);


$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);

【讨论】:

我尝试在 Mac 和 Linux 上安装 XAMPP 的 5.6.21 和 7.0.6 版本,但我总是收到此错误:HTTP/2 client preface string missing or corrupt. Hex dump for received bytes ...。你知道我怎么能解决这个问题吗?我可以从命令行发送推送通知,但在 PHP 中它不起作用。 我想了解使用 HTTP/2 和 curl 7.38.0 的推送通知是否可以在共享主机环境中工作?由于安全原因,以前的共享主机提供商会阻止端口 2195 和 2196,因此无法使用 TCP 套接字进行推送通知。 @raj:这是一个完全独立的问题,不适合对答案发表评论...... 这还需要 openSSL 1.0.2,尽管 1.0.1 现在已经 5 年了,而且还在继续,但它在 centOS 6 上无法通过 yum 更新获得。【参考方案3】:

PHP >= 5.5.24 不足以使用 curl 发出 HTTP/2 请求,即使定义了 CURL_HTTP_VERSION_2_0 也是如此。如果您尝试向 APNS(Apple Push Notification Service)发出请求,您将收到如下错误消息:

?@@?HTTP/2 client preface string missing or corrupt. Hex dump for received bytes: 504f5354202f332f6465766963652f616538666562613534

由于 curl 是 libcurl 的 binding,因此您还必须启用 curl 并启用 http/2。

有关示例代码,请参阅我的 answer 以了解关于 SO 的类似问题

安装步骤,可以参考tutorial

【讨论】:

谢谢!这行得通。虽然我使用CURLINFO_HEADER_OUT 检查了请求标头,但它显示HTTP/1.1。但它现在可以工作了,以前没有工作过。 我有 PHP 5.6、curl 7.54(支持 HTTP2)和 OpenSSL 1.0.1 但 CURL_HTTP_VERSION_2_0 仍然未定义,有什么想法吗? Apple 在尝试连接时返回 Unexpected HTTP/1.x request 错误消息。 @Andrew 检查您的 curl OpenSSL 版本是否高于 1.0.1。我最终不必要地重新编译了我的 PHP 版本,最终发现 Apple APN 需要一个从不版本的 TLS。 @andreszs 我遇到了同样的问题,直到我用sudo apachectl restart重新启动了apache【参考方案4】:

目前 PHP 中没有直接的 HTTP/2 支持。

有一个想法可以在未来直接向 PHP 添加这样的支持: https://wiki.php.net/ideas/php6#http2_support

第 3 方库 Guzzle https://github.com/guzzle/guzzle 支持 HTTP/2,如果安装了正确的 php 和 curl 版本:

use GuzzleHttp\Client;

$client = new Client();
$client->get('https://http2.akamai.com/demo/tile-0.png', [
    'version' => 2.0,
    'debug' => true,
]);

【讨论】:

以上是关于如何在 PHP 中发送 HTTP/2 POST 请求的主要内容,如果未能解决你的问题,请参考以下文章

在 Ruby 中发送 HTTP/2 POST 请求

在Ruby中发送HTTP / 2 POST请求

如何防止用户向 php 文件发送如此多的 post 请求

如何将 POST 数据发送到 PHP 中的另一个会话?

如何使用 PHP 发送 POST 请求?

如何使用 POST 将字符串发送到 php [重复]