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, который я использую: 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&m=145090900217798&w=2


person mark    schedule 23.12.2015    source источник
comment
Вы используете последнюю версию curl? Вы пробовали с Apache? Я запускал его с PHP 7.0.0 (хотя 7.0.1 только что вышел), curl (7.43.0) и Apache (2.4.16). Без вопросов.   -  person Clay    schedule 24.12.2015
comment
У меня нет апача и нет опыта, так что нет, нет апача. Я разделил исходники git и смог определить, когда изменилось поведение. Обновлю пост в ближайшее время. Я не беспокоился о другой версии curl, потому что поведение скриптов NodeJS тоже изменилось, что привело меня к выводу, что это не проблема на стороне клиента как таковая.   -  person mark    schedule 24.12.2015
comment
Вы уже сообщили об ошибке на bugs.php.net? Если нет, я бы сделал это сейчас. Это определенно кажется ошибкой, и я не продвинулся дальше, чем вы, копаясь в истории Git. Во-первых, убедитесь, что он все еще не работает в последних коммитах.   -  person Will    schedule 03.01.2016
comment
Я послал в список рассылки, но так как я еще не получил там ответа (плохая идея во время праздников, я думаю), я в конечном итоге сделаю это позже на этой неделе. Спасибо за ваше время и поддержку!   -  person mark    schedule 04.01.2016
comment
Эта ошибка все еще присутствует в версиях PHP7.3 FPM: stackoverflow.com/questions/54444220/   -  person Yahya Uddin    schedule 30.01.2019


Ответы (2)


Судя по вашему сообщению, вы используете PHP7.0.0. Если мое предположение (bool) TRUE, я предлагаю вам перейти на PHP7.0.1.

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


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


Более того:

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



ПРИМЕЧАНИЕ. Я знаю, что должен проверить исправленную ошибку, но...

person Ema4rl    schedule 04.01.2016

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

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

person mark    schedule 05.02.2016