# File: fastapi/responses.py | Symbol: ORJSONResponse
@deprecated(
    "ORJSONResponse is deprecated, FastAPI now serializes data directly to JSON "
    "bytes via Pydantic when a return type or response model is set, which is "
    "faster and doesn't need a custom response class. Read more in the FastAPI "
    "docs: https://fastapi.tiangolo.com/advanced/custom-response/#orjson-or-response-model "
    "and https://fastapi.tiangolo.com/tutorial/response-model/",
    category=FastAPIDeprecationWarning,
    stacklevel=2,
)
class ORJSONResponse(JSONResponse):
    """JSON response using the orjson library to serialize data to JSON.

    **Deprecated**: `ORJSONResponse` is deprecated. FastAPI now serializes data
    directly to JSON bytes via Pydantic when a return type or response model is
    set, which is faster and doesn't need a custom response class.

    Read more in the
    [FastAPI docs for Custom Response](https://fastapi.tiangolo.com/advanced/custom-response/#orjson-or-response-model)
    and the
    [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/).

    **Note**: `orjson` is not included with FastAPI and must be installed
    separately, e.g. `pip install orjson`.
    """

    def render(self, content: Any) -> bytes:
        assert orjson is not None, "orjson must be installed to use ORJSONResponse"
        return orjson.dumps(
            content, option=orjson.OPT_NON_STR_KEYS | orjson.OPT_SERIALIZE_NUMPY
        )


# File: fastapi/responses.py | Symbol: <module>
import importlib
from typing import Any, Protocol, cast
from fastapi.exceptions import FastAPIDeprecationWarning
from fastapi.sse import EventSourceResponse as EventSourceResponse  # noqa
from starlette.responses import FileResponse as FileResponse  # noqa
from starlette.responses import HTMLResponse as HTMLResponse  # noqa
from starlette.responses import JSONResponse as JSONResponse  # noqa
from starlette.responses import PlainTextResponse as PlainTextResponse  # noqa
from starlette.responses import RedirectResponse as RedirectResponse  # noqa
from starlette.responses import Response as Response  # noqa
from starlette.responses import StreamingResponse as StreamingResponse  # noqa
from typing_extensions import deprecated
try:
    ujson = cast(_UjsonModule, importlib.import_module("ujson"))
except ModuleNotFoundError:  # pragma: nocover
    ujson = None  # type: ignore[assignment]
try:
    orjson = cast(_OrjsonModule, importlib.import_module("orjson"))
except ModuleNotFoundError:  # pragma: nocover
    orjson = None  # type: ignore[assignment]


# File: fastapi/routing.py | Symbol: request_response
def request_response(
    func: Callable[[Request], Awaitable[Response] | Response],
) -> ASGIApp:
    """
    Takes a function or coroutine `func(request) -> response`,
    and returns an ASGI application.
    """
    f: Callable[[Request], Awaitable[Response]] = (
        func  # type: ignore[assignment]
        if is_async_callable(func)
        else functools.partial(run_in_threadpool, func)  # type: ignore[call-arg]
    )  # ty: ignore[invalid-assignment]

    async def app(scope: Scope, receive: Receive, send: Send) -> None:
        request = Request(scope, receive, send)

        async def app(scope: Scope, receive: Receive, send: Send) -> None:
            # Starts customization
            response_awaited = False
            async with AsyncExitStack() as request_stack:
                scope["fastapi_inner_astack"] = request_stack
                async with AsyncExitStack() as function_stack:
                    scope["fastapi_function_astack"] = function_stack
                    response = await f(request)
                await response(scope, receive, send)
                # Continues customization
                response_awaited = True
            if not response_awaited:
                raise FastAPIError(
                    "Response not awaited. There's a high chance that the "
                    "application code is raising an exception and a dependency with yield "
                    "has a block with a bare except, or a block with except Exception, "
                    "and is not raising the exception again. Read more about it in the "
                    "docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except"
                )

        # Same as in Starlette
        await wrap_app_handling_exceptions(app, request)(scope, receive, send)

    return app


# File: fastapi/routing.py | Symbol: websocket_session
def websocket_session(
    func: Callable[[WebSocket], Awaitable[None]],
) -> ASGIApp:
    """
    Takes a coroutine `func(session)`, and returns an ASGI application.
    """
    # assert asyncio.iscoroutinefunction(func), "WebSocket endpoints must be async"

    async def app(scope: Scope, receive: Receive, send: Send) -> None:
        session = WebSocket(scope, receive=receive, send=send)

        async def app(scope: Scope, receive: Receive, send: Send) -> None:
            async with AsyncExitStack() as request_stack:
                scope["fastapi_inner_astack"] = request_stack
                async with AsyncExitStack() as function_stack:
                    scope["fastapi_function_astack"] = function_stack
                    await func(session)

        # Same as in Starlette
        await wrap_app_handling_exceptions(app, session)(scope, receive, send)

    return app


# File: fastapi/routing.py | Symbol: _AsyncLiftContextManager
class _AsyncLiftContextManager(AbstractAsyncContextManager[_T]):
    """
    Wraps a synchronous context manager to make it async.

    This is vendored from Starlette to avoid importing private symbols.
    """

    def __init__(self, cm: AbstractContextManager[_T]) -> None:
        self._cm = cm

    async def __aenter__(self) -> _T:
        return self._cm.__enter__()

    async def __aexit__(
        self,
        exc_type: type[BaseException] | None,
        exc_value: BaseException | None,
        traceback: types.TracebackType | None,
    ) -> bool | None:
        return self._cm.__exit__(exc_type, exc_value, traceback)


# File: fastapi/routing.py | Symbol: _wrap_gen_lifespan_context
def _wrap_gen_lifespan_context(
    lifespan_context: Callable[[Any], Generator[Any, Any, Any]],
) -> Callable[[Any], AbstractAsyncContextManager[Any]]:
    """
    Wrap a generator-based lifespan context into an async context manager.

    This is vendored from Starlette to avoid importing private symbols.
    """
    cmgr = contextlib.contextmanager(lifespan_context)

    @functools.wraps(cmgr)
    def wrapper(app: Any) -> _AsyncLiftContextManager[Any]:
        return _AsyncLiftContextManager(cmgr(app))

    return wrapper


# File: fastapi/routing.py | Symbol: _merge_lifespan_context
def _merge_lifespan_context(
    original_context: Lifespan[Any], nested_context: Lifespan[Any]
) -> Lifespan[Any]:
    @asynccontextmanager
    async def merged_lifespan(
        app: AppType,
    ) -> AsyncIterator[Mapping[str, Any] | None]:
        async with original_context(app) as maybe_original_state:
            async with nested_context(app) as maybe_nested_state:
                if maybe_nested_state is None and maybe_original_state is None:
                    yield None  # old ASGI compatibility
                else:
                    yield {**(maybe_nested_state or {}), **(maybe_original_state or {})}

    return merged_lifespan  # type: ignore[return-value]  # ty: ignore[invalid-return-type]


# File: fastapi/routing.py | Symbol: _DefaultLifespan
class _DefaultLifespan:
    """
    Default lifespan context manager that runs on_startup and on_shutdown handlers.

    This is a copy of the Starlette _DefaultLifespan class that was removed
    in Starlette. FastAPI keeps it to maintain backward compatibility with
    on_startup and on_shutdown event handlers.

    Ref: https://github.com/Kludex/starlette/pull/3117
    """

    def __init__(self, router: "APIRouter") -> None:
        self._router = router

    async def __aenter__(self) -> None:
        await self._router._startup()

    async def __aexit__(self, *exc_info: object) -> None:
        await self._router._shutdown()

    def __call__(self: _T, app: object) -> _T:
        return self


# File: fastapi/routing.py | Symbol: _extract_endpoint_context
def _extract_endpoint_context(func: Any) -> EndpointContext:
    """Extract endpoint context with caching to avoid repeated file I/O."""
    func_id = id(func)

    if func_id in _endpoint_context_cache:
        return _endpoint_context_cache[func_id]

    try:
        ctx: EndpointContext = {}

        if (source_file := inspect.getsourcefile(func)) is not None:
            ctx["file"] = source_file
        if (line_number := inspect.getsourcelines(func)[1]) is not None:
            ctx["line"] = line_number
        if (func_name := getattr(func, "__name__", None)) is not None:
            ctx["function"] = func_name
    except Exception:
        ctx = EndpointContext()

    _endpoint_context_cache[func_id] = ctx
    return ctx


# File: fastapi/routing.py | Symbol: serialize_response
async def serialize_response(
    *,
    field: ModelField | None = None,
    response_content: Any,
    include: IncEx | None = None,
    exclude: IncEx | None = None,
    by_alias: bool = True,
    exclude_unset: bool = False,
    exclude_defaults: bool = False,
    exclude_none: bool = False,
    is_coroutine: bool = True,
    endpoint_ctx: EndpointContext | None = None,
    dump_json: bool = False,
) -> Any:
    if field:
        if is_coroutine:
            value, errors = field.validate(response_content, {}, loc=("response",))
        else:
            value, errors = await run_in_threadpool(
                field.validate, response_content, {}, loc=("response",)
            )
        if errors:
            ctx = endpoint_ctx or EndpointContext()
            raise ResponseValidationError(
                errors=errors,
                body=response_content,
                endpoint_ctx=ctx,
            )
        serializer = field.serialize_json if dump_json else field.serialize
        return serializer(
            value,
            include=include,
            exclude=exclude,
            by_alias=by_alias,
            exclude_unset=exclude_unset,
            exclude_defaults=exclude_defaults,
            exclude_none=exclude_none,
        )

    else:
        return jsonable_encoder(response_content)


