public function resolve(Request $request, Response $response)
 {
     foreach ($this->rules as $rule) {
         if ($rule['source']($request->uri('path'))) {
             if (is_callable(@$rule['target'])) {
                 $target = $rule['target']($request, $response);
             } else {
                 $target = @$rule['target'];
             }
             // do nothing
             if (empty($target)) {
                 continue;
             }
             if (is_string($target)) {
                 $request->setUri($target);
             } else {
                 if (is_array($target)) {
                     if (empty($target['uri']) && isset($target['options']['status'])) {
                         $response->status($target['options']['status']);
                     } else {
                         if (isset($target['options'])) {
                             $response->redirect($target['uri'], $target['options']);
                         } else {
                             $request->setUri($target['uri'] + $request->uri());
                         }
                     }
                 }
             }
             break;
         }
     }
 }
Exemple #2
0
 public function resolve(Request $request, Response $response)
 {
     $pathInfo = $request->uri('path');
     // Inex 1 because request URI starts with a slash
     if (strpos($pathInfo, $this->dstPath) !== 1) {
         return;
     } else {
         $pathInfo = substr($pathInfo, strlen($this->dstPath) + 1);
     }
     $pathInfo = pathinfo($pathInfo);
     // Only serves .min.css requests
     if (!preg_match('/\\.min\\.css$/', $pathInfo['basename'])) {
         return;
     }
     $pathInfo['filename'] = preg_replace('/\\.min$/', '', $pathInfo['filename']);
     $_srcPath = "/{$pathInfo['dirname']}/{$pathInfo['filename']}.css";
     $dstPath = "./{$this->dstPath}/{$pathInfo['dirname']}/{$pathInfo['filename']}.min.css";
     foreach ($this->srcPath as $srcPath) {
         $srcPath = "./{$srcPath}{$_srcPath}";
         // compile when: target file not exists, or source is newer
         if (file_exists($srcPath) && (!file_exists($dstPath) || @filemtime($srcPath) > @filemtime($dstPath))) {
             // empty results are ignored
             $result = trim(@CssMin::minify(file_get_contents($srcPath)));
             if ($result && !@file_put_contents($dstPath, $result)) {
                 Log::warn('Permission denied, unable to minify CSS.');
             }
             break;
         }
     }
 }
Exemple #3
0
 public function resolve(Request $request, Response $response)
 {
     $pathInfo = $request->uri('path');
     // Inex 1 because request URI starts with a slash
     if (strpos($pathInfo, $this->dstPath) !== 1) {
         return;
     } else {
         $pathInfo = substr($pathInfo, strlen($this->dstPath) + 1);
     }
     $pathInfo = pathinfo($pathInfo);
     // Only serves .css requests
     if ($pathInfo['extension'] != 'css') {
         return;
     }
     // also takes care of .min requests
     $pathInfo['filename'] = preg_replace('/\\.min$/', '', $pathInfo['filename']);
     $_srcPath = "/{$pathInfo['dirname']}/{$pathInfo['filename']}.scss";
     $dstPath = "./{$this->dstPath}/{$pathInfo['dirname']}/{$pathInfo['filename']}.css";
     foreach ($this->srcPath as $srcPath) {
         $srcPath = "./{$srcPath}{$_srcPath}";
         // compile when: target file not exists, or source is newer
         if (!file_exists($dstPath) || @filemtime($srcPath) > @filemtime($dstPath)) {
             $result = @trim((new Compiler())->compile(file_get_contents($srcPath)));
             // note; write empty file if target exists
             if ($result || file_exists($dstPath)) {
                 if (!@file_put_contents($dstPath, $result)) {
                     Log::warn('Permission denied, unable to compile SCSS.');
                 }
             }
             break;
         }
     }
 }
 function resolve(Request $request, Response $response)
 {
     if ($response->status() != 200) {
         return;
         // only normal response will be processed
     }
     foreach ((array) $request->meta('output') as $outputFilter) {
         // format: func([param1[,param2[,param3 ...]]])
         if (preg_match('/(\\w+)\\(([\\w\\s,]*)\\)/', $outputFilter, $matches)) {
             $func = @$this->funcMap[$matches[1]];
             if (is_callable($func)) {
                 if (@$matches[2]) {
                     $func = call_user_func_array($func, explode(',', $matches[2]));
                 }
                 if (is_callable($func)) {
                     try {
                         $response->send(call_user_func_array($func, array($response->body())));
                     } catch (\Exception $e) {
                         Log::error(sprintf('[InvokerPostProcessor] Error calling %s(): %s @ %s:%d', $matches[1], $e->getMessage(), basename($e->getFile()), $e->getLine()), $e->getTrace());
                         $response->send(array('error' => $e->getMessage(), 'code' => $e->getCode()), 500);
                     }
                 }
             }
         }
     }
 }
