public function handleRequest(HTTPRequest $request)
    {
        Injector::inst()->registerService($request, HTTPRequest::class);

        $rules = Director::config()->uninherited('rules');

        $this->extend('updateRules', $rules);

        // Default handler - mo URL rules matched, so return a 404 error.
        $handler = function () {
            return new HTTPResponse('No URL rule was matched', 404);
        };

        foreach ($rules as $pattern => $controllerOptions) {
            // Match pattern
            $arguments = $request->match($pattern, true);
            if ($arguments == false) {
                continue;
            }

            // Normalise route rule
            if (is_string($controllerOptions)) {
                if (substr($controllerOptions, 0, 2) == '->') {
                    $controllerOptions = array('Redirect' => substr($controllerOptions, 2));
                } else {
                    $controllerOptions = array('Controller' => $controllerOptions);
                }
            }
            $request->setRouteParams($controllerOptions);

            // controllerOptions provide some default arguments
            $arguments = array_merge($controllerOptions, $arguments);

            // Pop additional tokens from the tokenizer if necessary
            if (isset($controllerOptions['_PopTokeniser'])) {
                $request->shift($controllerOptions['_PopTokeniser']);
            }

            // Handler for redirection
            if (isset($arguments['Redirect'])) {
                $handler = function () use ($arguments) {
                    // Redirection
                    $response = new HTTPResponse();
                    $response->redirect(static::absoluteURL($arguments['Redirect']));
                    return $response;
                };
                break;
            }

            // Handler for constructing and calling a controller
            $handler = function (HTTPRequest $request) use ($arguments) {
                try {
                    /** @var RequestHandler $controllerObj */
                    $controllerObj = Injector::inst()->create($arguments['Controller']);
                    return $controllerObj->handleRequest($request);
                } catch (HTTPResponse_Exception $responseException) {
                    return $responseException->getResponse();
                }
            };
            break;
        }

        // Call the handler with the configured middlewares
        $response = $this->callMiddleware($request, $handler);

        // Note that if a different request was previously registered, this will now be lost
        // In these cases it's better to use Kernel::nest() prior to kicking off a nested request
        Injector::inst()->unregisterNamedObject(HTTPRequest::class);

        return $response;
    }