From e146b8c0ddbc6384c5a66f23dea71743fc282289 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 19 Oct 2017 18:46:56 -0700 Subject: [PATCH] Prevent response from sending more than once. --- VERSION | 2 +- flight/Engine.php | 50 ++++++++++++++++++++++++----------------- flight/net/Response.php | 29 +++++++++++++++++++++--- 3 files changed, 57 insertions(+), 24 deletions(-) diff --git a/VERSION b/VERSION index 8c9698a..aaf8be7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.4 \ No newline at end of file +1.3.5 \ No newline at end of file diff --git a/flight/Engine.php b/flight/Engine.php index ea6f6f9..0d95262 100644 --- a/flight/Engine.php +++ b/flight/Engine.php @@ -284,7 +284,7 @@ class Engine { $response = $this->response(); $router = $this->router(); - // Allow post-filters to run + // Allow filters to run $this->after('start', function() use ($self) { $self->stop(); }); @@ -331,11 +331,29 @@ class Engine { * * @param int $code HTTP status code */ - public function _stop($code = 200) { - $this->response() - ->status($code) - ->write(ob_get_clean()) - ->send(); + public function _stop($code = null) { + $response = $this->response(); + + if (!$response->sent()) { + if ($code !== null) { + $response->status($code); + } + + $response->write(ob_get_clean()); + + $response->send(); + } + } + + /** + * Routes a URL to a callback function. + * + * @param string $pattern URL pattern to match + * @param callback $callback Callback function + * @param boolean $pass_route Pass the matching route object to the callback + */ + public function _route($pattern, $callback, $pass_route = false) { + $this->router()->map($pattern, $callback, $pass_route); } /** @@ -366,7 +384,8 @@ class Engine { ); try { - $this->response(false) + $this->response() + ->clear() ->status(500) ->write($msg) ->send(); @@ -383,7 +402,8 @@ class Engine { * Sends an HTTP 404 response when a URL is not found. */ public function _notFound() { - $this->response(false) + $this->response() + ->clear() ->status(404) ->write( '

404 Not Found

'. @@ -393,17 +413,6 @@ class Engine { ->send(); } - /** - * Routes a URL to a callback function. - * - * @param string $pattern URL pattern to match - * @param callback $callback Callback function - * @param boolean $pass_route Pass the matching route object to the callback - */ - public function _route($pattern, $callback, $pass_route = false) { - $this->router()->map($pattern, $callback, $pass_route); - } - /** * Redirects the current request to another URL. * @@ -422,7 +431,8 @@ class Engine { $url = $base . preg_replace('#/+#', '/', '/' . $url); } - $this->response(false) + $this->response() + ->clear() ->status($code) ->header('Location', $url) ->write($url) diff --git a/flight/net/Response.php b/flight/net/Response.php index cab0305..c4f6ec7 100644 --- a/flight/net/Response.php +++ b/flight/net/Response.php @@ -29,6 +29,11 @@ class Response { */ protected $body; + /** + * @var bool HTTP response sent + */ + protected $sent = false; + /** * @var array HTTP status codes */ @@ -247,9 +252,7 @@ class Response { } // Send content length - $length = (extension_loaded('mbstring')) ? - mb_strlen($this->body, 'latin1') : - strlen($this->body); + $length = $this->getContentLength(); if ($length > 0) { header('Content-Length: '.$length); @@ -258,6 +261,24 @@ class Response { return $this; } + /** + * Gets the content length. + * + * @return string Content length + */ + public function getContentLength() { + return extension_loaded('mbstring') ? + mb_strlen($this->body, 'latin1') : + strlen($this->body); + } + + /** + * Gets whether response was sent. + */ + public function sent() { + return $this->sent; + } + /** * Sends a HTTP response. */ @@ -271,6 +292,8 @@ class Response { } echo $this->body; + + $this->sent = true; } }