Exemple #5
0
 public function resolve(Request $request, Response $response)
 {
     // Then request params
     if (empty($locale)) {
         $locale = $request->meta('locale');
     }
     // User preference
     if (empty($request->user)) {
         $locale = @$request->user['locale'];
     }
     // Accept from HTTP headers
     if (empty($locale)) {
         $locale = Locale::acceptFromHttp($request->header('Accept-Language'));
     }
     // TODO: Use Locale::lookup(); and its fallback mechanism for $this->defaultLocale.
     // TODO: Locale::getPrimaryLanguage() should be useful.
     // Default locale
     if (empty($locale)) {
         $locale = $this->defaultLocale;
     }
     if (!empty($locale)) {
         if ($request->meta('locale') != $locale) {
             $response->cookie('__locale', $locale, FRAMEWORK_COOKIE_EXPIRE_TIME, '/');
         }
         $response->translation(new Translation($locale));
     }
 }
Exemple #6
0
 /**
  * Use the new resolving mechanism to call for local services.
  */
 static function call($service, $method, $parameters = array(), $options = array())
 {
     $hostname = System::getHostname('service');
     if (!$hostname) {
         throw new ServiceException('Service hostname undefined.');
     }
     if (is_string($options)) {
         $options = array('method' => $options);
     }
     if (isset($options['type']) && empty($options['method'])) {
         $options['method'] = $options['type'];
     }
     $options = (array) $options + self::$defaultOptions;
     $prefix = conf::get('web::resolvers.service.prefix', '/service');
     $options['uri'] = array('scheme' => (bool) @$options['secure'] ? 'https' : 'http', 'host' => $hostname, 'path' => "{$prefix}/{$service}/{$method}/" . implode('/', array_map('urlencode', (array) $parameters)));
     unset($prefix);
     // Customizable Resolver
     if (@$options['resolver'] instanceof Resolver) {
         $serviceResolver = $options['resolver'];
     } else {
         $serviceResolver = Resolver::getActiveInstance();
     }
     unset($options['resolver']);
     if (@$options['response'] instanceof Response) {
         $serviceResponse = $options['response'];
     } else {
         $serviceResponse = new Response();
     }
     unset($options['response']);
     $serviceRequest = new Request($options);
     // Explicitly force this request to be local.
     $serviceRequest->__local = true;
     return $serviceRequest->send($serviceResolver, $serviceResponse);
 }
 public function resolve(Request $request, Response $response)
 {
     // Check whitelisted IP
     if (in_array($request->client('address'), $this->whitelist())) {
         return;
     }
     $request->setUri($this->template);
 }
Exemple #8
0
 /**
  * Add appropriate response header for response class to output.
  */
 public function resolve(Request $req, Response $res)
 {
     $callback = $req->param('JSONP_CALLBACK_NAME');
     if (!$callback) {
         $callback = $this->defaultCallback;
     }
     if ($callback && $req->param($callback)) {
         $res->header('X-JSONP-CALLBACK', $req->param($callback));
     }
 }
