mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-18 11:30:55 +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:
parent
51153a580c
commit
2b02024e23
2 changed files with 32 additions and 46 deletions
|
@ -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', ''));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue