php - 使用分块编码对 PHP7 的 POST 请求无法正确返回结果

标签 php chunked-encoding php-7

我正在从客户端发送 POST 请求(使用 curl 和自定义 nodejs 脚本进行测试)并且没有正确返回响应。整个过程适用于 PHP 5.6。

环境

尽可能减少整个事情:

  • 在 Vagrant VM Ubuntu 14.04 LTS 中运行的一切
  • nginx 1.9.7 来自 http://nginx.org/packages/ubuntu/
  • 使用 --disable-all --enable-fpm 从官方来源编译的 PHP7 FPM

我正在使用的最小 nginx 站点配置:

server {
  listen 80;
  server_name localhost;
  location / {
    fastcgi_param REQUEST_METHOD $request_method;
    fastcgi_pass  unix:/var/run/php/php7.0-fpm-api.sock;
    fastcgi_param SCRIPT_FILENAME /vagrant/index.php;
  }
}

/vagrant/index.php 中的示例 PHP 脚本:

<?php
echo str_repeat('.', 512);
flush(); // not necessary, only due testing

我正在使用的 curl 调用:curl -XPOST http://localhost/-H "Transfer-Encoding: chunked"-d ''

我正在使用的 NodeJS 脚本:

'use strict';

var http = require('http');
var url = require('url');

var uri = url.parse(process.env.URL);
var options = {
  method: 'POST', protocol: uri.protocol, hostname: uri.hostname,
  port: uri.port, path: uri.path,
};
var data = '';

var httpRequest = http.request(options, function(res) {
    res.on('data', function(chunk) {
      console.log('received data', chunk.length);
      data += chunk;
    });
    res.on('end', function() { console.log('final size', data.length); });
  })
  .on('error', function(err) { console.log(err); });

httpRequest.write('');
httpRequest.end();

将我的测试请求发送到 PHP 5.6

$ curl http://localhost/
..........[cut off]

$ curl -XPOST http://localhost/ -H "Transfer-Encoding: chunked" -d ''
..........[cut off]

$ URL=http://localhost/ node php7test.js
received data 512
final size 512

将我的测试请求发送到 PHP 7.0

$ curl http://localhost/
..........[cut off]

$ URL=http://localhost/ node php7test.js
final size 0

$ curl -XPOST http://localhost/ -H "Transfer-Encoding: chunked" -d ''
curl: (18) transfer closed with outstanding read data remaining

为什么我要搞乱 block 编码?

没有商业理由这样做,但是我使用了一个非常相似的 NodeJS 代码,它默认为分 block 编码,当切换到 PHP7 时突然停止工作。

我发现以下方法可以从 nodejs 端工作:显式设置 Content-Length header 会删除 NodeJS 发送的隐式 Transfer-Encoding: chunked header ,并且因此适用于两个 PHP 版本。

但是我想了解为什么 PHP7 在这里的行为不同,以及我是否有误或者这里到底发生了什么。

更新 1:

  • 我比较了 5.6 和 7.0 之间的 sapi/fpm/ 源代码,除了 PHP 内部更改导致的更改外,我几乎看不出任何区别
  • 内置服务器(php -S)不受影响,所有测试

更新 2:

我将 PHP 源代码一分为二,并能够查明行为何时发生变化:

在两者之间,git bisect 的输出,我无法编译的提交:

$ git bisect skip
There are only 'skip'ped commits left to test.
The first bad commit could be any of:
ba5ecf355fe792a5a2a8e6582d5e081d02b16fbf
e383cb4493031a7cd952cfcaed3297e583149c07
fef18f4bea1980a59a9283c2197bd090aaf500cb
18cf4e0a8a574034f60f4d123407c173e57e54ec
We cannot bisect more!

感觉这可能是一个错误,我将其写给内部人员,也许他们有一些见解:https://marc.info/?l=php-internals&m=145090900217798&w=2

最佳答案

根据您的帖子,我猜您使用的是 PHP7.0.0。如果我的猜测是 (bool) TRUE 那么我会建议您迁移到 PHP7.0.1

PHP7.0.0 有大约 27 个错误,这些错误在 PHP7.0.1 中被消除;
来源:PHP.net changelog .


我还查看了您上面的 PHP 代码(戴着我的谷歌眼镜),但它非常简单。我怀疑它有什么问题。尽管我猜测这与 PHP7 处理 flush() 和输出的方式有关。


此外:

注意您的更新(特别是更新 1更新 2);我真的必须在那里表扬你! 这非常令人印象深刻。 请务必查看此已修复的错误 #61751 .如果我对您的 PHP 版本的判断是正确的,那么这个已修复的错误可能已经解决了您的问题;您只需要迁移到 PHP7.0.1



注意: 我知道我应该检查已修复错误的内部结构,但是......

关于php - 使用分块编码对 PHP7 的 POST 请求无法正确返回结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34440220/

相关文章:

javascript - 未捕获的类型错误 : Cannot read property 'mData' of undefined

php - 单击“保存”按钮数据未插入到 Android 数据库中

nginx - 启用Nginx分块传输编码

java - HTTP 分块传输

ubuntu - XDebug 无法打开远程调试文件 '/var/log/xdebug/xdebug.log'?

php ajax评论系统不起作用查询不插入任何内容

php - AWS SWF 关闭事件未发送至决策程序

javascript - 如何修复 Process 类依赖于 proc_open,该类在您的 PHP 安装中不可用

PHP 文件服务脚本 : Unreliable Downloads?

php - 类型声明和类型注释是过时的还是相互补充的?