Exemple #9
0
 /**
  * Makes GET request to the URL and return the results to the template’s $_text array,
  * where it will be rendered to the final template output
  * @param type $tree
  * @param type $content
  * @return type
  */
 protected function _partial($tree, $content)
 {
     $address = trim($tree["raw"], " /");
     if (StringMethods::indexOf($address, "http") != 0) {
         $host = RequestMethods::server("HTTP_HOST");
         $address = "http://{$host}/{$address}";
     }
     $request = new Request();
     $response = addslashes(trim($request->get($address)));
     return "\$_text[] = \"{$response}\";";
 }
Exemple #10
0
 /**
  * Make GET request to given URL and place the results
  * in the template file
  * @param  array $tree    Node from the template tree
  * @param  mixed $content Content of node
  * @return string         String to be included in template
  */
 protected function _partial($tree, $content)
 {
     $address = trim($tree["raw"], " /");
     // Convert a relative URl to an absolute URL
     if (StringMethods::indexOf($address, "http") != 0) {
         $host = RequestMethods::server("HTTP_HOST");
         $address = "http://{$host}/{$address}";
     }
     // Make GET request to URL and return results to
     // template $_text array
     $request = new Request();
     $response = addslashes(trim($request->get($address)));
     return "\$_text[] = \"{$response}\";";
 }
Exemple #11
0
 public function resolve(Request $request, Response $response)
 {
     $commandPath = $this->basePath . '/' . $request->uri();
     if (!is_file($commandPath)) {
         throw new FrameworkException('Target command does not exist.');
     }
     require_once $commandPath;
     $fx = compose(unshiftsArg('str_replace', ' ', ''), 'ucwords', 'strtolower', unshiftsArg('str_replace', '-', ' '));
     $className = $fx($request->uri());
     if (!class_exists($className) || is_a($className, 'IExecutableCommand', true)) {
         throw new FrameworkException("File is loaded, expecting class {$className} from {$commandPath}.");
     }
     $command = new $className();
     $command->execute($request, $response);
 }
Exemple #12
0
 public function resolve(Request $request, Response $response)
 {
     global $argv;
     // Debug access log
     if (System::environment() == 'debug') {
         switch ($request->client('type')) {
             case 'cli':
                 $message = implode(' ', array($request->client('type'), $request->uri()));
                 break;
             default:
                 $message = implode(' ', array($request->client('version'), strtoupper($request->method()), $request->uri('path')));
                 @Log::debug($message, array_filter(array('origin' => $request->client('referer'), 'userAgent' => util::cascade(@$request->client('userAgent'), 'Unknown'), 'timeElapsed' => round(microtime(1) - $request->timestamp(), 4) . ' secs')));
                 break;
         }
     }
 }
Exemple #13
0
 function resolve(Request $request, Response $response)
 {
     $pathname = $this->basePath . $request->uri('path');
     switch (pathinfo($pathname, PATHINFO_EXTENSION)) {
         case 'md':
         case 'mdown':
             break;
         default:
             return;
     }
     if (is_file($pathname)) {
         $text = file_get_contents($pathname);
         $text = (new Parsedown())->text($text);
         $response->send($text, 200);
     }
 }
Exemple #14
0
 public static function Run()
 {
     self::$list['method'] = Request::getInstance()->method;
     self::$list['path'] = Request::getInstance()->path;
     self::$list['controller'] = str_replace('\\controller\\', '', Router::getInstance()->getControllerClass());
     self::$list['action'] = Router::getInstance()->getAction();
     require __DIR__ . '/src/view.php';
 }
Exemple #15
0
 /**
  * Checks whether an update is available.
  */
 public function resolve(Request $request, Response $response)
 {
     $path = $request->uri('path');
     $hash = $request->param('v');
     $info = Cache::getInfo($path, $hash);
     if (!$info) {
         return;
     }
     // Send a bunch of headers
     // 1. Conditional request
     // If-Modified-Since: Match against $info->getMTime();
     // If-None-Match: Match against the md5_file();
     // 2. Normal request
     // Content-Type + charset
     // Content-Length
     // Cache-Control
     // Date
     // Pragma (remove)
     // header('Content-Type: application/json; charset=utf-8', true);
 }