# File: fastapi/routing.py | Symbol: run_endpoint_function
async def run_endpoint_function(
    *, dependant: Dependant, values: dict[str, Any], is_coroutine: bool
) -> Any:
    # Only called by get_request_handler. Has been split into its own function to
    # facilitate profiling endpoints, since inner functions are harder to profile.
    assert dependant.call is not None, "dependant.call must be a function"

    if is_coroutine:
        return await dependant.call(**values)
    else:
        return await run_in_threadpool(dependant.call, **values)


# File: fastapi/routing.py | Symbol: _build_response_args
def _build_response_args(
    *, status_code: int | None, solved_result: Any
) -> dict[str, Any]:
    response_args: dict[str, Any] = {
        "background": solved_result.background_tasks,
    }
    # If status_code was set, use it, otherwise use the default from the
    # response class, in the case of redirect it's 307
    current_status_code = (
        status_code if status_code else solved_result.response.status_code
    )
    if current_status_code is not None:
        response_args["status_code"] = current_status_code
    if solved_result.response.status_code:
        response_args["status_code"] = solved_result.response.status_code
    return response_args


# File: fastapi/routing.py | Symbol: get_request_handler
def get_request_handler(
    dependant: Dependant,
    body_field: ModelField | None = None,
    status_code: int | None = None,
    response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse),
    response_field: ModelField | None = None,
    response_model_include: IncEx | None = None,
    response_model_exclude: IncEx | None = None,
    response_model_by_alias: bool = True,
    response_model_exclude_unset: bool = False,
    response_model_exclude_defaults: bool = False,
    response_model_exclude_none: bool = False,
    dependency_overrides_provider: Any | None = None,
    embed_body_fields: bool = False,
    strict_content_type: bool | DefaultPlaceholder = Default(True),
    stream_item_field: ModelField | None = None,
    is_json_stream: bool = False,
) -> Callable[[Request], Coroutine[Any, Any, Response]]:
    assert dependant.call is not None, "dependant.call must be a function"
    is_coroutine = dependant.is_coroutine_callable
    is_body_form = body_field and isinstance(body_field.field_info, params.Form)
    if isinstance(response_class, DefaultPlaceholder):
        actual_response_class: type[Response] = response_class.value
    else:
        actual_response_class = response_class
    is_sse_stream = lenient_issubclass(actual_response_class, EventSourceResponse)
    if isinstance(strict_content_type, DefaultPlaceholder):
        actual_strict_content_type: bool = strict_content_type.value
    else:
        actual_strict_content_type = strict_content_type

    async def app(request: Request) -> Response:
        response: Response | None = None
        file_stack = request.scope.get("fastapi_middleware_astack")
        assert isinstance(file_stack, AsyncExitStack), (
            "fastapi_middleware_astack not found in request scope"
        )

        # Extract endpoint context for error messages
        endpoint_ctx = (
            _extract_endpoint_context(dependant.call)
            if dependant.call
            else EndpointContext()
        )

        if dependant.path:
            # For mounted sub-apps, include the mount path prefix
            mount_path = request.scope.get("root_path", "").rstrip("/")
            endpoint_ctx["path"] = f"{request.method} {mount_path}{dependant.path}"

        # Read body and auto-close files
        try:
            body: Any = None
            if body_field:
                if is_body_form:
                    body = await request.form()
                    file_stack.push_async_callback(body.close)
                else:
                    body_bytes = await request.body()
                    if body_bytes:
                        json_body: Any = Undefined
                        content_type_value = request.headers.get("content-type")
                        if not content_type_value:
                            if not actual_strict_content_type:
                                json_body = await request.json()
                        else:
                            message = email.message.Message()
                            message["content-type"] = content_type_value
                            if message.get_content_maintype() == "application":
                                subtype = message.get_content_subtype()
                                if subtype == "json" or subtype.endswith("+json"):
                                    json_body = await request.json()
                        if json_body != Undefined:
                            body = json_body
                        else:
                            body = body_bytes
        except json.JSONDecodeError as e:
            validation_error = RequestValidationError(
                [
                    {
                        "type": "json_invalid",
                        "loc": ("body", e.pos),
                        "msg": "JSON decode error",
                        "input": {},
                        "ctx": {"error": e.msg},
                    }
                ],
                body=e.doc,
                endpoint_ctx=endpoint_ctx,
            )
            raise validation_error from e
        except HTTPException:
            # If a middleware raises an HTTPException, it should be raised again
            raise
        except Exception as e:
            http_error = HTTPException(
                status_code=400, detail="There was an error parsing the body"
            )
            raise http_error from e

        # Solve dependencies and run path operation function, auto-closing dependencies
        errors: list[Any] = []
        async_exit_stack = request.scope.get("fastapi_inner_astack")
        assert isinstance(async_exit_stack, AsyncExitStack), (
            "fastapi_inner_astack not found in request scope"
        )
        solved_result = await solve_dependencies(
            request=request,
            dependant=dependant,
            body=cast(dict[str, Any] | FormData | bytes | None, body),
            dependency_overrides_provider=dependency_overrides_provider,
            async_exit_stack=async_exit_stack,
            embed_body_fields=embed_body_fields,
        )
        errors = solved_result.errors
        assert dependant.call  # For types
        if not errors:
            # Shared serializer for stream items (JSONL and SSE).
            # Validates against stream_item_field when set, then
            # serializes to JSON bytes.
            def _serialize_data(data: Any) -> bytes:
                if stream_item_field:
                    value, errors_ = stream_item_field.validate(
                        data, {}, loc=("response",)
                    )
                    if errors_:
                        ctx = endpoint_ctx or EndpointContext()
                        raise ResponseValidationError(
                            errors=errors_,
                            body=data,
                            endpoint_ctx=ctx,
                        )
                    return stream_item_field.serialize_json(
                        value,
                        include=response_model_include,
                        exclude=response_model_exclude,
                        by_alias=response_model_by_alias,
                        exclude_unset=response_model_exclude_unset,
                        exclude_defaults=response_model_exclude_defaults,
                        exclude_none=response_model_exclude_none,
                    )
                else:
                    data = jsonable_encoder(data)
                    return json.dumps(data).encode("utf-8")

            if is_sse_stream:
                # Generator endpoint: stream as Server-Sent Events
                gen = dependant.call(**solved_result.values)

                def _serialize_sse_item(item: Any) -> bytes:
                    if isinstance(item, ServerSentEvent):
                        # User controls the event structure.
                        # Serialize the data payload if present.
                        # For ServerSentEvent items we skip stream_item_field
                        # validation (the user may mix types intentionally).
                        if item.raw_data is not None:
                            data_str: str | None = item.raw_data
                        elif item.data is not None:
                            if hasattr(item.data, "model_dump_json"):
                                data_str = item.data.model_dump_json()
                            else:
                                data_str = json.dumps(jsonable_encoder(item.data))
                        else:
                            data_str = None
                        return format_sse_event(
                            data_str=data_str,
                            event=item.event,
                            id=item.id,
                            retry=item.retry,
                            comment=item.comment,
                        )
                    else:
                        # Plain object: validate + serialize via
                        # stream_item_field (if set) and wrap in data field
                        return format_sse_event(
                            data_str=_serialize_data(item).decode("utf-8")
                        )

                if dependant.is_async_gen_callable:
                    sse_aiter: AsyncIterator[Any] = gen.__aiter__()
                else:
                    sse_aiter = iterate_in_threadpool(gen)

                @asynccontextmanager
                async def _sse_producer_cm() -> AsyncIterator[
                    ObjectReceiveStream[bytes]
                ]:
                    # Use a memory stream to decouple generator iteration
                    # from the keepalive timer. A producer task pulls items
                    # from the generator independently, so
                    # `anyio.fail_after` never wraps the generator's
                    # `__anext__` directly - avoiding CancelledError that
                    # would finalize the generator and also working for sync
                    # generators running in a thread pool.
                    #
                    # This context manager is entered on the request-scoped
                    # AsyncExitStack so its __aexit__ (which cancels the
                    # task group) is called by the exit stack after the
                    # streaming response completes — not by async generator
                    # finalization via GeneratorExit.
                    # Ref: https://peps.python.org/pep-0789/
                    send_stream, receive_stream = anyio.create_memory_object_stream[
                        bytes
                    ](max_buffer_size=1)

                    async def _producer() -> None:
                        async with send_stream:
                            async for raw_item in sse_aiter:
                                await send_stream.send(_serialize_sse_item(raw_item))

                    send_keepalive, receive_keepalive = (
                        anyio.create_memory_object_stream[bytes](max_buffer_size=1)
                    )

                    async def _keepalive_inserter() -> None:
                        """Read from the producer and forward to the output,
                        inserting keepalive comments on timeout."""
                        async with send_keepalive, receive_stream:
                            try:
                                while True:
                                    try:
                                        with anyio.fail_after(_PING_INTERVAL):
                                            data = await receive_stream.receive()
                                        await send_keepalive.send(data)
                                    except TimeoutError:
                                        await send_keepalive.send(KEEPALIVE_COMMENT)
                            except anyio.EndOfStream:
                                pass

                    async with anyio.create_task_group() as tg:
                        tg.start_soon(_producer)
                        tg.start_soon(_keepalive_inserter)
                        yield receive_keepalive
                        tg.cancel_scope.cancel()

                # Enter the SSE context manager on the request-scoped
                # exit stack. The stack outlives the streaming response,
                # so __aexit__ runs via proper structured teardown, not
                # via GeneratorExit thrown into an async generator.
                sse_receive_stream = await async_exit_stack.enter_async_context(
                    _sse_producer_cm()
                )
                # Ensure the receive stream is closed when the exit stack
                # unwinds, preventing ResourceWarning from __del__.
                async_exit_stack.push_async_callback(sse_receive_stream.aclose)

                async def _sse_with_checkpoints(
                    stream: ObjectReceiveStream[bytes],
                ) -> AsyncIterator[bytes]:
                    async for data in stream:
                        yield data
                        # Guarantee a checkpoint so cancellation can be
                        # delivered even when the producer is faster than
                        # the consumer and receive() never suspends.
                        await anyio.sleep(0)

                sse_stream_content: AsyncIterator[bytes] | Iterator[bytes] = (
                    _sse_with_checkpoints(sse_receive_stream)
                )

                response = StreamingResponse(
                    sse_stream_content,
                    media_type="text/event-stream",
                    background=solved_result.background_tasks,
                )
                response.headers["Cache-Control"] = "no-cache"
                # For Nginx proxies to not buffer server sent events
                response.headers["X-Accel-Buffering"] = "no"
                response.headers.raw.extend(solved_result.response.headers.raw)
            elif is_json_stream:
                # Generator endpoint: stream as JSONL
                gen = dependant.call(**solved_result.values)

                def _serialize_item(item: Any) -> bytes:
                    return _serialize_data(item) + b"\n"

                if dependant.is_async_gen_callable:

                    async def _async_stream_jsonl() -> AsyncIterator[bytes]:
                        async for item in gen:
                            yield _serialize_item(item)
                            # To allow for cancellation to trigger
                            # Ref: https://github.com/fastapi/fastapi/issues/14680
                            await anyio.sleep(0)

                    jsonl_stream_content: AsyncIterator[bytes] | Iterator[bytes] = (
                        _async_stream_jsonl()
                    )
                else:

                    def _sync_stream_jsonl() -> Iterator[bytes]:
                        for item in gen:  # ty: ignore[not-iterable]
                            yield _serialize_item(item)

                    jsonl_stream_content = _sync_stream_jsonl()

                response = StreamingResponse(
                    jsonl_stream_content,
                    media_type="application/jsonl",
                    background=solved_result.background_tasks,
                )
                response.headers.raw.extend(solved_result.response.headers.raw)
            elif dependant.is_async_gen_callable or dependant.is_gen_callable:
                # Raw streaming with explicit response_class (e.g. StreamingResponse)
                gen = dependant.call(**solved_result.values)
                if dependant.is_async_gen_callable:

                    async def _async_stream_raw(
                        async_gen: AsyncIterator[Any],
                    ) -> AsyncIterator[Any]:
                        async for chunk in async_gen:
                            yield chunk
                            # To allow for cancellation to trigger
                            # Ref: https://github.com/fastapi/fastapi/issues/14680
                            await anyio.sleep(0)

                    gen = _async_stream_raw(gen)
                response_args = _build_response_args(
                    status_code=status_code, solved_result=solved_result
                )
                response = actual_response_class(content=gen, **response_args)
                response.headers.raw.extend(solved_result.response.headers.raw)
            else:
                raw_response = await run_endpoint_function(
                    dependant=dependant,
                    values=solved_result.values,
                    is_coroutine=is_coroutine,
                )
                if isinstance(raw_response, Response):
                    if raw_response.background is None:
                        raw_response.background = solved_result.background_tasks
                    response = raw_response
                else:
                    response_args = _build_response_args(
                        status_code=status_code, solved_result=solved_result
                    )
                    # Use the fast path (dump_json) when no custom response
                    # class was set and a response field with a TypeAdapter
                    # exists. Serializes directly to JSON bytes via Pydantic's
                    # Rust core, skipping the intermediate Python dict +
                    # json.dumps() step.
                    use_dump_json = response_field is not None and isinstance(
                        response_class, DefaultPlaceholder
                    )
                    content = await serialize_response(
                        field=response_field,
                        response_content=raw_response,
                        include=response_model_include,
                        exclude=response_model_exclude,
                        by_alias=response_model_by_alias,
                        exclude_unset=response_model_exclude_unset,
                        exclude_defaults=response_model_exclude_defaults,
                        exclude_none=response_model_exclude_none,
                        is_coroutine=is_coroutine,
                        endpoint_ctx=endpoint_ctx,
                        dump_json=use_dump_json,
                    )
                    if use_dump_json:
                        response = Response(
                            content=content,
                            media_type="application/json",
                            **response_args,
                        )
                    else:
                        response = actual_response_class(content, **response_args)
                    if not is_body_allowed_for_status_code(response.status_code):
                        response.body = b""
                    response.headers.raw.extend(solved_result.response.headers.raw)
        if errors:
            validation_error = RequestValidationError(
                errors, body=body, endpoint_ctx=endpoint_ctx
            )
            raise validation_error

        # Return response
        assert response
        return response

    return app


# File: fastapi/routing.py | Symbol: get_websocket_app
def get_websocket_app(
    dependant: Dependant,
    dependency_overrides_provider: Any | None = None,
    embed_body_fields: bool = False,
) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]:
    async def app(websocket: WebSocket) -> None:
        endpoint_ctx = (
            _extract_endpoint_context(dependant.call)
            if dependant.call
            else EndpointContext()
        )
        if dependant.path:
            # For mounted sub-apps, include the mount path prefix
            mount_path = websocket.scope.get("root_path", "").rstrip("/")
            endpoint_ctx["path"] = f"WS {mount_path}{dependant.path}"
        async_exit_stack = websocket.scope.get("fastapi_inner_astack")
        assert isinstance(async_exit_stack, AsyncExitStack), (
            "fastapi_inner_astack not found in request scope"
        )
        solved_result = await solve_dependencies(
            request=websocket,
            dependant=dependant,
            dependency_overrides_provider=dependency_overrides_provider,
            async_exit_stack=async_exit_stack,
            embed_body_fields=embed_body_fields,
        )
        if solved_result.errors:
            raise WebSocketRequestValidationError(
                solved_result.errors,
                endpoint_ctx=endpoint_ctx,
            )
        assert dependant.call is not None, "dependant.call must be a function"
        await dependant.call(**solved_result.values)

    return app


# File: fastapi/routing.py | Symbol: APIWebSocketRoute
class APIWebSocketRoute(routing.WebSocketRoute):
    def __init__(
        self,
        path: str,
        endpoint: Callable[..., Any],
        *,
        name: str | None = None,
        dependencies: Sequence[params.Depends] | None = None,
        dependency_overrides_provider: Any | None = None,
    ) -> None:
        self.path = path
        self.endpoint = endpoint
        self.name = get_name(endpoint) if name is None else name
        self.dependencies = list(dependencies or [])
        self.path_regex, self.path_format, self.param_convertors = compile_path(path)
        (
            self.dependant,
            self._flat_dependant,
            self._embed_body_fields,
        ) = _build_dependant_with_parameterless_dependencies(
            path=self.path_format,
            call=self.endpoint,
            dependencies=self.dependencies,
        )
        self.app = websocket_session(
            get_websocket_app(
                dependant=self.dependant,
                dependency_overrides_provider=dependency_overrides_provider,
                embed_body_fields=self._embed_body_fields,
            )
        )

    def matches(self, scope: Scope) -> tuple[Match, Scope]:
        match, child_scope = super().matches(scope)
        if match != Match.NONE:
            child_scope["route"] = self
        return match, child_scope


# File: fastapi/routing.py | Symbol: _frontend_dependency_endpoint
def _frontend_dependency_endpoint() -> None:
    pass  # pragma: no cover


# File: fastapi/routing.py | Symbol: _build_dependant_with_parameterless_dependencies
def _build_dependant_with_parameterless_dependencies(
    *,
    path: str,
    call: Callable[..., Any],
    dependencies: Sequence[params.Depends],
) -> tuple[Dependant, Dependant, bool]:
    dependant = get_dependant(path=path, call=call, scope="function")
    for depends in dependencies[::-1]:
        dependant.dependencies.insert(
            0,
            get_parameterless_sub_dependant(depends=depends, path=path),
        )
    flat_dependant = get_flat_dependant(dependant)
    embed_body_fields = _should_embed_body_fields(flat_dependant.body_params)
    return dependant, flat_dependant, embed_body_fields


# File: fastapi/routing.py | Symbol: _get_fastapi_scope
def _get_fastapi_scope(scope: Scope) -> dict[str, Any]:
    fastapi_scope = scope.setdefault(_FASTAPI_SCOPE_KEY, {})
    assert isinstance(fastapi_scope, dict)
    return fastapi_scope


# File: fastapi/routing.py | Symbol: _update_scope
def _update_scope(scope: Scope, child_scope: Scope) -> None:
    fastapi_child_scope = child_scope.get(_FASTAPI_SCOPE_KEY)
    for key, value in child_scope.items():
        if key != _FASTAPI_SCOPE_KEY:
            scope[key] = value
    if isinstance(fastapi_child_scope, dict):
        _get_fastapi_scope(scope).update(fastapi_child_scope)


# File: fastapi/routing.py | Symbol: _get_scope_effective_route_context
def _get_scope_effective_route_context(scope: Scope) -> Any | None:
    return scope.get(_FASTAPI_SCOPE_KEY, {}).get(_FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY)


# File: fastapi/routing.py | Symbol: _get_scope_included_router
def _get_scope_included_router(scope: Scope) -> Any | None:
    return scope.get(_FASTAPI_SCOPE_KEY, {}).get(_FASTAPI_INCLUDED_ROUTER_KEY)


# File: fastapi/routing.py | Symbol: _frontend_scope_specificity
def _frontend_scope_specificity(scope: Scope) -> int | None:
    specificity = scope.get(_FASTAPI_SCOPE_KEY, {}).get(
        _FASTAPI_FRONTEND_SPECIFICITY_KEY
    )
    if isinstance(specificity, int):
        return specificity
    return None


# File: fastapi/routing.py | Symbol: _restore_fastapi_scope_key
def _restore_fastapi_scope_key(scope: Scope, key: str, previous: Any) -> None:
    fastapi_scope = scope.get(_FASTAPI_SCOPE_KEY)
    if not isinstance(fastapi_scope, dict):
        return
    if previous is _SCOPE_MISSING:
        fastapi_scope.pop(key, None)
    else:
        fastapi_scope[key] = previous


# File: fastapi/routing.py | Symbol: _APIRouteLike
class _APIRouteLike(Protocol):
    path: str
    endpoint: Callable[..., Any]
    stream_item_type: Any | None
    response_model: Any
    summary: str | None
    response_description: str
    deprecated: bool | None
    operation_id: str | None
    response_model_include: IncEx | None
    response_model_exclude: IncEx | None
    response_model_by_alias: bool
    response_model_exclude_unset: bool
    response_model_exclude_defaults: bool
    response_model_exclude_none: bool
    include_in_schema: bool
    response_class: type[Response] | DefaultPlaceholder
    dependency_overrides_provider: Any | None
    callbacks: list[BaseRoute] | None
    openapi_extra: dict[str, Any] | None
    generate_unique_id_function: Callable[[Any], str] | DefaultPlaceholder
    strict_content_type: bool | DefaultPlaceholder
    tags: list[str | Enum]
    responses: dict[int | str, dict[str, Any]]
    name: str
    path_regex: Any
    path_format: str
    param_convertors: dict[str, Any]
    methods: set[str]
    unique_id: str
    status_code: int | None
    response_field: ModelField | None
    stream_item_field: ModelField | None
    dependencies: list[params.Depends]
    description: str
    response_fields: dict[int | str, ModelField]
    dependant: Dependant
    _flat_dependant: Dependant
    _embed_body_fields: bool
    body_field: ModelField | None
    is_sse_stream: bool
    is_json_stream: bool


# File: fastapi/routing.py | Symbol: _populate_api_route_state
def _populate_api_route_state(
    route: _APIRouteLike,
    path: str,
    endpoint: Callable[..., Any],
    *,
    response_model: Any = Default(None),
    status_code: int | None = None,
    tags: list[str | Enum] | None = None,
    dependencies: Sequence[params.Depends] | None = None,
    summary: str | None = None,
    description: str | None = None,
    response_description: str = "Successful Response",
    responses: dict[int | str, dict[str, Any]] | None = None,
    deprecated: bool | None = None,
    name: str | None = None,
    methods: set[str] | list[str] | None = None,
    operation_id: str | None = None,
    response_model_include: IncEx | None = None,
    response_model_exclude: IncEx | None = None,
    response_model_by_alias: bool = True,
    response_model_exclude_unset: bool = False,
    response_model_exclude_defaults: bool = False,
    response_model_exclude_none: bool = False,
    include_in_schema: bool = True,
    response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse),
    dependency_overrides_provider: Any | None = None,
    callbacks: list[BaseRoute] | None = None,
    openapi_extra: dict[str, Any] | None = None,
    generate_unique_id_function: Callable[[Any], str] | DefaultPlaceholder = Default(
        generate_unique_id
    ),
    strict_content_type: bool | DefaultPlaceholder = Default(True),
) -> None:
    route.path = path
    route.endpoint = endpoint
    route.stream_item_type = None
    if isinstance(response_model, DefaultPlaceholder):
        return_annotation = get_typed_return_annotation(endpoint)
        if lenient_issubclass(return_annotation, Response):
            response_model = None
        else:
            stream_item = get_stream_item_type(return_annotation)
            if stream_item is not None:
                # Extract item type for JSONL or SSE streaming when
                # response_class is DefaultPlaceholder (JSONL) or
                # EventSourceResponse (SSE).
                # ServerSentEvent is excluded: it's a transport
                # wrapper, not a data model, so it shouldn't feed
                # into validation or OpenAPI schema generation.
                if (
                    isinstance(response_class, DefaultPlaceholder)
                    or lenient_issubclass(response_class, EventSourceResponse)
                ) and not lenient_issubclass(stream_item, ServerSentEvent):
                    route.stream_item_type = stream_item
                response_model = None
            else:
                response_model = return_annotation
    route.response_model = response_model
    route.summary = summary
    route.response_description = response_description
    route.deprecated = deprecated
    route.operation_id = operation_id
    route.response_model_include = response_model_include
    route.response_model_exclude = response_model_exclude
    route.response_model_by_alias = response_model_by_alias
    route.response_model_exclude_unset = response_model_exclude_unset
    route.response_model_exclude_defaults = response_model_exclude_defaults
    route.response_model_exclude_none = response_model_exclude_none
    route.include_in_schema = include_in_schema
    route.response_class = response_class
    route.dependency_overrides_provider = dependency_overrides_provider
    route.callbacks = callbacks
    route.openapi_extra = openapi_extra
    route.generate_unique_id_function = generate_unique_id_function
    route.strict_content_type = strict_content_type
    route.tags = tags or []
    route.responses = responses or {}
    route.name = get_name(endpoint) if name is None else name
    route.path_regex, route.path_format, route.param_convertors = compile_path(path)
    if methods is None:
        methods = ["GET"]
    route.methods = {method.upper() for method in methods}
    if isinstance(generate_unique_id_function, DefaultPlaceholder):
        current_generate_unique_id: Callable[[Any], str] = (
            generate_unique_id_function.value
        )
    else:
        current_generate_unique_id = generate_unique_id_function
    route.unique_id = route.operation_id or current_generate_unique_id(route)
    # normalize enums e.g. http.HTTPStatus
    if isinstance(status_code, IntEnum):
        status_code = int(status_code)
    route.status_code = status_code
    if route.response_model:
        assert is_body_allowed_for_status_code(status_code), (
            f"Status code {status_code} must not have a response body"
        )
        response_name = "Response_" + route.unique_id
        route.response_field = create_model_field(
            name=response_name,
            type_=route.response_model,
            mode="serialization",
        )
    else:
        route.response_field = None
    if route.stream_item_type:
        stream_item_name = "StreamItem_" + route.unique_id
        route.stream_item_field = create_model_field(
            name=stream_item_name,
            type_=route.stream_item_type,
            mode="serialization",
        )
    else:
        route.stream_item_field = None
    route.dependencies = list(dependencies or [])
    route.description = description or inspect.cleandoc(route.endpoint.__doc__ or "")
    # if a "form feed" character (page break) is found in the description text,
    # truncate description text to the content preceding the first "form feed"
    route.description = route.description.split("\f")[0].strip()
    response_fields = {}
    for additional_status_code, response in route.responses.items():
        assert isinstance(response, dict), "An additional response must be a dict"
        model = response.get("model")
        if model:
            assert is_body_allowed_for_status_code(additional_status_code), (
                f"Status code {additional_status_code} must not have a response body"
            )
            response_name = f"Response_{additional_status_code}_{route.unique_id}"
            response_field = create_model_field(
                name=response_name, type_=model, mode="serialization"
            )
            response_fields[additional_status_code] = response_field
    if response_fields:
        route.response_fields = response_fields
    else:
        route.response_fields = {}

    assert callable(endpoint), "An endpoint must be a callable"
    (
        route.dependant,
        route._flat_dependant,
        route._embed_body_fields,
    ) = _build_dependant_with_parameterless_dependencies(
        path=route.path_format,
        call=route.endpoint,
        dependencies=route.dependencies,
    )
    route.body_field = get_body_field(
        flat_dependant=route._flat_dependant,
        name=route.unique_id,
        embed_body_fields=route._embed_body_fields,
    )
    # Detect generator endpoints that should stream as JSONL or SSE
    is_generator = (
        route.dependant.is_async_gen_callable or route.dependant.is_gen_callable
    )
    route.is_sse_stream = is_generator and lenient_issubclass(
        response_class, EventSourceResponse
    )
    route.is_json_stream = is_generator and isinstance(
        response_class, DefaultPlaceholder
    )


