public function route(Request $request): Route
	{
		$requestMethod = $request->getMethod();

		$requestPath = $request->getPath();

		foreach($this->routes->getRoutesByMethod($requestMethod) as $route)
		{
			if($this->matches($route, $requestPath) && $this->constraintsAreSatisfied($route))
			{
				// Redirect to URL with trailing slash if the route should have one

				if($route->hasTrailingSlash() && !empty($requestPath) && substr($requestPath, -1) !== '/')
				{
					return $this->redirectRoute($requestPath);
				}

				// If this is an "OPTIONS" request then we'll collect all the allowed request methods
				// from all routes matching the requested path. We'll then add an "allows" header
				// to the matched route

				if($requestMethod === 'OPTIONS')
				{
					return $this->optionsRoute($requestPath);
				}

				// Assign the route to the request

				$request->setRoute($route);

				// Return the matched route and parameters

				return $route;
			}
		}

		// Check if there are any routes that match the pattern and constaints for other request methods

		if(!empty(($allowedMethods = $this->getAllowedMethodsForMatchingRoutes($requestPath))))
		{
			throw new MethodNotAllowedException($allowedMethods);
		}

		// No routes matched so we'll throw a not found exception

		throw new NotFoundException($requestMethod . ': ' . $requestPath);
	}