Exemple #16
0
 public function initialize()
 {
     require_once 'config/routing.php';
     foreach ($this->routes as $route) {
         if (preg_match($route['path'], Request::getInstance()->path, $matches)) {
             $this->controller = $route['controller'];
             $this->action = $route['action'];
             if (!empty($matches)) {
                 $this->matches = $matches;
             }
         }
     }
 }
 public function resolve(Request $req, Response $res)
 {
     $req->user = new User();
     // User from CLI
     switch ($req->client('type')) {
         case 'cli':
             // Retrieve user context from process data, then CLI argument.
             $userId = (int) Process::get('type');
             if (!$userId) {
                 $req->cli()->options('u', array('alias' => 'user', 'type' => 'integer', 'describe' => 'Idenitfier of target context user.'));
                 $userId = (int) $req->meta('user');
             }
             if ($userId) {
                 $req->user->load($userId);
             }
             unset($userId);
             break;
         default:
             // Session ID provided, validate it.
             $sid = $req->meta('sid');
             if ($sid) {
                 $ret = Session::ensure($sid, $req->meta('token'), $req->fingerprint());
                 // Session doesn't exist, delete the cookie.
                 if ($ret === false || $ret === Session::ERR_EXPIRED) {
                     $res->cookie('__sid', '', time() - 3600);
                 } else {
                     if (is_integer($ret)) {
                         switch ($ret) {
                             // note: System should treat as public user.
                             case Session::ERR_INVALID:
                                 break;
                         }
                     } else {
                         // Success, proceed.
                         $req->user->load(Session::current('username'));
                         unset($req->user->password);
                     }
                 }
             } else {
                 if ($this->setupSession && !@\core\Node::get('User')) {
                     $req->user->data(['id' => 0, 'groups' => ['Administrators'], 'username' => '__default']);
                 }
             }
             break;
     }
 }