# File: fastapi/routing.py | Class: APIRoute | Symbol: APIRoute.__init__
def __init__(
        self,
        path: str,
        endpoint: Callable[..., Any],
        *,
        response_model: Any = Default(None),
        status_code: int | None = None,
        tags: list[str | Enum] | None = None,
        dependencies: Sequence[params.Depends] | None = None,
        summary: str | None = None,
        description: str | None = None,
        response_description: str = "Successful Response",
        responses: dict[int | str, dict[str, Any]] | None = None,
        deprecated: bool | None = None,
        name: str | None = None,
        methods: set[str] | list[str] | None = None,
        operation_id: str | None = None,
        response_model_include: IncEx | None = None,
        response_model_exclude: IncEx | None = None,
        response_model_by_alias: bool = True,
        response_model_exclude_unset: bool = False,
        response_model_exclude_defaults: bool = False,
        response_model_exclude_none: bool = False,
        include_in_schema: bool = True,
        response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse),
        dependency_overrides_provider: Any | None = None,
        callbacks: list[BaseRoute] | None = None,
        openapi_extra: dict[str, Any] | None = None,
        generate_unique_id_function: Callable[["APIRoute"], str]
        | DefaultPlaceholder = Default(generate_unique_id),
        strict_content_type: bool | DefaultPlaceholder = Default(True),
    ) -> None:
        _populate_api_route_state(
            cast(_APIRouteLike, self),
            path,
            endpoint,
            response_model=response_model,
            status_code=status_code,
            tags=tags,
            dependencies=dependencies,
            summary=summary,
            description=description,
            response_description=response_description,
            responses=responses,
            deprecated=deprecated,
            name=name,
            methods=methods,
            operation_id=operation_id,
            response_model_include=response_model_include,
            response_model_exclude=response_model_exclude,
            response_model_by_alias=response_model_by_alias,
            response_model_exclude_unset=response_model_exclude_unset,
            response_model_exclude_defaults=response_model_exclude_defaults,
            response_model_exclude_none=response_model_exclude_none,
            include_in_schema=include_in_schema,
            response_class=response_class,
            dependency_overrides_provider=dependency_overrides_provider,
            callbacks=callbacks,
            openapi_extra=openapi_extra,
            generate_unique_id_function=generate_unique_id_function,
            strict_content_type=strict_content_type,
        )
        self.app = request_response(self.get_route_handler())


# File: fastapi/routing.py | Class: APIRoute | Symbol: APIRoute.get_route_handler
def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]:
        route = cast(_APIRouteLike, self)
        # TODO: Replace or deprecate this no-scope hook so included-route
        # effective context can be passed explicitly instead of via ContextVar.
        effective_context = _effective_route_context_var.get()
        if effective_context is not None and effective_context.original_route is self:
            route = cast(_APIRouteLike, effective_context)
        return get_request_handler(
            dependant=route.dependant,
            body_field=route.body_field,
            status_code=route.status_code,
            response_class=route.response_class,
            response_field=route.response_field,
            response_model_include=route.response_model_include,
            response_model_exclude=route.response_model_exclude,
            response_model_by_alias=route.response_model_by_alias,
            response_model_exclude_unset=route.response_model_exclude_unset,
            response_model_exclude_defaults=route.response_model_exclude_defaults,
            response_model_exclude_none=route.response_model_exclude_none,
            dependency_overrides_provider=route.dependency_overrides_provider,
            embed_body_fields=route._embed_body_fields,
            strict_content_type=route.strict_content_type,
            stream_item_field=route.stream_item_field,
            is_json_stream=route.is_json_stream,
        )


# File: fastapi/routing.py | Class: APIRoute | Symbol: APIRoute.matches
def matches(self, scope: Scope) -> tuple[Match, Scope]:
        effective_context = _get_scope_effective_route_context(scope)
        if effective_context is not None and effective_context.original_route is self:
            match, child_scope = effective_context.matches(scope)
        else:
            match, child_scope = super().matches(scope)
        if match != Match.NONE:
            child_scope["route"] = self
        return match, child_scope


# File: fastapi/routing.py | Class: APIRoute | Symbol: APIRoute.handle
async def handle(self, scope: Scope, receive: Receive, send: Send) -> None:
        effective_context = _get_scope_effective_route_context(scope)
        if effective_context is not None and effective_context.original_route is self:
            methods = effective_context.methods
            if methods and scope["method"] not in methods:
                headers = {"Allow": ", ".join(methods)}
                if "app" in scope:
                    raise HTTPException(status_code=405, headers=headers)
                response = PlainTextResponse(
                    "Method Not Allowed", status_code=405, headers=headers
                )
                await response(scope, receive, send)
                return
            token = _effective_route_context_var.set(effective_context)
            try:
                app = request_response(self.get_route_handler())
            finally:
                _effective_route_context_var.reset(token)
            await app(scope, receive, send)
            return
        await super().handle(scope, receive, send)


# File: fastapi/routing.py | Symbol: _RouterIncludeContext
@dataclass
class _RouterIncludeContext:
    included_router: "APIRouter"
    prefix: str = ""
    tags: list[str | Enum] = field(default_factory=list)
    dependencies: list[params.Depends] = field(default_factory=list)
    default_response_class: type[Response] | DefaultPlaceholder = field(
        default_factory=lambda: Default(JSONResponse)
    )
    responses: dict[int | str, dict[str, Any]] = field(default_factory=dict)
    callbacks: list[BaseRoute] = field(default_factory=list)
    deprecated: bool | None = None
    include_in_schema: bool = True
    generate_unique_id_function: Callable[[APIRoute], str] | DefaultPlaceholder = field(
        default_factory=lambda: Default(generate_unique_id)
    )
    strict_content_type: bool | DefaultPlaceholder = field(
        default_factory=lambda: Default(True)
    )
    dependency_overrides_provider: Any | None = None

    @classmethod
    def for_include(
        cls,
        *,
        parent_router: "APIRouter",
        included_router: "APIRouter",
        prefix: str = "",
        tags: list[str | Enum] | None = None,
        dependencies: Sequence[params.Depends] | None = None,
        default_response_class: type[Response] | DefaultPlaceholder = Default(
            JSONResponse
        ),
        responses: dict[int | str, dict[str, Any]] | None = None,
        callbacks: list[BaseRoute] | None = None,
        deprecated: bool | None = None,
        include_in_schema: bool = True,
        generate_unique_id_function: Callable[[APIRoute], str]
        | DefaultPlaceholder = Default(generate_unique_id),
    ) -> "_RouterIncludeContext":
        return cls(
            included_router=included_router,
            prefix=parent_router.prefix + prefix,
            tags=[*parent_router.tags, *(tags or [])],
            dependencies=[*parent_router.dependencies, *(dependencies or [])],
            default_response_class=get_value_or_default(
                default_response_class, parent_router.default_response_class
            ),
            responses={**parent_router.responses, **(responses or {})},
            callbacks=[*parent_router.callbacks, *(callbacks or [])],
            deprecated=deprecated or parent_router.deprecated,
            include_in_schema=parent_router.include_in_schema and include_in_schema,
            generate_unique_id_function=get_value_or_default(
                generate_unique_id_function, parent_router.generate_unique_id_function
            ),
            strict_content_type=parent_router.strict_content_type,
            dependency_overrides_provider=parent_router.dependency_overrides_provider,
        )

    def combine(
        self, child_context: "_RouterIncludeContext"
    ) -> "_RouterIncludeContext":
        return _RouterIncludeContext(
            included_router=child_context.included_router,
            prefix=self.prefix + child_context.prefix,
            tags=[*self.tags, *child_context.tags],
            dependencies=[*self.dependencies, *child_context.dependencies],
            default_response_class=get_value_or_default(
                child_context.default_response_class, self.default_response_class
            ),
            responses={**self.responses, **child_context.responses},
            callbacks=[*self.callbacks, *child_context.callbacks],
            deprecated=self.deprecated or child_context.deprecated,
            include_in_schema=self.include_in_schema
            and child_context.include_in_schema,
            generate_unique_id_function=get_value_or_default(
                child_context.generate_unique_id_function,
                self.generate_unique_id_function,
            ),
            strict_content_type=get_value_or_default(
                child_context.strict_content_type, self.strict_content_type
            ),
            dependency_overrides_provider=self.dependency_overrides_provider,
        )

    def path_for(self, route: _RouteWithPath) -> str:
        return self.prefix + route.path


# File: fastapi/routing.py | Class: _EffectiveRouteContext | Symbol: _EffectiveRouteContext.from_api_route
@classmethod
    def from_api_route(
        cls,
        *,
        original_route: APIRoute,
        include_context: _RouterIncludeContext,
    ) -> "_EffectiveRouteContext":
        route = cast(_APIRouteLike, original_route)
        context = cls(original_route=original_route)
        _populate_api_route_state(
            cast(_APIRouteLike, context),
            include_context.path_for(original_route),
            route.endpoint,
            response_model=route.response_model,
            status_code=route.status_code,
            tags=[*include_context.tags, *route.tags],
            dependencies=[*include_context.dependencies, *route.dependencies],
            summary=route.summary,
            description=route.description,
            response_description=route.response_description,
            responses={**include_context.responses, **route.responses},
            deprecated=route.deprecated or include_context.deprecated,
            methods=route.methods,
            operation_id=route.operation_id,
            response_model_include=route.response_model_include,
            response_model_exclude=route.response_model_exclude,
            response_model_by_alias=route.response_model_by_alias,
            response_model_exclude_unset=route.response_model_exclude_unset,
            response_model_exclude_defaults=route.response_model_exclude_defaults,
            response_model_exclude_none=route.response_model_exclude_none,
            include_in_schema=route.include_in_schema
            and include_context.include_in_schema,
            response_class=get_value_or_default(
                route.response_class,
                include_context.included_router.default_response_class,
                include_context.default_response_class,
            ),
            name=route.name,
            dependency_overrides_provider=include_context.dependency_overrides_provider,
            callbacks=[*include_context.callbacks, *(route.callbacks or [])],
            openapi_extra=route.openapi_extra,
            generate_unique_id_function=get_value_or_default(
                route.generate_unique_id_function,
                include_context.included_router.generate_unique_id_function,
                include_context.generate_unique_id_function,
            ),
            strict_content_type=get_value_or_default(
                route.strict_content_type,
                include_context.included_router.strict_content_type,
                include_context.strict_content_type,
            ),
        )
        return context


