1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-09 16:32:39 +01:00

Use AphrontRequestStream to read request input

Summary:
Ref T10604. This uses the new standalone stream reader introduced in D15483 to read request data, instead of putting the logic in PhabricatorStartup.

It also doesn't read request data until it specifically needs to. This supports, e.g., streaming Git LFS PUT requests, and streaming more types of requests in the future.

Test Plan: See D15483. Made various different types of requests and wasn't immediately able to break anything.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10604

Differential Revision: https://secure.phabricator.com/D15484
This commit is contained in:
epriestley 2016-03-16 10:47:07 -07:00
parent 51153a580c
commit 2b02024e23
2 changed files with 32 additions and 46 deletions

View file

@ -25,11 +25,18 @@ class AphrontDefaultApplicationConfiguration
$content_type = idx($_SERVER, 'CONTENT_TYPE');
$is_form_data = preg_match('@^multipart/form-data@i', $content_type);
$raw_input = PhabricatorStartup::getRawInput();
if (strlen($raw_input) && !$is_form_data) {
$data += $parser->parseQueryString($raw_input);
} else if ($_POST) {
$data += $_POST;
$request_method = idx($_SERVER, 'REQUEST_METHOD');
if ($request_method === 'PUT') {
// For PUT requests, do nothing: in particular, do NOT read input. This
// allows us to stream input later and process very large PUT requests,
// like those coming from Git LFS.
} else {
$raw_input = PhabricatorStartup::getRawInput();
if (strlen($raw_input) && !$is_form_data) {
$data += $parser->parseQueryString($raw_input);
} else if ($_POST) {
$data += $_POST;
}
}
$data += $parser->parseQueryString(idx($_SERVER, 'QUERY_STRING', ''));

View file

@ -83,6 +83,26 @@ final class PhabricatorStartup {
* @task info
*/
public static function getRawInput() {
if (self::$rawInput === null) {
$stream = new AphrontRequestStream();
if (isset($_SERVER['HTTP_CONTENT_ENCODING'])) {
$encoding = trim($_SERVER['HTTP_CONTENT_ENCODING']);
$stream->setEncoding($encoding);
}
$input = '';
do {
$bytes = $stream->readData();
if ($bytes === null) {
break;
}
$input .= $bytes;
} while (true);
self::$rawInput = $input;
}
return self::$rawInput;
}
@ -128,47 +148,6 @@ final class PhabricatorStartup {
self::detectPostMaxSizeTriggered();
self::beginOutputCapture();
if (isset($_SERVER['HTTP_CONTENT_ENCODING'])) {
$encoding = trim($_SERVER['HTTP_CONTENT_ENCODING']);
} else {
$encoding = null;
}
$input_stream = fopen('php://input', 'rb');
if (!$input_stream) {
self::didFatal(
'Unable to open "php://input" to read HTTP request body.');
}
if ($encoding === 'gzip') {
$ok = stream_filter_append(
$input_stream,
'zlib.inflate',
STREAM_FILTER_READ,
array(
'window' => 30,
));
if (!$ok) {
self::didFatal(
'Failed to append gzip inflate filter to HTTP request body input '.
'stream.');
}
}
$input_data = '';
while (!feof($input_stream)) {
$read_bytes = fread($input_stream, 16 * 1024);
if ($read_bytes === false) {
self::didFatal(
'Failed to read input bytes from HTTP request body.');
}
$input_data .= $read_bytes;
}
fclose($input_stream);
self::$rawInput = $input_data;
}