Exemple #18
0
 public function resolve(Request $request, Response $response)
 {
     $path = $this->srcPath . $request->uri('path') . '.url';
     // Check if target file is a proxy.
     if (!is_file($path)) {
         return;
     }
     $cacheTarget = parse_ini_file($path);
     $cacheTarget = @$cacheTarget['URL'];
     unset($path);
     if (!$cacheTarget) {
         Log::warning('Proxy file has not URL parameter.', array('requestUri' => $request->uri(), 'proxyFile' => $request->uri('path') . '.uri'));
         $response->status(502);
         // Bad Gateway
         return;
     }
     /*! Cache Header Notes
      *
      *  # Cache-Control
      *  [public | private] Cacheable when public, otherwise the client is responsible for caching.
      *  [no-cache( \w+)?]  When no fields are specified, the whole thing must revalidate everytime,
      *                     otherwise cache it except specified fields.
      *  [no-store] 				 Ignore caching and pipe into output.
      *  [max-age=\d+] 		 Seconds before this cache is meant to expire, this overrides Expires header.
      *  [s-maxage=\d+] 		 Overrides max-age and Expires header, behaves just like max-age.
      *                 	   (This is for CDN and we are using it.)
      *  [must-revalidate]  Tells those CDNs which are intended to serve stale contents to revalidate every time.
      *  [proxy-revalidate] Like the "s-" version of max-age, a "must-revalidate" override only for CDN.
      *  [no-transform]     Some CDNs will optimize images and other formats, this "opt-out" of it.
      *
      *  # Expires
      *  RFC timestamp for an absolute cache expiration, overridden by Cache-Control header.
      *
      *  # ETag
      *  Hash of anything, weak ETags is not supported at this moment.
      *
      *  # vary
      *  Too much fun inside and we are too serious about caching, ignore this.
      *
      *  # pragma
      *  This guy is too old to recognize.
      *  [no-cache] Only this is known nowadays and is already succeed by Cache-Control: no-cache.
      *
      */
     // note; Use "cache-meta://" scheme for header and cache meta info, for performance.
     // 1. Check if cache exists.
     $cache = (array) Cache::get("cache-meta://{$cacheTarget}");
     // Cache expiration, in seconds.
     // expires = ( s-maxage || max-age || Expires );
     if (@$cache['expires'] && time() > $cache['expires']) {
         Cache::delete("cache-meta://{$cacheTarget}");
         Cache::delete("cache://{$cacheTarget}");
         $cache = null;
     }
     // - If not exists, make normal request to remote server.
     // - If exists, make conditional request to remote server.
     //   - Revalidation, we can skip this request and serve the content if false.
     //     revalidates = ( Cache-Control:proxy-revalidate || Cache-Control:must-revalidate )
     if (!$cache || @$cache['revalidates']) {
         $_request = array('uri' => $cacheTarget);
         if ($cache) {
             // Last-Modified
             if (@$cache['headers']['Last-Modified']) {
                 $_request['headers']['If-Modified-Since'] = $cache['Last-Modified'];
             }
             // Entity-Tag
             if (@$cache['headers']['ETag'] && strpos($cache['headers']['ETag'], 'W\\') !== 0) {
                 $_request['headers']['If-None-Match'] = $cache['ETag'];
             }
         } else {
             $cache = array();
         }
         // Make the request
         $_response = new Response(array('autoOutput' => false));
         (new Request($_request))->send(null, $_response);
         unset($_request);
         // parse headers into cache settings.
         if (in_array($_response->status(), array(200, 304))) {
             $res = preg_split('/\\s*,\\s*/', util::unwrapAssoc($_response->header('Cache-Control')));
             $res = array_reduce($res, function ($res, $value) {
                 // todo; Take care of no-cache with field name.
                 if (strpos($value, '=') > 0) {
                     $value = explode('=', $value);
                     $res[$value[0]] = $value[1];
                 } else {
                     $res[$value] = true;
                 }
                 return $res;
             }, array());
             // private, no-store, no-cache
             if (@$res['private'] || @$res['no-store'] || @$res['no-cache']) {
                 // note; in case the upstream server change this to uncacheable
                 Cache::delete("cache-meta://{$cacheTarget}");
                 Cache::delete("cache://{$cacheTarget}");
                 $_response->clearBody();
             }
             if ($_response->status() == 200 && $_response->body()) {
                 $cache['contents'] = $_response->body();
             }
             // expires = ( s-maxage || max-age || Expires );
             if (@$res['s-maxage']) {
                 $cache['expires'] = time() + $res['s-maxage'];
             } elseif (@$res['max-age']) {
                 $cache['expires'] = time() + $res['max-age'];
             } else {
                 $res = util::unwrapAssoc($_response->header('Expires'));
                 if ($res) {
                     $cache['expires'] = strtotime($res);
                 }
             }
             // revalidates = ( Cache-Control:proxy-revalidate || Cache-Control:must-revalidate )
             if (@$res['proxy-revalidate'] || @$res['must-revalidate']) {
                 $cache['revalidates'] = true;
             }
             unset($res);
         }
         $cache['headers'] = array_map('core\\Utility::unwrapAssoc', $_response->header());
         // PHP does not support chunked, skip this one.
         unset($cache['headers']['Transfer-Encoding']);
         // note; If cache is to be ignored, the $cacheTarget variable will be already unset().
         if (isset($cacheTarget)) {
             if (@$cache['contents']) {
                 Cache::set("cache://{$cacheTarget}", $cache['contents']);
             }
             Cache::set("cache-meta://{$cacheTarget}", array_filter_keys($cache, isNot('contents')));
         }
         unset($_response);
     }
     // note; Send cache headers regardless of the request condition.
     if (@$cache['headers']) {
         $response->clearHeaders();
         foreach ($cache['headers'] as $name => $value) {
             $response->header($name, $value, true);
         }
         unset($name, $value);
     }
     // note; Handles conditional request
     $ch = array_map('core\\Utility::unwrapAssoc', (array) @$cache['headers']);
     $mtime = @$ch['Last-Modified'] ? strtotime($ch['Last-Modified']) : false;
     // Request headr: If-Modified-Since
     if (@$ch['Last-Modified'] && $mtime) {
         if (strtotime($request->header('If-Modified-Since')) >= $mtime) {
             return $response->status(304);
         }
     }
     // Request header: If-Range
     if ($request->header('If-Range')) {
         // Entity tag
         if (strpos(substr($request->header('If-Range'), 0, 2), '"') !== false && @$ch['ETag']) {
             if ($this->compareETags(@$ch['ETag'], $request->header('If-Range'))) {
                 return $this->response()->status(304);
             }
         } elseif (strtotime($request->header('If-Range')) === $mtime) {
             return $this->response()->status(304);
         }
     }
     unset($mtime);
     // Request header: If-None-Match
     if (!$request->header('If-Modified-Since') && $request->header('If-None-Match')) {
         // Exists but not GET or HEAD
         switch ($request->method()) {
             case 'get':
             case 'head':
                 break;
             default:
                 return $this->response()->status(412);
         }
         /*! Note by Vicary @ 24 Jan, 2013
          *  If-None-Match means 304 when target resources exists.
          */
         if ($request->header('If-None-Match') === '*' && @$ch['ETag']) {
             return $this->response()->status(304);
         }
         if ($this->compareETags(@$ch['ETag'], preg_split('/\\s*,\\s*/', $request->header('If-None-Match')))) {
             return $this->response()->status(304);
         }
     }
     // Request header: If-Match
     if (!$request->header('If-Modified-Since') && $request->header('If-Match')) {
         // Exists but not GET or HEAD
         switch ($request->method()) {
             case 'get':
             case 'head':
                 break;
             default:
                 return $this->response()->status(412);
         }
         if ($request->header('If-Match') === '*' && !@$ch['ETag']) {
             return $this->response()->status(412);
         }
         preg_match_all('/(?:^\\*$|(:?"([^\\*"]+)")(?:\\s*,\\s*(:?"([^\\*"]+)")))$/', $request->header('If-Match'), $eTags);
         // 412 Precondition Failed when nothing matches.
         if (@$eTags[1] && !in_array($eTag, (array) $eTags[1])) {
             return $this->response()->status(412);
         }
     }
     if ($cacheTarget && empty($cache['contents'])) {
         $cache['contents'] = Cache::get("cache://{$cacheTarget}");
     }
     // Output the cahce content
     $response->send($cache['contents'], 200);
 }