# File: fastapi/routing.py | Class: _EffectiveRouteContext | Symbol: _EffectiveRouteContext.from_frontend_route_group
@classmethod
    def from_frontend_route_group(
        cls,
        *,
        original_route: "_FrontendRouteGroup",
        include_context: _RouterIncludeContext,
    ) -> "_EffectiveRouteContext":
        dependencies = [*include_context.dependencies, *original_route.dependencies]
        context = cls(
            original_route=original_route,
            frontend_prefix=include_context.prefix,
            dependencies=dependencies,
            dependency_overrides_provider=include_context.dependency_overrides_provider,
        )
        (
            context.dependant,
            context._flat_dependant,
            context._embed_body_fields,
        ) = _build_dependant_with_parameterless_dependencies(
            path="",
            call=_frontend_dependency_endpoint,
            dependencies=dependencies,
        )
        return context


# File: fastapi/routing.py | Class: _EffectiveRouteContext | Symbol: _EffectiveRouteContext.matches
def matches(self, scope: Scope) -> tuple[Match, Scope]:
        if isinstance(self.original_route, _FrontendRouteGroup):
            return self.original_route.matches_with_prefix(scope, self.frontend_prefix)
        if not isinstance(self.original_route, APIRoute):
            assert self.starlette_route is not None
            return self.starlette_route.matches(scope)
        if scope["type"] != "http":
            return Match.NONE, {}
        route_path = get_route_path(scope)
        match = self.path_regex.match(route_path)
        if not match:
            return Match.NONE, {}
        matched_params = match.groupdict()
        for key, value in matched_params.items():
            matched_params[key] = self.param_convertors[key].convert(value)
        path_params = dict(scope.get("path_params", {}))
        path_params.update(matched_params)
        child_scope = {"endpoint": self.endpoint, "path_params": path_params}
        methods = self.methods
        if methods and scope["method"] not in methods:
            return Match.PARTIAL, child_scope
        return Match.FULL, child_scope


# File: fastapi/routing.py | Class: _EffectiveRouteContext | Symbol: _EffectiveRouteContext.url_path_for
def url_path_for(self, name: str, /, **path_params: Any) -> Any:
        if not isinstance(self.original_route, APIRoute):
            assert self.starlette_route is not None
            return self.starlette_route.url_path_for(name, **path_params)
        seen_params = set(path_params.keys())
        param_convertors = self.param_convertors
        expected_params = set(param_convertors.keys())
        if name != self.name or seen_params != expected_params:
            raise routing.NoMatchFound(name, path_params)
        path, remaining_params = routing.replace_params(
            self.path_format, param_convertors, path_params
        )
        assert not remaining_params
        return URLPath(path=path, protocol="http")


# File: fastapi/routing.py | Symbol: RouteContext
@dataclass(frozen=True)
class RouteContext:
    route: BaseRoute
    _route_context: _EffectiveRouteContext | None = field(default=None, repr=False)

    @property
    def original_route(self) -> BaseRoute:
        if self._route_context is not None:
            return self._route_context.original_route
        return self.route

    @property
    def _effective_route(self) -> BaseRoute | _EffectiveRouteContext:
        if self._route_context is not None:
            return self._route_context
        return self.route

    @property
    def path(self) -> str | None:
        return getattr(self._effective_route, "path", None)

    @property
    def path_format(self) -> str | None:
        return getattr(self._effective_route, "path_format", None)

    @property
    def name(self) -> str | None:
        return getattr(self._effective_route, "name", None)

    @property
    def methods(self) -> set[str] | None:
        return getattr(self._effective_route, "methods", None)

    @property
    def endpoint(self) -> Callable[..., Any] | None:
        return getattr(self._effective_route, "endpoint", None)

    def __getattr__(self, name: str) -> Any:
        return getattr(self._effective_route, name)


# File: fastapi/routing.py | Class: _IncludedRouter | Symbol: _IncludedRouter.effective_candidates
def effective_candidates(self) -> list["_EffectiveRouteContext | _IncludedRouter"]:
        routes_version = self.original_router._get_routes_version()
        if routes_version == self._effective_candidates_version:
            return self._effective_candidates
        self._effective_candidates = []
        candidates = self.original_router.routes
        for route in candidates:
            if isinstance(route, _IncludedRouter):
                child_context = self.include_context.combine(route.include_context)
                child_branch = _IncludedRouter(
                    original_router=route.original_router,
                    include_context=child_context,
                )
                self._effective_candidates.append(child_branch)
                continue
            route_context = self._build_effective_context(route)
            if route_context is not None:
                self._effective_candidates.append(route_context)
        self._effective_candidates_version = routes_version
        return self._effective_candidates


# File: fastapi/routing.py | Class: _IncludedRouter | Symbol: _IncludedRouter.effective_low_priority_routes
def effective_low_priority_routes(self) -> list["_EffectiveRouteContext"]:
        routes_version = self.original_router._get_routes_version()
        if routes_version == self._effective_low_priority_routes_version:
            return self._effective_low_priority_routes
        self._effective_low_priority_routes = []
        for route in self.original_router._low_priority_routes:
            route_context = self._build_effective_context(route)
            if route_context is not None:
                self._effective_low_priority_routes.append(route_context)
        for route in self.original_router.routes:
            if isinstance(route, _IncludedRouter):
                child_context = self.include_context.combine(route.include_context)
                child_branch = _IncludedRouter(
                    original_router=route.original_router,
                    include_context=child_context,
                )
                self._effective_low_priority_routes.extend(
                    child_branch.effective_low_priority_routes()
                )
        self._effective_low_priority_routes_version = routes_version
        return self._effective_low_priority_routes


# File: fastapi/routing.py | Class: _IncludedRouter | Symbol: _IncludedRouter._build_effective_context
def _build_effective_context(
        self, route: BaseRoute
    ) -> _EffectiveRouteContext | None:
        if isinstance(route, APIRoute):
            return _EffectiveRouteContext.from_api_route(
                original_route=route,
                include_context=self.include_context,
            )
        if isinstance(route, _FrontendRouteGroup):
            return _EffectiveRouteContext.from_frontend_route_group(
                original_route=route,
                include_context=self.include_context,
            )
        if isinstance(route, routing.Route):
            starlette_route: BaseRoute = routing.Route(
                self.include_context.path_for(route),
                endpoint=route.endpoint,
                methods=list(route.methods or []),
                name=route.name,
                include_in_schema=route.include_in_schema,
            )
            return _EffectiveRouteContext(
                original_route=route,
                starlette_route=starlette_route,
            )
        if isinstance(route, APIWebSocketRoute):
            starlette_route = APIWebSocketRoute(
                self.include_context.path_for(route),
                endpoint=route.endpoint,
                name=route.name,
                dependencies=[*self.include_context.dependencies, *route.dependencies],
                dependency_overrides_provider=(
                    self.include_context.dependency_overrides_provider
                ),
            )
            return _EffectiveRouteContext(
                original_route=route,
                starlette_route=starlette_route,
            )
        if isinstance(route, routing.WebSocketRoute):
            starlette_route = routing.WebSocketRoute(
                self.include_context.path_for(route), route.endpoint, name=route.name
            )
            return _EffectiveRouteContext(
                original_route=route,
                starlette_route=starlette_route,
            )
        if isinstance(route, routing.Mount):
            starlette_route = copy.copy(route)
            starlette_route.path = self.include_context.path_for(route).rstrip("/")
            (
                starlette_route.path_regex,
                starlette_route.path_format,
                starlette_route.param_convertors,
            ) = compile_path(starlette_route.path + "/{path:path}")
            return _EffectiveRouteContext(
                original_route=route,
                starlette_route=starlette_route,
            )
        if isinstance(route, routing.Host):
            if self.include_context.prefix:
                prefixed_app: ASGIApp = routing.Router(
                    routes=[routing.Mount(self.include_context.prefix, app=route.app)]
                )
            else:
                prefixed_app = route.app
            starlette_route = routing.Host(
                route.host, app=prefixed_app, name=route.name
            )
            return _EffectiveRouteContext(
                original_route=route,
                starlette_route=starlette_route,
            )
        return None


