diff options
author | Bernhard Posselt <Raydiation@users.noreply.github.com> | 2015-02-27 15:43:01 +0100 |
---|---|---|
committer | Bernhard Posselt <Raydiation@users.noreply.github.com> | 2015-02-27 15:43:01 +0100 |
commit | 970b14d2979cb03d1e9ba96cbce3e43a52835333 (patch) | |
tree | fcfc92e273dbd8ab04663e5484a63194a22b43ed /lib | |
parent | 0c058490f4d6eeb7bfb066aa36cac635f5f9b175 (diff) | |
parent | 95239ad21e113d7d25d5844b0ac5f15a606f2140 (diff) | |
download | nextcloud-server-970b14d2979cb03d1e9ba96cbce3e43a52835333.tar.gz nextcloud-server-970b14d2979cb03d1e9ba96cbce3e43a52835333.zip |
Merge pull request #13616 from owncloud/streamresponse
AppFramework StreamResponse
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/appframework/app.php | 40 | ||||
-rw-r--r-- | lib/private/appframework/dependencyinjection/dicontainer.php | 5 | ||||
-rw-r--r-- | lib/private/appframework/http/dispatcher.php | 10 | ||||
-rw-r--r-- | lib/private/appframework/http/output.php | 70 | ||||
-rw-r--r-- | lib/public/appframework/http/icallbackresponse.php | 28 | ||||
-rw-r--r-- | lib/public/appframework/http/ioutput.php | 57 | ||||
-rw-r--r-- | lib/public/appframework/http/streamresponse.php | 48 |
7 files changed, 241 insertions, 17 deletions
diff --git a/lib/private/appframework/app.php b/lib/private/appframework/app.php index 537f10255a3..6d54b931d5a 100644 --- a/lib/private/appframework/app.php +++ b/lib/private/appframework/app.php @@ -24,9 +24,10 @@ namespace OC\AppFramework; -use \OC_App; -use \OC\AppFramework\DependencyInjection\DIContainer; -use \OCP\AppFramework\QueryException; +use OC_App; +use OC\AppFramework\DependencyInjection\DIContainer; +use OCP\AppFramework\QueryException; +use OCP\AppFramework\Http\ICallbackResponse; /** * Entry point for every request in your app. You can consider this as your @@ -93,15 +94,22 @@ class App { // initialize the dispatcher and run all the middleware before the controller $dispatcher = $container['Dispatcher']; - list($httpHeaders, $responseHeaders, $responseCookies, $output) = - $dispatcher->dispatch($controller, $methodName); + list( + $httpHeaders, + $responseHeaders, + $responseCookies, + $output, + $response + ) = $dispatcher->dispatch($controller, $methodName); + + $io = $container['OCP\\AppFramework\\Http\\IOutput']; if(!is_null($httpHeaders)) { - header($httpHeaders); + $io->setHeader($httpHeaders); } foreach($responseHeaders as $name => $value) { - header($name . ': ' . $value); + $io->setHeader($name . ': ' . $value); } foreach($responseCookies as $name => $value) { @@ -109,12 +117,22 @@ class App { if($value['expireDate'] instanceof \DateTime) { $expireDate = $value['expireDate']->getTimestamp(); } - setcookie($name, $value['value'], $expireDate, $container->getServer()->getWebRoot(), null, $container->getServer()->getConfig()->getSystemValue('forcessl', false), true); + $io->setCookie( + $name, + $value['value'], + $expireDate, + $container->getServer()->getWebRoot(), + null, + $container->getServer()->getConfig()->getSystemValue('forcessl', false), + true + ); } - if(!is_null($output)) { - header('Content-Length: ' . strlen($output)); - print($output); + if ($response instanceof ICallbackResponse) { + $response->callback($io); + } else if(!is_null($output)) { + $io->setHeader('Content-Length: ' . strlen($output)); + $io->setOutput($output); } } diff --git a/lib/private/appframework/dependencyinjection/dicontainer.php b/lib/private/appframework/dependencyinjection/dicontainer.php index 4229b251e29..e88177c6398 100644 --- a/lib/private/appframework/dependencyinjection/dicontainer.php +++ b/lib/private/appframework/dependencyinjection/dicontainer.php @@ -28,6 +28,7 @@ use OC; use OC\AppFramework\Http; use OC\AppFramework\Http\Request; use OC\AppFramework\Http\Dispatcher; +use OC\AppFramework\Http\Output; use OC\AppFramework\Core\API; use OC\AppFramework\Middleware\MiddlewareDispatcher; use OC\AppFramework\Middleware\Security\SecurityMiddleware; @@ -69,6 +70,10 @@ class DIContainer extends SimpleContainer implements IAppContainer { return $this->getServer()->getAppManager(); }); + $this->registerService('OCP\\AppFramework\\Http\\IOutput', function($c){ + return new Output(); + }); + $this->registerService('OCP\\IAvatarManager', function($c) { return $this->getServer()->getAvatarManager(); }); diff --git a/lib/private/appframework/http/dispatcher.php b/lib/private/appframework/http/dispatcher.php index 24540ef3c94..910e9c32ed4 100644 --- a/lib/private/appframework/http/dispatcher.php +++ b/lib/private/appframework/http/dispatcher.php @@ -100,17 +100,15 @@ class Dispatcher { $response = $this->middlewareDispatcher->afterController( $controller, $methodName, $response); - // get the output which should be printed and run the after output - // middleware to modify the response - $output = $response->render(); - $out[3] = $this->middlewareDispatcher->beforeOutput( - $controller, $methodName, $output); - // depending on the cache object the headers need to be changed $out[0] = $this->protocol->getStatusHeader($response->getStatus(), $response->getLastModified(), $response->getETag()); $out[1] = array_merge($response->getHeaders()); $out[2] = $response->getCookies(); + $out[3] = $this->middlewareDispatcher->beforeOutput( + $controller, $methodName, $response->render() + ); + $out[4] = $response; return $out; } diff --git a/lib/private/appframework/http/output.php b/lib/private/appframework/http/output.php new file mode 100644 index 00000000000..808f1ec6dfd --- /dev/null +++ b/lib/private/appframework/http/output.php @@ -0,0 +1,70 @@ +<?php +/** + * @author Bernhard Posselt + * @copyright 2015 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\AppFramework\Http; + +use OCP\AppFramework\Http\IOutput; + +/** + * Very thin wrapper class to make output testable + */ +class Output implements IOutput { + + /** + * @param string $out + */ + public function setOutput($out) { + print($out); + } + + /** + * @param string $path + * + * @return bool false if an error occured + */ + public function setReadfile($path) { + return @readfile($path); + } + + /** + * @param string $header + */ + public function setHeader($header) { + header($header); + } + + /** + * @param int $code sets the http status code + */ + public function setHttpResponseCode($code) { + http_response_code($code); + } + + /** + * @return int returns the current http response code + */ + public function getHttpResponseCode() { + return http_response_code(); + } + + /** + * @param string $name + * @param string $value + * @param int $expire + * @param string $path + * @param string $domain + * @param bool $secure + * @param bool $httponly + */ + public function setCookie($name, $value, $expire, $path, $domain, $secure, $httponly) { + setcookie($name, $value, $expire, $path, $domain, $secure, $httponly); + } + +} diff --git a/lib/public/appframework/http/icallbackresponse.php b/lib/public/appframework/http/icallbackresponse.php new file mode 100644 index 00000000000..4a392ed081d --- /dev/null +++ b/lib/public/appframework/http/icallbackresponse.php @@ -0,0 +1,28 @@ +<?php +/** + * @author Bernhard Posselt + * @copyright 2015 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCP\AppFramework\Http; + + +/** + * Interface ICallbackResponse + * + * @package OCP\AppFramework\Http + */ +interface ICallbackResponse { + + /** + * Outputs the content that should be printed + * + * @param IOutput a small wrapper that handles output + */ + function callback(IOutput $output); + +} diff --git a/lib/public/appframework/http/ioutput.php b/lib/public/appframework/http/ioutput.php new file mode 100644 index 00000000000..191f84374dc --- /dev/null +++ b/lib/public/appframework/http/ioutput.php @@ -0,0 +1,57 @@ +<?php +/** + * @author Bernhard Posselt + * @copyright 2015 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCP\AppFramework\Http; + + +/** + * Very thin wrapper class to make output testable + */ +interface IOutput { + + /** + * @param string $out + */ + public function setOutput($out); + + /** + * @param string $path + * + * @return bool false if an error occured + */ + public function setReadfile($path); + + /** + * @param string $header + */ + public function setHeader($header); + + /** + * @return int returns the current http response code + */ + public function getHttpResponseCode(); + + /** + * @param int $code sets the http status code + */ + public function setHttpResponseCode($code); + + /** + * @param string $name + * @param string $value + * @param int $expire + * @param string $path + * @param string $domain + * @param bool $secure + * @param bool $httponly + */ + public function setCookie($name, $value, $expire, $path, $domain, $secure, $httponly); + +} diff --git a/lib/public/appframework/http/streamresponse.php b/lib/public/appframework/http/streamresponse.php new file mode 100644 index 00000000000..870eb95cc1a --- /dev/null +++ b/lib/public/appframework/http/streamresponse.php @@ -0,0 +1,48 @@ +<?php +/** + * @author Bernhard Posselt + * @copyright 2015 Bernhard Posselt <dev@bernhard-posselt.com> + * + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCP\AppFramework\Http; + +use OCP\AppFramework\Http; + +/** + * Class StreamResponse + * + * @package OCP\AppFramework\Http + */ +class StreamResponse extends Response implements ICallbackResponse { + /** @var string */ + private $filePath; + + /** + * @param string $filePath the path to the file which should be streamed + */ + public function __construct ($filePath) { + $this->filePath = $filePath; + } + + + /** + * Streams the file using readfile + * + * @param IOutput a small wrapper that handles output + */ + public function callback (IOutput $output) { + // handle caching + if ($output->getHttpResponseCode() !== Http::STATUS_NOT_MODIFIED) { + if (!file_exists($this->filePath)) { + $output->setHttpResponseCode(Http::STATUS_NOT_FOUND); + } elseif ($output->setReadfile($this->filePath) === false) { + $output->setHttpResponseCode(Http::STATUS_BAD_REQUEST); + } + } + } + +} |