Exemple #19
0
 public function resolve(Request $request, Response $response)
 {
     // Stop processing when previous resolvers has done something and given a response status code.
     if ($response->status()) {
         return;
     }
     $path = $request->uri('path');
     // note; decode escaped URI characters into escaped shell path
     $path = preg_replace_callback('/%([\\dA-F]{2,2})/i', function ($matches) {
         return '\\' . chr(hexdec($matches[1]));
     }, $path);
     // Store original request
     if (empty($request->__directoryIndex)) {
         $request->__uri = $request->uri();
     }
     if (stripos($path, $this->pathPrefix) === 0) {
         $path = substr($path, strlen($this->pathPrefix));
     }
     if (strpos($path, '?') !== false) {
         $path = strstr($path, '?', true);
     }
     $path = urldecode($path);
     if (!$path) {
         $path = './';
     }
     //------------------------------
     //  Emulate DirectoryIndex
     //------------------------------
     if (is_dir($path)) {
         if (!is_file($path) && !isset($request->__directoryIndex)) {
             // Prevent redirection loop
             $request->__directoryIndex = true;
             foreach ($this->directoryIndex() as $file) {
                 $request->setUri(preg_replace('/^\\.\\//', '', $path) . $file);
                 // Exit whenever an index is handled successfully, this will exit.
                 if ($this->resolve($request, $response)) {
                     return;
                 }
             }
             unset($request->__directoryIndex);
             // Nothing works, going down.
             if (isset($request->__uri)) {
                 $request->setUri($request->__uri);
             }
         }
     } else {
         if (empty($request->__directoryIndex)) {
             $dirname = dirname($path);
             if ($dirname == '.') {
                 $dirname = '/';
             }
             if (in_array(pathinfo($path, PATHINFO_FILENAME), $this->directoryIndex())) {
                 // extension-less
                 if (!pathinfo($path, PATHINFO_EXTENSION) || is_file($path)) {
                     $response->redirect($dirname);
                     return true;
                 }
             }
             unset($dirname);
         }
     }
     //------------------------------
     //  Virtual file handling
     //------------------------------
     $this->createVirtualFile($path);
     if (is_file($path)) {
         try {
             $this->handle($path, $request, $response);
         } catch (ResolverException $e) {
             $response->status($e->statusCode());
         }
         if (!$response->status()) {
             $response->status(200);
         }
         return true;
     }
 }
