mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 00:32:42 +01:00
Remove the execution time limit (if any) before sinking HTTP responses
Summary: Ref T12907. At least part of the problem is that we can hit PHP's `max_execution_time` limit on the file download pathway. We don't currently set this to anything in the application itself, but PHP often sets it to 30s by default (and we have it set to 30s in production). When writing responses, remove this limit. This limit is mostly a protection against accidental loops/recurison/etc., not a process slot protection. It doesn't really protect process slots anyway, since it doesn't start counting until the request starts executing, so you can (by default) //send// the request as slowly as you want without hitting this limit. By releasing the limit this late, hopefully all the loops and recursion issues have already been caught and we're left with mostly smooth sailing. We already remove this limit when sending `git clone` responses in `DiffusionServeController` and nothing has blown up. This affects `git clone http://` and similar. (I may have had this turned off locally and/or just be too impatient to wait 30s, which is why I haven't caught this previously.) Test Plan: - Poked around and downloaded some files. - Will `curl ...` in production and see if that goes better. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T12907 Differential Revision: https://secure.phabricator.com/D19547
This commit is contained in:
parent
9cf3b3bbf8
commit
81a7c9ac43
2 changed files with 27 additions and 1 deletions
|
@ -54,7 +54,16 @@ abstract class AphrontResponse extends Phobject {
|
|||
|
||||
|
||||
public function getContentIterator() {
|
||||
return array($this->buildResponseString());
|
||||
// By default, make sure responses are truly returning a string, not some
|
||||
// kind of object that behaves like a string.
|
||||
|
||||
// We're going to remove the execution time limit before dumping the
|
||||
// response into the sink, and want any rendering that's going to occur
|
||||
// to happen BEFORE we release the limit.
|
||||
|
||||
return array(
|
||||
(string)$this->buildResponseString(),
|
||||
);
|
||||
}
|
||||
|
||||
public function buildResponseString() {
|
||||
|
|
|
@ -112,6 +112,23 @@ abstract class AphrontHTTPSink extends Phobject {
|
|||
$response->getHTTPResponseMessage());
|
||||
$this->writeHeaders($all_headers);
|
||||
|
||||
// Allow clients an unlimited amount of time to download the response.
|
||||
|
||||
// This allows clients to perform a "slow loris" attack, where they
|
||||
// download a large response very slowly to tie up process slots. However,
|
||||
// concurrent connection limits and "RequestReadTimeout" already prevent
|
||||
// this attack. We could add our own minimum download rate here if we want
|
||||
// to make this easier to configure eventually.
|
||||
|
||||
// For normal page responses, we've fully rendered the page into a string
|
||||
// already so all that's left is writing it to the client.
|
||||
|
||||
// For unusual responses (like large file downloads) we may still be doing
|
||||
// some meaningful work, but in theory that work is intrinsic to streaming
|
||||
// the response.
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
$abort = false;
|
||||
foreach ($data as $block) {
|
||||
if (!$this->isWritable()) {
|
||||
|
|
Loading…
Reference in a new issue