public function route($request)
    {
        $defaults = [
            'path'   => '',
            'method' => 'GET',
            'host'   => '*',
            'scheme' => '*'
        ];

        $this->_defaults = [];

        if ($request instanceof RequestInterface) {
            $uri = $request->getUri();
            $r = [
                'scheme' => $uri->getScheme(),
                'host'   => $uri->getHost(),
                'method' => $request->getMethod(),
                'path'   => $uri->getPath()
            ];
            if (method_exists($request, 'basePath')) {
                $this->basePath($request->basePath());
            }
        } elseif (!is_array($request)) {
            $r = array_combine(array_keys($defaults), func_get_args() + array_values($defaults));
        } else {
            $r = $request + $defaults;
        }
        $r = $this->_normalizeRequest($r);

        if ($route = $this->_route($r)) {
            $route->request = is_object($request) ? $request : $r;
            foreach ($route->persist as $key) {
                if (isset($route->params[$key])) {
                    $this->_defaults[$key] = $route->params[$key];
                }
            }
        } else {
            $route = $this->_classes['route'];
            $error = $route::NOT_FOUND;
            $message = "No route found for `{$r['scheme']}:{$r['host']}:{$r['method']}:/{$r['path']}`.";
            $route = new $route(compact('error', 'message'));
        }

        return $route;
    }