diff options
author | Roeland Jago Douma <roeland@famdouma.nl> | 2016-09-05 21:00:53 +0200 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2016-09-06 11:57:39 +0200 |
commit | 3c55fe6bab73dabfb92e95e26f205fbb7b5781ec (patch) | |
tree | 4ee9ae8be1e3046cb98b0bd92e800853fdd5eaa8 /lib | |
parent | 314afcecf9080c78f485039852e30efee2e112c6 (diff) | |
download | nextcloud-server-3c55fe6bab73dabfb92e95e26f205fbb7b5781ec.tar.gz nextcloud-server-3c55fe6bab73dabfb92e95e26f205fbb7b5781ec.zip |
Split OCS version handling
This cleans up a bit the OCSController/Middleware. Since the 2 versions
of OCS differ a bit. Moved a lot of stuff internal since it is of no
concern to the outside.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/AppFramework/Middleware/OCSMiddleware.php | 85 | ||||
-rw-r--r-- | lib/private/AppFramework/OCS/BaseResponse.php | 85 | ||||
-rw-r--r-- | lib/private/AppFramework/OCS/V1Response.php | 78 | ||||
-rw-r--r-- | lib/private/AppFramework/OCS/V2Response.php | 76 | ||||
-rw-r--r-- | lib/public/AppFramework/OCSController.php | 32 |
5 files changed, 305 insertions, 51 deletions
diff --git a/lib/private/AppFramework/Middleware/OCSMiddleware.php b/lib/private/AppFramework/Middleware/OCSMiddleware.php index 68445bbcc51..0fc7bb0f0ec 100644 --- a/lib/private/AppFramework/Middleware/OCSMiddleware.php +++ b/lib/private/AppFramework/Middleware/OCSMiddleware.php @@ -23,14 +23,15 @@ namespace OC\AppFramework\Middleware; use OC\AppFramework\Http; +use OC\AppFramework\OCS\BaseResponse; +use OC\AppFramework\OCS\V1Response; +use OC\AppFramework\OCS\V2Response; use OCP\API; +use OCP\AppFramework\Controller; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\JSONResponse; -use OCP\AppFramework\Http\OCSResponse; use OCP\AppFramework\Http\Response; use OCP\AppFramework\OCS\OCSException; -use OCP\AppFramework\OCS\OCSForbiddenException; -use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\AppFramework\OCSController; use OCP\IRequest; use OCP\AppFramework\Middleware; @@ -40,6 +41,9 @@ class OCSMiddleware extends Middleware { /** @var IRequest */ private $request; + /** @var int */ + private $ocsVersion; + /** * @param IRequest $request */ @@ -50,47 +54,33 @@ class OCSMiddleware extends Middleware { /** * @param \OCP\AppFramework\Controller $controller * @param string $methodName + */ + public function beforeController($controller, $methodName) { + if ($controller instanceof OCSController) { + if (substr_compare($this->request->getScriptName(), '/ocs/v2.php', -strlen('/ocs/v2.php')) === 0) { + $this->ocsVersion = 2; + } else { + $this->ocsVersion = 1; + } + $controller->setOCSVersion($this->ocsVersion); + } + } + + /** + * @param \OCP\AppFramework\Controller $controller + * @param string $methodName * @param \Exception $exception * @throws \Exception - * @return OCSResponse + * @return BaseResponse */ public function afterException($controller, $methodName, \Exception $exception) { if ($controller instanceof OCSController && $exception instanceof OCSException) { - $format = $this->getFormat($controller); - $code = $exception->getCode(); if ($code === 0) { $code = API::RESPOND_UNKNOWN_ERROR; } - // Build the response - $response = new OCSResponse($format, $code, $exception->getMessage()); - - // Forbidden always sets 401 (even on v1.php) - if ($exception instanceof OCSForbiddenException || $code === API::RESPOND_UNAUTHORISED) { - $response->setStatus(Http::STATUS_UNAUTHORIZED); - } - - // On v2.php we set actual HTTP error codes - if (substr_compare($this->request->getScriptName(), '/ocs/v2.php', -strlen('/ocs/v2.php')) === 0) { - if ($code === API::RESPOND_NOT_FOUND) { - $response->setStatus(Http::STATUS_NOT_FOUND); - } else if ($code === API::RESPOND_SERVER_ERROR) { - $response->setStatus(Http::STATUS_INTERNAL_SERVER_ERROR); - } else if ($code === API::RESPOND_UNKNOWN_ERROR) { - $response->setStatus(Http::STATUS_INTERNAL_SERVER_ERROR); - } else if ($code === API::RESPOND_UNAUTHORISED) { - // Already set - } - // 4xx and 5xx codes are forwarded as is. - else if ($code >= 400 && $code < 600) { - $response->setStatus($code); - } else { - // All other codes get a bad request - $response->setStatus(Http::STATUS_BAD_REQUEST); - } - } - return $response; + return $this->buildNewResponse($controller, $code, $exception->getMessage()); } throw $exception; @@ -107,18 +97,17 @@ class OCSMiddleware extends Middleware { * If a different middleware has detected that a request unauthorized or forbidden * we need to catch the response and convert it to a proper OCS response. */ - if ($controller instanceof OCSController && !($response instanceof OCSResponse)) { + if ($controller instanceof OCSController && !($response instanceof BaseResponse)) { if ($response->getStatus() === Http::STATUS_UNAUTHORIZED || $response->getStatus() === Http::STATUS_FORBIDDEN) { - $format = $this->getFormat($controller); $message = ''; if ($response instanceof JSONResponse) { /** @var DataResponse $response */ $message = $response->getData()['message']; } - $response = new OCSResponse($format, \OCP\API::RESPOND_UNAUTHORISED, $message); - $response->setStatus(Http::STATUS_UNAUTHORIZED); + + return $this->buildNewResponse($controller, API::RESPOND_UNAUTHORISED, $message); } } @@ -126,6 +115,26 @@ class OCSMiddleware extends Middleware { } /** + * @param Controller $controller + * @param int $code + * @param string $message + * @return V1Response|V2Response + */ + private function buildNewResponse($controller, $code, $message) { + $format = $this->getFormat($controller); + + $data = new DataResponse(); + $data->setStatus($code); + if ($this->ocsVersion === 1) { + $response = new V1Response($data, $format, $message); + } else { + $response = new V2Response($data, $format, $message); + } + + return $response; + } + + /** * @param \OCP\AppFramework\Controller $controller * @return string */ diff --git a/lib/private/AppFramework/OCS/BaseResponse.php b/lib/private/AppFramework/OCS/BaseResponse.php new file mode 100644 index 00000000000..c9295a26779 --- /dev/null +++ b/lib/private/AppFramework/OCS/BaseResponse.php @@ -0,0 +1,85 @@ +<?php +/** + * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ +namespace OC\AppFramework\OCS; + +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\Response; + +abstract class BaseResponse extends Response { + /** @var array */ + protected $data; + + /** @var string */ + protected $format; + + /** @var string */ + protected $statusMessage; + + /** @var int */ + protected $itemsCount; + + /** @var int */ + protected $itemsPerPage; + + /** + * BaseResponse constructor. + * + * @param DataResponse|null $dataResponse + * @param string $format + * @param string|null $statusMessage + * @param int|null $itemsCount + * @param int|null $itemsPerPage + */ + public function __construct(DataResponse $dataResponse, + $format = 'xml', + $statusMessage = null, + $itemsCount = null, + $itemsPerPage = null) { + $this->format = $format; + $this->statusMessage = $statusMessage; + $this->itemsCount = $itemsCount; + $this->itemsPerPage = $itemsPerPage; + + $this->data = $dataResponse->getData(); + + $this->setHeaders($dataResponse->getHeaders()); + $this->setStatus($dataResponse->getStatus()); + $this->setETag($dataResponse->getETag()); + $this->setLastModified($dataResponse->getLastModified()); + $this->setCookies($dataResponse->getCookies()); + $this->setContentSecurityPolicy($dataResponse->getContentSecurityPolicy()); + } + + /** + * @param string[] $meta + * @return string + */ + protected function renderResult($meta) { + // TODO rewrite functions + return \OC_API::renderResult($this->format, $meta, $this->data); + } + + public function getOCSStatus() { + return parent::getStatus(); + } +} diff --git a/lib/private/AppFramework/OCS/V1Response.php b/lib/private/AppFramework/OCS/V1Response.php new file mode 100644 index 00000000000..08b11788110 --- /dev/null +++ b/lib/private/AppFramework/OCS/V1Response.php @@ -0,0 +1,78 @@ +<?php +/** + * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ +namespace OC\AppFramework\OCS; + +use OCP\API; +use OCP\AppFramework\Http; + +class V1Response extends BaseResponse { + + /** + * The V1 endpoint has very limited http status codes basically everything + * is status 200 except 401 + * + * @return int + */ + public function getStatus() { + $status = parent::getStatus(); + if ($status === Http::STATUS_FORBIDDEN || $status === API::RESPOND_UNAUTHORISED) { + return Http::STATUS_UNAUTHORIZED; + } + + return Http::STATUS_OK; + } + + /** + * In v1 all OK is 100 + * + * @return int + */ + public function getOCSStatus() { + $status = parent::getOCSStatus(); + + if ($status === Http::STATUS_OK) { + return 100; + } + + return $status; + } + + /** + * Construct the meta part of the response + * And then late the base class render + * + * @return string + */ + public function render() { + $meta = [ + 'status' => $this->getOCSStatus() === 100 ? 'ok' : 'failure', + 'statuscode' => $this->getOCSStatus(), + 'message' => $this->getOCSStatus() === 100 ? 'OK' : $this->statusMessage, + ]; + + $meta['totalitems'] = $this->itemsCount !== null ? (string)$this->itemsCount : ''; + $meta['itemsperpage'] = $this->itemsPerPage !== null ? (string)$this->itemsPerPage: ''; + + return $this->renderResult($meta); + } +} diff --git a/lib/private/AppFramework/OCS/V2Response.php b/lib/private/AppFramework/OCS/V2Response.php new file mode 100644 index 00000000000..7e98efe867d --- /dev/null +++ b/lib/private/AppFramework/OCS/V2Response.php @@ -0,0 +1,76 @@ +<?php +/** + * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ +namespace OC\AppFramework\OCS; + +use OCP\AppFramework\Http; +use OCP\API; + +class V2Response extends BaseResponse { + + /** + * The V2 endpoint just passes on status codes. + * Of course we have to map the OCS specific codes to proper HTTP status codes + * + * @return int + */ + public function getStatus() { + + $status = parent::getStatus(); + if ($status === API::RESPOND_UNAUTHORISED) { + return Http::STATUS_UNAUTHORIZED; + } else if ($status === API::RESPOND_NOT_FOUND) { + return Http::STATUS_NOT_FOUND; + } else if ($status === API::RESPOND_SERVER_ERROR || $status === API::RESPOND_UNKNOWN_ERROR) { + return Http::STATUS_INTERNAL_SERVER_ERROR; + } else if ($status < 200 || $status > 600) { + return Http::STATUS_BAD_REQUEST; + } + + return $status; + } + + /** + * Construct the meta part of the response + * And then late the base class render + * + * @return string + */ + public function render() { + $status = parent::getStatus(); + + $meta = [ + 'status' => $status >= 200 && $status < 300 ? 'ok' : 'failure', + 'statuscode' => $this->getOCSStatus(), + 'message' => $status >= 200 && $status < 300 ? 'OK' : $this->statusMessage, + ]; + + if ($this->itemsCount !== null) { + $meta['totalitems'] = $this->itemsCount; + } + if ($this->itemsPerPage !== null) { + $meta['itemsperpage'] = $this->itemsPerPage; + } + + return $this->renderResult($meta); + } +} diff --git a/lib/public/AppFramework/OCSController.php b/lib/public/AppFramework/OCSController.php index 6036fc6a5a8..5f18ba0807a 100644 --- a/lib/public/AppFramework/OCSController.php +++ b/lib/public/AppFramework/OCSController.php @@ -42,6 +42,9 @@ use OCP\IRequest; */ abstract class OCSController extends ApiController { + /** @var int */ + private $ocsVersion; + /** * constructor of the controller * @param string $appName the name of the app @@ -72,6 +75,15 @@ abstract class OCSController extends ApiController { } /** + * @param int $version + * @since 9.2.0 + * @internal + */ + public function setOCSVersion($version) { + $this->ocsVersion = $version; + } + + /** * Since the OCS endpoints default to XML we need to find out the format * again * @param mixed $response the value that was returned from a controller and @@ -90,22 +102,16 @@ abstract class OCSController extends ApiController { * @param string $format json or xml * @param DataResponse $data the data which should be transformed * @since 8.1.0 - * @return OCSResponse + * @return \OC\AppFramework\OCS\BaseResponse */ private function buildOCSResponse($format, DataResponse $data) { - $params = [ - 'statuscode' => 100, - 'message' => 'OK', - 'data' => $data->getData(), - 'itemscount' => '', - 'itemsperpage' => '' - ]; + if ($this->ocsVersion === 1) { + $response = new \OC\AppFramework\OCS\V1Response($data, $format); + } else { + $response = new \OC\AppFramework\OCS\V2Response($data, $format); + } - return new OCSResponse( - $format, $params['statuscode'], - $params['message'], $params['data'], - $params['itemscount'], $params['itemsperpage'] - ); + return $response; } } |