# File: fastapi/routing.py | Class: _IncludedRouter | Symbol: _IncludedRouter._match
def _match(
        self, scope: Scope
    ) -> tuple[Match, Scope, BaseRoute | None, _EffectiveRouteContext | None]:
        partial: tuple[Scope, BaseRoute, _EffectiveRouteContext | None] | None = None
        for candidate in self.effective_candidates():
            if isinstance(candidate, _IncludedRouter):
                match, child_scope = candidate.matches(scope)
                route: BaseRoute = candidate
                route_context = None
            elif isinstance(candidate.original_route, APIRoute):
                route_context = candidate
                fastapi_scope = _get_fastapi_scope(scope)
                previous_context = fastapi_scope.get(
                    _FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY, _SCOPE_MISSING
                )
                fastapi_scope[_FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY] = route_context
                try:
                    match, child_scope = candidate.original_route.matches(scope)
                finally:
                    _restore_fastapi_scope_key(
                        scope, _FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY, previous_context
                    )
                route = candidate.original_route
            else:
                route_context = candidate
                match, child_scope = candidate.matches(scope)
                route = candidate.starlette_route or candidate.original_route
            if match == Match.FULL:
                return match, child_scope, route, route_context
            if match == Match.PARTIAL and partial is None:
                partial = (child_scope, route, route_context)
        if partial is not None:
            child_scope, route, route_context = partial
            return Match.PARTIAL, child_scope, route, route_context
        return Match.NONE, {}, None, None


# File: fastapi/routing.py | Class: _IncludedRouter | Symbol: _IncludedRouter.matches
def matches(self, scope: Scope) -> tuple[Match, Scope]:
        fastapi_scope = _get_fastapi_scope(scope)
        previous_router = fastapi_scope.get(
            _FASTAPI_INCLUDED_ROUTER_KEY, _SCOPE_MISSING
        )
        fastapi_scope[_FASTAPI_INCLUDED_ROUTER_KEY] = self
        try:
            match, _ = self.original_router.matches(scope)
            return match, {}
        finally:
            _restore_fastapi_scope_key(
                scope, _FASTAPI_INCLUDED_ROUTER_KEY, previous_router
            )


# File: fastapi/routing.py | Class: _IncludedRouter | Symbol: _IncludedRouter.handle
async def handle(self, scope: Scope, receive: Receive, send: Send) -> None:
        _get_fastapi_scope(scope)[_FASTAPI_INCLUDED_ROUTER_KEY] = self
        await self.original_router.handle(scope, receive, send)


# File: fastapi/routing.py | Class: _IncludedRouter | Symbol: _IncludedRouter._handle_selected
async def _handle_selected(
        self, scope: Scope, receive: Receive, send: Send
    ) -> None:
        match, child_scope, route, effective_context = self._match(scope)
        if match == Match.NONE or route is None:
            await self.original_router.default(scope, receive, send)
            return
        scope.update(child_scope)
        if isinstance(route, _IncludedRouter):
            await route.handle(scope, receive, send)
            return
        if effective_context is not None:
            _get_fastapi_scope(scope)[_FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY] = (
                effective_context
            )
            original_route = effective_context.original_route
            if isinstance(original_route, APIRoute):
                scope["route"] = original_route
                await original_route.handle(scope, receive, send)
                return
        await route.handle(scope, receive, send)


# File: fastapi/routing.py | Class: _IncludedRouter | Symbol: _IncludedRouter.effective_route_contexts
def effective_route_contexts(self) -> Iterator[_EffectiveRouteContext]:
        for candidate in self.effective_candidates():
            if isinstance(candidate, _IncludedRouter):
                yield from candidate.effective_route_contexts()
            else:
                yield candidate


# File: fastapi/routing.py | Class: _IncludedRouter | Symbol: _IncludedRouter.url_path_for
def url_path_for(self, name: str, /, **path_params: Any) -> Any:
        for route_context in self.effective_route_contexts():
            try:
                return route_context.url_path_for(name, **path_params)
            except routing.NoMatchFound:
                pass
        raise routing.NoMatchFound(name, path_params)


# File: fastapi/routing.py | Symbol: _iter_included_route_candidates
def _iter_included_route_candidates(routes: Sequence[BaseRoute]) -> Iterator[BaseRoute]:
    for route, route_context in _iter_routes_with_context(routes):
        if route_context is not None and route_context.starlette_route is not None:
            yield route_context.starlette_route
        else:
            yield route


# File: fastapi/routing.py | Symbol: iter_route_contexts
def iter_route_contexts(
    routes: Sequence[BaseRoute | RouteContext],
) -> Iterator[RouteContext]:
    for route in routes:
        if isinstance(route, RouteContext):
            yield route
            continue
        for original_route, route_context in _iter_routes_with_context([route]):
            if route_context is None:
                yield RouteContext(original_route)
            else:
                yield RouteContext(original_route, route_context)


# File: fastapi/routing.py | Symbol: _iter_routes_with_context
def _iter_routes_with_context(
    routes: Sequence[BaseRoute],
) -> Iterator[tuple[BaseRoute, _EffectiveRouteContext | None]]:
    for route in routes:
        if isinstance(route, _IncludedRouter):
            for route_context in route.effective_route_contexts():
                yield route_context.original_route, route_context
        else:
            yield route, None


# File: fastapi/routing.py | Symbol: _normalize_frontend_path
def _normalize_frontend_path(path: str) -> str:
    if not path:
        raise AssertionError("A frontend path cannot be empty")
    if not path.startswith("/"):
        raise AssertionError("A frontend path must start with '/'")
    if path != "/":
        path = path.rstrip("/")
    return path


# File: fastapi/routing.py | Symbol: _join_frontend_paths
def _join_frontend_paths(prefix: str, path: str) -> str:
    if not prefix:
        return path
    if path == "/":
        return prefix
    return prefix + path


# File: fastapi/routing.py | Symbol: _frontend_path_specificity
def _frontend_path_specificity(path: str) -> int:
    if path == "/":
        return 0
    return len(path)


# File: fastapi/routing.py | Symbol: _get_resolved_absolute_path
def _get_resolved_absolute_path(path: str | os.PathLike[str]) -> str:
    return os.path.realpath(os.fspath(path))


# File: fastapi/routing.py | Symbol: _FrontendStaticFiles
class _FrontendStaticFiles(StaticFiles):
    def __init__(
        self,
        *,
        directory: str | os.PathLike[str],
        fallback: Literal["auto", "index.html", "404.html"] | None,
        check_dir: bool = True,
    ) -> None:
        self.fallback = fallback
        if check_dir and not os.path.isdir(directory):
            raise RuntimeError(
                f"Frontend directory '{directory}' does not exist. "
                f"Resolved absolute path: '{_get_resolved_absolute_path(directory)}'"
            )
        super().__init__(
            directory=directory,
            html=True,
            check_dir=check_dir,
            follow_symlink=False,
        )
        if check_dir and fallback in {"index.html", "404.html"}:
            self._check_fallback_file(fallback)

    def _check_fallback_file(self, fallback: str) -> None:
        _, stat_result = self.lookup_path(fallback)
        if stat_result is None or not stat.S_ISREG(stat_result.st_mode):
            raise RuntimeError(
                f"Frontend fallback file '{fallback}' does not exist in "
                f"directory '{self.directory}'. Resolved absolute directory: "
                f"'{self._get_resolved_directory()}'"
            )

    def _get_resolved_directory(self) -> str:
        assert self.directory is not None
        return _get_resolved_absolute_path(self.directory)

    def get_path(self, scope: Scope) -> str:
        path = _get_fastapi_scope(scope).get(_FASTAPI_FRONTEND_PATH_KEY, "")
        assert isinstance(path, str)
        return os.path.normpath(os.path.join(*path.split("/")))

    async def get_response(self, path: str, scope: Scope) -> Response:
        if scope["method"] not in ("GET", "HEAD"):
            if await self._lookup_static_resource(path) is not None:
                raise HTTPException(status_code=405)
            raise HTTPException(status_code=404)

        static_resource = await self._lookup_static_resource(path)
        if static_resource is not None:
            full_path, stat_result, is_directory_index = static_resource
            if is_directory_index and not scope["path"].endswith("/"):
                url = URL(scope=scope)
                url = url.replace(path=url.path + "/")
                return RedirectResponse(url=url)
            return self.file_response(full_path, stat_result, scope)

        if self.fallback == "404.html" or (
            self.fallback == "auto" and self._fallback_file_exists("404.html")
        ):
            return await self._fallback_response("404.html", scope, status_code=404)

        if (
            self.fallback == "index.html"
            or (self.fallback == "auto" and self._fallback_file_exists("index.html"))
        ) and _is_frontend_navigation_request(scope):
            return await self._fallback_response("index.html", scope, status_code=200)

        raise HTTPException(status_code=404)

    async def _lookup_path(self, path: str) -> tuple[str, os.stat_result | None]:
        try:
            return await run_in_threadpool(self.lookup_path, path)
        except PermissionError:
            raise HTTPException(status_code=401) from None
        except OSError as exc:
            if exc.errno == errno.ENAMETOOLONG:
                raise HTTPException(status_code=404) from None
            raise exc
        except ValueError:
            raise HTTPException(status_code=404) from None

    async def _lookup_static_resource(
        self, path: str
    ) -> tuple[str, os.stat_result, bool] | None:
        full_path, stat_result = await self._lookup_path(path)
        if stat_result is None:
            return None
        if stat.S_ISREG(stat_result.st_mode):
            return full_path, stat_result, False
        if stat.S_ISDIR(stat_result.st_mode):
            index_path = os.path.join(path, "index.html")
            full_path, stat_result = await self._lookup_path(index_path)
            if stat_result is not None and stat.S_ISREG(stat_result.st_mode):
                return full_path, stat_result, True
        return None

    def _fallback_file_exists(self, fallback: str) -> bool:
        _, stat_result = self.lookup_path(fallback)
        return stat_result is not None and stat.S_ISREG(stat_result.st_mode)

    async def _fallback_response(
        self, fallback: str, scope: Scope, *, status_code: int
    ) -> Response:
        full_path, stat_result = await run_in_threadpool(self.lookup_path, fallback)
        if stat_result is None or not stat.S_ISREG(stat_result.st_mode):
            raise RuntimeError(
                f"Frontend fallback file '{fallback}' does not exist in "
                f"directory '{self.directory}'. Resolved absolute directory: "
                f"'{self._get_resolved_directory()}'"
            )
        return self.file_response(
            full_path, stat_result, scope, status_code=status_code
        )


