From 400daae3f38fbcf5daf1c90a26cb48cbca020ec9 Mon Sep 17 00:00:00 2001 From: Andrey Kutejko Date: Mon, 22 Dec 2014 01:25:49 +0200 Subject: [PATCH] move error handling and url dispatching to middlewares --- ipf/auth/middleware.php | 2 +- ipf/middleware/base.php | 37 +++++++++++++++++ ipf/middleware/common.php | 7 ++-- ipf/middleware/dispatch.php | 24 +++++++++++ ipf/middleware/error.php | 27 +++++++++++++ ipf/middleware/serve_static.php | 4 +- ipf/project.php | 18 ++++++++- ipf/router.php | 71 +-------------------------------- ipf/session/middleware.php | 8 ++-- 9 files changed, 118 insertions(+), 80 deletions(-) create mode 100644 ipf/middleware/base.php create mode 100644 ipf/middleware/dispatch.php create mode 100644 ipf/middleware/error.php diff --git a/ipf/auth/middleware.php b/ipf/auth/middleware.php index c50d5c2..203642c 100644 --- a/ipf/auth/middleware.php +++ b/ipf/auth/middleware.php @@ -2,7 +2,7 @@ namespace IPF\Auth; -class Middleware +class Middleware extends \IPF_Middleware { const SessionKey = 'IPF_User_auth'; diff --git a/ipf/middleware/base.php b/ipf/middleware/base.php new file mode 100644 index 0000000..39731a7 --- /dev/null +++ b/ipf/middleware/base.php @@ -0,0 +1,37 @@ +next = $next; + $this->settings = $settings; + } + + function processRequest($request) + { + return false; + } + + function processResponse($request, $response) + { + return $response; + } + + function call($request) + { + $response = $this->processRequest($request); + if ($response !== false) { + return $response; + } + + if ($this->next) { + $response = $this->next->call($request); + } + + return $this->processResponse($request, $response); + } +} + diff --git a/ipf/middleware/common.php b/ipf/middleware/common.php index 1b16bea..e61d1d1 100644 --- a/ipf/middleware/common.php +++ b/ipf/middleware/common.php @@ -1,13 +1,14 @@ settings->get('append_slash', true)) { $url = $request->absoluteUrl(); - if (substr($url, -1) !== '/') + if (substr($url, -1) !== '/') { return new IPF_HTTP_Response_Redirect($url.'/'); + } } return false; } diff --git a/ipf/middleware/dispatch.php b/ipf/middleware/dispatch.php new file mode 100644 index 0000000..b63bd2c --- /dev/null +++ b/ipf/middleware/dispatch.php @@ -0,0 +1,24 @@ +router; + + $m = $router->match($request); + if (!$m) { + return new IPF_HTTP_Response_NotFound($request); + } + + list($route, $match) = $m; + $request->params = $match; + + try { + return IPF::callFunction($route->func, array($request, $match)); + } catch (IPF_Router_Shortcut $e) { + return $e->response($request); + } + } +} + diff --git a/ipf/middleware/error.php b/ipf/middleware/error.php new file mode 100644 index 0000000..b69dca5 --- /dev/null +++ b/ipf/middleware/error.php @@ -0,0 +1,27 @@ +next) { + $response = $this->next->call($request); + } + + if (!($response instanceof IPF_HTTP_Response)) { + throw new \Exception('Response in not a IPF_HTTP_Response'); + } + + return $response; + } catch (\Exception $exception) { + error_log($exception); + if ($this->settings->get('debug')) + return new IPF_HTTP_Response_ServerErrorDebug($request, $exception); + else + return new IPF_HTTP_Response_ServerError($request, $exception); + } + } +} + diff --git a/ipf/middleware/serve_static.php b/ipf/middleware/serve_static.php index 916ec8a..7e32002 100644 --- a/ipf/middleware/serve_static.php +++ b/ipf/middleware/serve_static.php @@ -1,10 +1,10 @@ settings->get('static_url'); if (!preg_match('#^'.preg_quote($staticUrl).'(.*)$#', $request->query, $matches)) return false; diff --git a/ipf/project.php b/ipf/project.php index 9bf307d..1d67892 100644 --- a/ipf/project.php +++ b/ipf/project.php @@ -34,6 +34,19 @@ final class IPF_Project return $this->apps; } + private function chainMiddlewares() + { + $middlewares = IPF::get('middlewares', array()); + array_unshift($middlewares, 'IPF_Error_Middleware'); + array_push($middlewares, 'IPF_Dispatch_Middleware'); + + $m = null; + foreach (array_reverse($middlewares) as $mw) { + $m = new $mw($m, IPF::$settings); + } + return $m; + } + public function run() { \PFF\Container::setFactory('databaseConnection', array('IPF_Database', 'connect')); @@ -51,7 +64,10 @@ final class IPF_Project $cli->run(); } else { $this->request = new IPF_HTTP_Request; - $this->router->dispatch($this->request); + + $response = $this->chainMiddlewares()->call($this->request); + $response->render($this->request->method !== 'HEAD'); + $this->request = null; } diff --git a/ipf/router.php b/ipf/router.php index f644271..99be41b 100644 --- a/ipf/router.php +++ b/ipf/router.php @@ -24,82 +24,15 @@ class IPF_Router } } - public static function response500($request, $exception) - { - error_log($exception); - if (IPF::get('debug')) - return new IPF_HTTP_Response_ServerErrorDebug($request, $exception); - else - return new IPF_HTTP_Response_ServerError($request, $exception); - } - - public function dispatch($req) - { - try { - $middleware = array(); - foreach (IPF::get('middlewares', array()) as $mw) { - $middleware[] = new $mw(); - } - $skip = false; - foreach ($middleware as $mw) { - if (method_exists($mw, 'processRequest')) { - $response = $mw->processRequest($req); - if ($response !== false) { - // $response is a response - $response->render($req->method != 'HEAD' and !defined('IN_UNIT_TESTS')); - $skip = true; - break; - } - } - } - if ($skip === false) { - $response = $this->match($req); - if (!empty($req->response_vary_on)) { - $response->headers['Vary'] = $req->response_vary_on; - } - $middleware = array_reverse($middleware); - foreach ($middleware as $mw) { - if (method_exists($mw, 'processResponse')) { - $response = $mw->processResponse($req, $response); - } - } - //var_dump($response); - $response->render($req->method != 'HEAD'); - } - return array($req, $response); - } catch (IPF_Exception $e) { - $response = self::response500($req, $e); - $response->render(); - } - } - public function match($req) { - $func = null; foreach ($this->routes as $route) { $match = array(); if ($route->matcher()->match($req->query, $match)) { - $func = $route->func; - $req->params = $match; - break; + return array($route, $match); } } - - if ($func) { - try { - $r = IPF::callFunction($func, array($req, $match)); - if (!is_a($r, 'IPF_HTTP_Response')) { - return self::response500($req, new IPF_Exception('function '.$func.'() must return IPF_HTTP_Response instance')); - } - return $r; - } catch (IPF_Router_Shortcut $e) { - return $e->response($req); - } catch (IPF_Exception $e) { - return self::response500($req, $e); - } - } - - return new IPF_HTTP_Response_NotFound($req); + return null; } public function describe() diff --git a/ipf/session/middleware.php b/ipf/session/middleware.php index 8c5497b..5048976 100644 --- a/ipf/session/middleware.php +++ b/ipf/session/middleware.php @@ -1,10 +1,10 @@ COOKIE, IPF::get('session_cookie_id')); + $session_cookie = \PFF\Arr::get($request->COOKIE, $this->settings->get('session_cookie_id')); $request->session = Session::get($session_cookie); if (!$request->session) @@ -16,7 +16,7 @@ class IPF_Session_Middleware function processResponse($request, $response) { $session_cookie = $request->session->cookie(); - $response->cookies[IPF::get('session_cookie_id')] = $session_cookie; + $response->cookies[$this->settings->get('session_cookie_id')] = $session_cookie; return $response; } } -- 2.49.0