Exemple #20
0
<?php

error_reporting(E_ALL);
ini_set('display_errors', 1);
use FlickrTestApp\Config\AppConfig;
use Framework\Resolver;
use Framework\Router;
use Framework\Request;
// Composer autoload
$loader = (require __DIR__ . '/../vendor/autoload.php');
// Load application configuration
define('APP_CONFIG', realpath(__DIR__ . '/../src/FlickrTestApp/Config/AppConfig.php'));
// Check if the app configuration is readable
if (!is_readable(APP_CONFIG)) {
    die('No application configuration found. Please create an application configuration in ' . APP_CONFIG);
}
// Setup routes from AppConfig
$router = new Router(AppConfig::$routes);
// URL resolver
$resolver = Resolver::build($router);
// Build the current request to be served
$request = Request::fromCurrent();
// Built response object
$response = $resolver->handle($request);
// Dispatch the response
$response->dispatch();
Exemple #21
0
 static function authenticate(Request $r = null)
 {
     return $r && $r->method() == 'get';
 }
 public function resolve(Request $req, Response $res)
 {
     $auth = $this->paths;
     $pathNodes = trim($req->uri('path'), '/');
     if ($pathNodes) {
         $pathNodes = explode('/', $pathNodes);
     } else {
         $pathNodes = ['/'];
     }
     $lastWildcard = @$auth['*'];
     foreach ($pathNodes as $index => $pathNode) {
         if (!util::isAssoc($auth)) {
             break;
             // No more definitions, break out.
         }
         if (isset($auth['*'])) {
             $lastWildcard = $auth['*'];
         }
         if (isset($auth[$pathNode])) {
             $auth = $auth[$pathNode];
         } else {
             unset($auth);
             break;
         }
     }
     if (!isset($auth) || !is_bool($auth) && (!is_array($auth) || util::isAssoc($auth))) {
         if (empty($lastWildcard)) {
             throw new FrameworkException('Unable to resolve authentication chain from request URI.');
         } else {
             $auth = $lastWildcard;
         }
     }
     unset($pathNodes, $lastWildcard);
     // Numeric array
     if (is_array($auth) && !util::isAssoc($auth)) {
         $auth = array_reduce($auth, function ($result, $auth) use($req) {
             if (!$result) {
                 return $result;
             }
             if (is_callable($auth)) {
                 $auth = $auth($req);
             } else {
                 if (is_string($auth)) {
                     if (strpos($auth, '/') === false) {
                         $auth = "authenticators\\{$auth}";
                     }
                     if (is_a($auth, 'framework\\interfaces\\IAuthenticator', true)) {
                         $result = $result && $auth::authenticate($req);
                     } else {
                         throw new FrameworkException('Unknown authenticator type, must be ' . 'instance of IAuthenticator or callable.');
                     }
                 } else {
                     throw new FrameworkException('Unknown authenticator type, must be ' . 'instance of IAuthenticator or callable.');
                 }
             }
             return $result && $auth;
         }, true);
     }
     // Boolean
     if (is_bool($auth) && !$auth) {
         $res->status($this->statusCode);
     }
     // TODO: Mark allowed or denied according to the new resolver mechanism.
 }