# File: fastapi/routing.py | Symbol: _iter_accept_media_types
def _iter_accept_media_types(accept: str) -> Iterator[tuple[str, float]]:
    for raw_value in accept.split(","):
        message = email.message.Message()
        message["content-type"] = raw_value.strip()
        q = message.get_param("q")
        quality = 1.0
        if isinstance(q, str):
            try:
                quality = float(q)
            except ValueError:
                pass
        yield (
            f"{message.get_content_maintype()}/{message.get_content_subtype()}",
            quality,
        )


# File: fastapi/routing.py | Symbol: _is_frontend_navigation_request
def _is_frontend_navigation_request(scope: Scope) -> bool:
    route_path = get_route_path(scope)
    final_segment = route_path.rsplit("/", 1)[-1]
    if os.path.splitext(final_segment)[1]:
        return False
    request = Request(scope)
    wildcard_accepted = False
    html_rejected = False
    for media_type, quality in _iter_accept_media_types(
        request.headers.get("accept", "")
    ):
        if media_type in {"text/html", "application/xhtml+xml"}:
            if quality == 0:
                html_rejected = True
            else:
                return True
        elif media_type == "*/*" and quality != 0:
            wildcard_accepted = True
    return wildcard_accepted and not html_rejected


# File: fastapi/routing.py | Symbol: _FrontendRoute
class _FrontendRoute(BaseRoute):
    def __init__(
        self,
        path: str,
        *,
        directory: str | os.PathLike[str],
        fallback: Literal["auto", "index.html", "404.html"] | None = "auto",
        check_dir: bool = True,
    ) -> None:
        if fallback not in {"auto", "index.html", "404.html", None}:
            raise AssertionError(
                "fallback must be 'auto', 'index.html', '404.html', or None"
            )
        self.path = _normalize_frontend_path(path)
        self.methods = {"GET", "HEAD"}
        self.app = _FrontendStaticFiles(
            directory=directory, fallback=fallback, check_dir=check_dir
        )

    def matches(self, scope: Scope) -> tuple[Match, Scope]:
        return self.matches_with_path(scope, self.path)

    def matches_with_path(self, scope: Scope, path: str) -> tuple[Match, Scope]:
        if scope["type"] != "http":
            return Match.NONE, {}
        frontend_path = self._get_frontend_path(path, get_route_path(scope))
        if frontend_path is None:
            return Match.NONE, {}
        child_scope = {
            _FASTAPI_SCOPE_KEY: {
                _FASTAPI_FRONTEND_PATH_KEY: frontend_path,
                _FASTAPI_FRONTEND_SPECIFICITY_KEY: _frontend_path_specificity(path),
            }
        }
        if scope["method"] not in self.methods:
            return Match.PARTIAL, child_scope
        return Match.FULL, child_scope

    def _get_frontend_path(self, path: str, route_path: str) -> str | None:
        if path == "/":
            return route_path.lstrip("/")
        if route_path == path:
            return ""
        prefix = path + "/"
        if route_path.startswith(prefix):
            return route_path[len(prefix) :]
        return None

    async def handle(self, scope: Scope, receive: Receive, send: Send) -> None:
        await self.app(scope, receive, send)

    def url_path_for(self, name: str, /, **path_params: Any) -> URLPath:
        raise NoMatchFound(name, path_params)


# File: fastapi/routing.py | Symbol: _FrontendRouteGroup
class _FrontendRouteGroup(BaseRoute):
    def __init__(
        self,
        *,
        dependencies: Sequence[params.Depends] | None = None,
        dependency_overrides_provider: Any | None = None,
    ) -> None:
        self.routes: list[_FrontendRoute] = []
        self.dependencies = list(dependencies or [])
        self.dependency_overrides_provider = dependency_overrides_provider
        (
            self.dependant,
            self._flat_dependant,
            self._embed_body_fields,
        ) = _build_dependant_with_parameterless_dependencies(
            path="",
            call=_frontend_dependency_endpoint,
            dependencies=self.dependencies,
        )

    def add_frontend_route(
        self,
        path: str,
        *,
        directory: str | os.PathLike[str],
        fallback: Literal["auto", "index.html", "404.html"] | None = "auto",
        check_dir: bool = True,
    ) -> None:
        self.routes.append(
            _FrontendRoute(
                path,
                directory=directory,
                fallback=fallback,
                check_dir=check_dir,
            )
        )

    def matches(self, scope: Scope) -> tuple[Match, Scope]:
        match, child_scope, _ = self._match(scope, prefix="")
        return match, child_scope

    def matches_with_prefix(self, scope: Scope, prefix: str) -> tuple[Match, Scope]:
        match, child_scope, _ = self._match(scope, prefix=prefix)
        return match, child_scope

    def _match(
        self, scope: Scope, *, prefix: str
    ) -> tuple[Match, Scope, _FrontendRoute | None]:
        full: tuple[Scope, _FrontendRoute, int] | None = None
        partial: tuple[Scope, _FrontendRoute, int] | None = None
        for route in self.routes:
            path = _join_frontend_paths(prefix, route.path)
            match, child_scope = route.matches_with_path(scope, path)
            specificity = _frontend_path_specificity(path)
            if match == Match.FULL:
                if full is None or specificity > full[2]:
                    full = (child_scope, route, specificity)
            elif match == Match.PARTIAL:
                if partial is None or specificity > partial[2]:
                    partial = (child_scope, route, specificity)
        if full is not None:
            child_scope, route, _ = full
            return Match.FULL, child_scope, route
        if partial is not None:
            child_scope, route, _ = partial
            return Match.PARTIAL, child_scope, route
        return Match.NONE, {}, None

    async def handle(self, scope: Scope, receive: Receive, send: Send) -> None:
        effective_context = _get_scope_effective_route_context(scope)
        if (
            isinstance(effective_context, _EffectiveRouteContext)
            and effective_context.original_route is self
        ):
            prefix = effective_context.frontend_prefix
            dependant = effective_context.dependant
            dependency_overrides_provider = (
                effective_context.dependency_overrides_provider
            )
            embed_body_fields = effective_context._embed_body_fields
        else:
            prefix = ""
            dependant = self.dependant
            dependency_overrides_provider = self.dependency_overrides_provider
            embed_body_fields = self._embed_body_fields
        match, child_scope, route = self._match(scope, prefix=prefix)
        if match == Match.NONE or route is None:
            raise HTTPException(status_code=404)
        _update_scope(scope, child_scope)
        if match == Match.FULL and dependant and dependant.dependencies:
            async with self._solve_dependencies(
                scope,
                receive,
                send,
                dependant=dependant,
                dependency_overrides_provider=dependency_overrides_provider,
                embed_body_fields=embed_body_fields,
            ):
                await route.handle(scope, receive, send)
            return
        await route.handle(scope, receive, send)

    def url_path_for(self, name: str, /, **path_params: Any) -> URLPath:
        raise NoMatchFound(name, path_params)

    # TODO: probably move this out of the Route / Route Group, same in APIRoute
    # this should probably be top level FastAPI logic, not part of APIRoute and
    # duplicated here
    @asynccontextmanager
    async def _solve_dependencies(
        self,
        scope: Scope,
        receive: Receive,
        send: Send,
        *,
        dependant: Dependant,
        dependency_overrides_provider: Any | None,
        embed_body_fields: bool,
    ) -> AsyncIterator[None]:
        request = Request(scope, receive, send)
        previous_inner_astack = scope.get("fastapi_inner_astack", _SCOPE_MISSING)
        previous_function_astack = scope.get("fastapi_function_astack", _SCOPE_MISSING)
        try:
            async with AsyncExitStack() as request_stack:
                scope["fastapi_inner_astack"] = request_stack
                async with AsyncExitStack() as function_stack:
                    scope["fastapi_function_astack"] = function_stack
                    solved_result = await solve_dependencies(
                        request=request,
                        dependant=dependant,
                        dependency_overrides_provider=dependency_overrides_provider,
                        async_exit_stack=request_stack,
                        embed_body_fields=embed_body_fields,
                    )
                    if solved_result.errors:
                        raise RequestValidationError(solved_result.errors)
                    yield
        finally:
            if previous_inner_astack is _SCOPE_MISSING:
                scope.pop("fastapi_inner_astack", None)
            else:
                scope["fastapi_inner_astack"] = previous_inner_astack
            if previous_function_astack is _SCOPE_MISSING:
                scope.pop("fastapi_function_astack", None)
            else:
                scope["fastapi_function_astack"] = previous_function_astack