@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+32 -46
+12 -5
src/aphront/configuration/AphrontDefaultApplicationConfiguration.php
··· 25 25 $content_type = idx($_SERVER, 'CONTENT_TYPE'); 26 26 $is_form_data = preg_match('@^multipart/form-data@i', $content_type); 27 27 28 - $raw_input = PhabricatorStartup::getRawInput(); 29 - if (strlen($raw_input) && !$is_form_data) { 30 - $data += $parser->parseQueryString($raw_input); 31 - } else if ($_POST) { 32 - $data += $_POST; 28 + $request_method = idx($_SERVER, 'REQUEST_METHOD'); 29 + if ($request_method === 'PUT') { 30 + // For PUT requests, do nothing: in particular, do NOT read input. This 31 + // allows us to stream input later and process very large PUT requests, 32 + // like those coming from Git LFS. 33 + } else { 34 + $raw_input = PhabricatorStartup::getRawInput(); 35 + if (strlen($raw_input) && !$is_form_data) { 36 + $data += $parser->parseQueryString($raw_input); 37 + } else if ($_POST) { 38 + $data += $_POST; 39 + } 33 40 } 34 41 35 42 $data += $parser->parseQueryString(idx($_SERVER, 'QUERY_STRING', ''));
+20 -41
support/PhabricatorStartup.php
··· 83 83 * @task info 84 84 */ 85 85 public static function getRawInput() { 86 + if (self::$rawInput === null) { 87 + $stream = new AphrontRequestStream(); 88 + 89 + if (isset($_SERVER['HTTP_CONTENT_ENCODING'])) { 90 + $encoding = trim($_SERVER['HTTP_CONTENT_ENCODING']); 91 + $stream->setEncoding($encoding); 92 + } 93 + 94 + $input = ''; 95 + do { 96 + $bytes = $stream->readData(); 97 + if ($bytes === null) { 98 + break; 99 + } 100 + $input .= $bytes; 101 + } while (true); 102 + 103 + self::$rawInput = $input; 104 + } 105 + 86 106 return self::$rawInput; 87 107 } 88 108 ··· 128 148 self::detectPostMaxSizeTriggered(); 129 149 130 150 self::beginOutputCapture(); 131 - 132 - if (isset($_SERVER['HTTP_CONTENT_ENCODING'])) { 133 - $encoding = trim($_SERVER['HTTP_CONTENT_ENCODING']); 134 - } else { 135 - $encoding = null; 136 - } 137 - 138 - $input_stream = fopen('php://input', 'rb'); 139 - if (!$input_stream) { 140 - self::didFatal( 141 - 'Unable to open "php://input" to read HTTP request body.'); 142 - } 143 - 144 - if ($encoding === 'gzip') { 145 - $ok = stream_filter_append( 146 - $input_stream, 147 - 'zlib.inflate', 148 - STREAM_FILTER_READ, 149 - array( 150 - 'window' => 30, 151 - )); 152 - 153 - if (!$ok) { 154 - self::didFatal( 155 - 'Failed to append gzip inflate filter to HTTP request body input '. 156 - 'stream.'); 157 - } 158 - } 159 - 160 - $input_data = ''; 161 - while (!feof($input_stream)) { 162 - $read_bytes = fread($input_stream, 16 * 1024); 163 - if ($read_bytes === false) { 164 - self::didFatal( 165 - 'Failed to read input bytes from HTTP request body.'); 166 - } 167 - $input_data .= $read_bytes; 168 - } 169 - fclose($input_stream); 170 - 171 - self::$rawInput = $input_data; 172 151 } 173 152 174 153