public function start()
    {
        $this->beforeStart();

        // Begin output buffering and begin building the HTTP response
        $this->isBuffering = true;
        ob_start();

        $this->response = new Response();
        $this->context->registerInstance($this->response);

        try {
            // Dispatch the request to the router
            if (!$this->filters->trigger(Filters::BEFORE_ROUTE, $this->context)) {
                return $this->response;
            }

            $routingResult = $this->router->route($this->request);

            if ($routingResult != null) {
                $this->context->registerInstance($routingResult);
                $this->response->setResponseCode(ResponseCode::HTTP_OK);

                $returnValue = $this->dispatch($routingResult);

                // If a Response object was returned by the target code, use that object from now on
                if ($returnValue instanceof Response) {
                    if ($this->isBuffering) {
                        ob_clean();
                    }

                    $this->response = $returnValue;
                }
            } else {
                $anyOptionsAvailable = $this->router->getOptions($this->request);

                if (!$anyOptionsAvailable) {
                    // No options at all for this route, this is a true 404
                    $this->prepareNotFoundResponse();
                } else if ($this->request->getMethod() == RequestMethod::OPTIONS) {
                    // Options available, no custom OPTIONS handler, generate an OPTIONS ("Allow") response.
                    $this->prepareOptionsResponse();
                } else {
                    // There are options, but no match, this is a 405
                    $this->prepareNotAllowedResponse();
                }
            }

            $this->filters->trigger(Filters::AFTER_ROUTE, $this->context);
        } catch (\Exception $ex) {
            $this->prepareErrorResponse($ex);
        } finally {
            $this->sendResponse();
        }

        return $this->response;
    }