POST-запрос к PHP7 с кусочной кодировкой не возвращает должным образом результат

Я отправляю запрос POST от клиента (проверено с помощью curl и пользовательский скрипт nodejs) и не вернут ответ должным образом. Все это прекрасно работает с PHP 5.6.

Среда

Все сводится максимально:

  • все работает внутри Vagrant VM Ubuntu 14.04 LTS
  • nginx 1.9.7 из http://nginx.org/packages/ubuntu/
  • PHP7 FPM скомпилирован из официальных источников с --disable-all --enable-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;
}
}

Пример PHP-скрипта из /vagrant/index.php:

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

curl call я использую: 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

Почему я слоняюсь по кусочкам?

Для этого нет никаких бизнес-причин, однако я использовал очень похожий код NodeJS, который по умолчанию использует чанкованное кодирование, которое внезапно перестало работать при переходе на PHP7.

Я нашел следующее, чтобы работать со стороны nodejs: явно установить Content-Length заголовок удаляет неявный Transfer-Encoding: chunked Заголовок отправляется NodeJS и, таким образом, работает с обеими версиями PHP.

Однако я хотел бы понять, почему PHP7 ведет себя здесь по-разному, и я ошибаюсь, или что на самом деле происходит здесь.

Обновление 1:

  • Я сравнил sapi/fpm/ источники между 5.6 и 7.0, и я почти не вижу разницы, кроме изменений из-за внутренних изменений 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&м = 145090900217798&W = 2

25

Решение

Из вашего поста я предполагаю, что вы используете PHP7.0.0. Если мое предположение (BOOL) ПРАВДА тогда я предлагаю вам перейти на PHP7.0.1.

PHP7.0.0 имеет примерно 27 ошибок которые были раздавлены в PHP7.0.1; среди других фиксированных предметов.
Источник: PHP.net changelog.

Я также посмотрел на ваш код PHP выше (с моими очками Google) но это смехотворно просто. Я сомневаюсь, что что-то может быть не так с этим. Хотя я предполагаю, что это связано с тем, как PHP7 ручки промывать() и выводы.

Более того:

Отмечая ваши обновления (особенно Обновление 1, а также Обновление 2); Я должен действительно похвалить вас там! Это очень впечатляет.
Не забудьте проверить эту исправленную ошибку # 61751. Если я был прав насчет вашей версии PHP, то эта исправленная ошибка могла бы решить вашу проблему; вам просто нужно перейти на PHP7.0.1.


НОТА: Я знаю, что я должен проверить внутреннюю часть исправленной ошибки, но …

1

Другие решения

Это / было ошибка в PHP7, которая была исправлена ​​совсем недавно https://github.com/php/php-src/pull/1745 . Он еще не опубликован ни в одном официальном релизе, но в конце концов появится там через некоторое время.

До вышеуказанного PR также сообщалось об ошибке, описывающей похожую проблему: https://bugs.php.net/bug.php?id=71466

0