From 4266a38c01b54595c2691dfd882f970edc690bcd Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Wed, 8 Jul 2020 12:04:35 +0300 Subject: [PATCH] dev --- application/Espo/Core/Api/Response.php | 10 ++ application/Espo/Core/Api/ResponseWrapper.php | 12 ++ application/Espo/Core/Api/RouteProcessor.php | 112 ++++++++++++++++++ application/Espo/Core/Application.php | 75 +----------- 4 files changed, 138 insertions(+), 71 deletions(-) create mode 100644 application/Espo/Core/Api/RouteProcessor.php diff --git a/application/Espo/Core/Api/Response.php b/application/Espo/Core/Api/Response.php index 91cb15bf89..49a8d4875c 100644 --- a/application/Espo/Core/Api/Response.php +++ b/application/Espo/Core/Api/Response.php @@ -46,6 +46,16 @@ interface Response */ public function setHeader(string $name, string $value); + /** + * Get a header value. + */ + public function getHeader(string $name) : ?string; + + /** + * Whether a header is set. + */ + public function hasHeader(string $name) : bool; + /** * Write a body. */ diff --git a/application/Espo/Core/Api/ResponseWrapper.php b/application/Espo/Core/Api/ResponseWrapper.php index 8d64b4a89d..02205096df 100644 --- a/application/Espo/Core/Api/ResponseWrapper.php +++ b/application/Espo/Core/Api/ResponseWrapper.php @@ -55,6 +55,18 @@ class ResponseWrapper implements ApiResponse $this->response = $this->response->withHeader($name, $value); } + public function getHeader(string $name) : ?string + { + if (!$this->response->hasHeader($name)) return null; + + return $this->response->getHeaderLine($name); + } + + public function hasHeader(string $name) : bool + { + return $this->response->hasHeader($name); + } + public function getResponse() : Psr7Response { return $this->response; diff --git a/application/Espo/Core/Api/RouteProcessor.php b/application/Espo/Core/Api/RouteProcessor.php new file mode 100644 index 0000000000..0e1384ab86 --- /dev/null +++ b/application/Espo/Core/Api/RouteProcessor.php @@ -0,0 +1,112 @@ +config = $config; + $this->controllerManager = $controllerManager; + } + + public function process(string $route, array $routeParams, RequestWrapper $request, ResponseWrapper $response, array $args) + { + $response->setHeader('Content-Type', 'application/json'); + + $data = $request->getBodyContents(); + + $params = []; + + $paramKeys = array_keys($routeParams); + + $setKeyList = []; + + foreach ($paramKeys as $key) { + $value = $routeParams[$key]; + + $paramName = $key; + if ($value[0] === ':') { + $realKey = substr($value, 1); + $params[$paramName] = $args[$realKey]; + $setKeyList[] = $realKey; + } else { + $params[$paramName] = $value; + } + } + + foreach ($args as $key => $value) { + if (in_array($key, $setKeyList)) continue; + $params[$key] = $value; + } + + $controllerName = $params['controller'] ?? null; + $actionName = $params['action'] ?? null; + + if (!$controllerName) { + throw new Error("Route '{$route}' doesn't have a controller."); + } + + $controllerName = ucfirst($controllerName); + + if (!$actionName) { + $httpMethod = strtolower($request->getMethod()); + $crudList = $this->config->get('crud') ?? []; + $actionName = $crudList[$httpMethod] ?? null; + if (!$actionName) { + throw new Error("No action for method {$httpMethod}."); + } + } + + unset($params['controller']); + unset($params['action']); + + $contents = $this->controllerManager->process($controllerName, $actionName, $params, $data, $request, $response); + + if (is_string($contents)) { + $response->writeBody($contents); + } + + $response->setHeader('Expires', '0'); + $response->setHeader('Last-Modified', gmdate("D, d M Y H:i:s") . " GMT"); + $response->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'); + $response->setHeader('Pragma', 'no-cache'); + } +} diff --git a/application/Espo/Core/Application.php b/application/Espo/Core/Application.php index caf2969ab9..94573ecf06 100644 --- a/application/Espo/Core/Application.php +++ b/application/Espo/Core/Application.php @@ -41,6 +41,7 @@ use Espo\Core\{ Api\ErrorOutput as ApiErrorOutput, Api\RequestWrapper, Api\ResponseWrapper, + Api\RouteProcessor, Utils\Auth, Utils\Route, Utils\Autoload, @@ -122,18 +123,9 @@ class Application $responseWrapped = new ResponseWrapper($response); try { - /*$authRequired = true; - - $conditions = $item['conditions'] ?? []; - if (($conditions['auth'] ?? true) === false) { - $authRequired = false; - }*/ - $authRequired = !($item['noAuth'] ?? false); - $auth = $this->createAuth($requestWrapped); - $apiAuth = new ApiAuth($auth, $authRequired); - + $apiAuth = new ApiAuth($this->createAuth($requestWrapped), $authRequired); $apiAuth->process($requestWrapped, $responseWrapped); if (!$apiAuth->isResolved()) { @@ -143,7 +135,8 @@ class Application $this->setupSystemUser(); } - $this->processRoute($item, $requestWrapped, $responseWrapped, $args); + $routeProcessor = $this->getInjectableFactory()->create(RouteProcessor::class); + $routeProcessor->process($item['route'], $item['params'], $requestWrapped, $responseWrapped, $args); } catch (\Exception $exception) { (new ApiErrorOutput($requestWrapped))->process( $responseWrapped, $exception, false, $item, $args @@ -390,66 +383,6 @@ class Application ]); } - protected function processRoute(array $route, RequestWrapper $request, ResponseWrapper $response, array $args) - { - $response->setHeader('Content-Type', 'application/json'); - - $data = $request->getBodyContents(); - - $params = []; - - $paramKeys = array_keys($route['params']); - - $setKeyList = []; - - foreach ($paramKeys as $key) { - $value = $route['params'][$key]; - - $paramName = $key; - if ($value[0] === ':') { - $realKey = substr($value, 1); - $params[$paramName] = $args[$realKey]; - $setKeyList[] = $realKey; - } else { - $params[$paramName] = $value; - } - } - - foreach ($args as $key => $value) { - if (in_array($key, $setKeyList)) continue; - $params[$key] = $value; - } - - $controllerName = $params['controller'] ?? null; - $actionName = $params['action'] ?? null; - - if (!$controllerName) { - throw new Error("Route ".$route['route']." doesn't have a controller."); - } - - $controllerName = ucfirst($controllerName); - - if (!$actionName) { - $httpMethod = strtolower($request->getMethod()); - $crudList = $this->getConfig()->get('crud') ?? []; - $actionName = $crudList[$httpMethod] ?? null; - if (!$actionName) { - throw new Error("No action for method {$httpMethod}."); - } - } - - unset($params['controller']); - unset($params['action']); - - $controllerManager = $this->container->get('controllerManager'); - - $contents = $controllerManager->process($controllerName, $actionName, $params, $data, $request, $response); - - if (is_string($contents)) { - $response->writeBody($contents); - } - } - protected function initAutoloads() { $autoload = $this->getInjectableFactory()->create(Autoload::class);