【问题标题】:PHP: How to read POST body with Transfer-Encoding: chunked, no Content-LengthPHP:如何使用 Transfer-Encoding 读取 POST 正文:分块,无 Content-Length
【发布时间】:2015-09-04 14:27:08
【问题描述】:

我正在编写一个服务来接收来自我家中的能源监控设备的数据。设备可以推送数据的唯一方法是使用 HTTP POST,使用Transfer-Encoding: chunked,而不使用Content-Length,并将数据作为请求正文中的 XML。

我希望能够在 PHP 脚本(在 Apache 之后)中读取这些数据并将其存储在我的数据库中。

现在看来,在 PHP 中读取 HTTP 请求正文的最正确方法是打开并读取 php://input。但是,来自 PHP 网站用户的 cmets 表明(并且我的测试证实),如果客户端未指定 Content-Length 标头,php://input 不会返回任何数据(即使客户端以分块编码发送数据) .

是否有其他方法可以访问请求正文?我可以配置 Apache(使用 .htaccess)来解码分块数据并在获得所有数据后调用我的脚本,并包含Content-Length?或者配置 PHP 让它能够处理这个问题?

谢谢!

【问题讨论】:

  • 什么版本的 PHP?我记得这是特定于 fastCGI 实现而不是 mod_php。从技术上讲,它们遵循 HTTP 1.1 规范。对于 mod_fcgid,您可以查看 patch。参考:bugs.php.net/bug.php?id=60826
  • 啊,我正在使用 PHP 5.6.5 和 FastCGI。我将尝试更改为非快速 CGI(我的网络主机让我选择),看看会发生什么;我会尽快回来报告。

标签: php apache http-headers


【解决方案1】:

不妨把这个写成我想的答案。

您描述的问题记录在这里:https://bugs.php.net/bug.php?id=60826

主题亮点:

这就是我发现的。如果您发送分块的 http 请求但不发送 发送内容长度(我们应该使用 HTTP 1.1 协议) 请求的正文部分为空(php://input 不返回任何内容)。这 结果对于 PHP 运行的以下配置仍然有效 通过 FastCGI:

与运行为 mod_php 的 PHP 相同的配置就可以了,正文 可以通过 php://input 获取请求。

本质上,PHP 遵循规范,而不是超出规范 FastCGI CONTENT_LENGTH 标头值 - 所以正确的修复是 必须高于 PHP,在 FastCGI 或 web 服务器实现中。

可能的解决方法:

0) 将 httpd 与 mod_php 一起使用

1) 使用不同的网络服务器。

2) 查看 mod_fcgid 的补丁

3) 可能(不推荐)翻转always_populate_raw_post_data 看看$HTTP_RAW_POST_DATA 中是否有任何内容

【讨论】:

  • 谢谢。我的网络主机(Dreamhost)让我在选择用于域的 PHP 版本时在“CGI”和“FastCGI”之间切换,所以我将它切换到 CGI(它是 FastCGI),但 php://input 似乎仍然没有包含任何东西。
  • 是的。不幸的是,两个主要的(称为处理程序)是 CGI(通用网关接口)或 DSO(动态共享对象)。 fastCGI 和 CGI​​ 都会受到该问题的影响。如果选择 CGI 和 fastCGI,请使用 fastCGI。据我了解,您需要将 mod_php (DSO)与 apache 一起使用,或者使用另一个服务器,比如 nginx ......或者也许 patched mod_fcgid 与 apache 一起使用。
  • 好的,谢谢。由于这些都不是我的共享主机帐户上的选项,因此我将不得不找出其他方法。感谢您的帮助,我会将您的答案标记为已接受,以防其他人遇到此问题。
猜你喜欢
  • 1970-01-01
  • 2019-05-15
  • 2021-04-13
  • 2019-09-22
  • 2014-02-10
  • 2016-11-05
  • 2012-10-06
  • 1970-01-01
相关资源
最近更新 更多