|
@ -1,5 +1,6 @@ |
|
|
import dataclasses |
|
|
import dataclasses |
|
|
import email.message |
|
|
import email.message |
|
|
|
|
|
import functools |
|
|
import inspect |
|
|
import inspect |
|
|
import json |
|
|
import json |
|
|
import sys |
|
|
import sys |
|
@ -8,6 +9,7 @@ from enum import Enum, IntEnum |
|
|
from typing import ( |
|
|
from typing import ( |
|
|
Any, |
|
|
Any, |
|
|
AsyncIterator, |
|
|
AsyncIterator, |
|
|
|
|
|
Awaitable, |
|
|
Callable, |
|
|
Callable, |
|
|
Collection, |
|
|
Collection, |
|
|
Coroutine, |
|
|
Coroutine, |
|
@ -59,6 +61,8 @@ from fastapi.utils import ( |
|
|
) |
|
|
) |
|
|
from pydantic import BaseModel |
|
|
from pydantic import BaseModel |
|
|
from starlette import routing |
|
|
from starlette import routing |
|
|
|
|
|
from starlette._exception_handler import wrap_app_handling_exceptions |
|
|
|
|
|
from starlette._utils import is_async_callable |
|
|
from starlette.concurrency import run_in_threadpool |
|
|
from starlette.concurrency import run_in_threadpool |
|
|
from starlette.exceptions import HTTPException |
|
|
from starlette.exceptions import HTTPException |
|
|
from starlette.requests import Request |
|
|
from starlette.requests import Request |
|
@ -68,11 +72,9 @@ from starlette.routing import ( |
|
|
Match, |
|
|
Match, |
|
|
compile_path, |
|
|
compile_path, |
|
|
get_name, |
|
|
get_name, |
|
|
request_response, |
|
|
|
|
|
websocket_session, |
|
|
|
|
|
) |
|
|
) |
|
|
from starlette.routing import Mount as Mount # noqa |
|
|
from starlette.routing import Mount as Mount # noqa |
|
|
from starlette.types import AppType, ASGIApp, Lifespan, Scope |
|
|
from starlette.types import AppType, ASGIApp, Lifespan, Receive, Scope, Send |
|
|
from starlette.websockets import WebSocket |
|
|
from starlette.websockets import WebSocket |
|
|
from typing_extensions import Annotated, Doc, deprecated |
|
|
from typing_extensions import Annotated, Doc, deprecated |
|
|
|
|
|
|
|
@ -246,7 +248,12 @@ def get_request_handler( |
|
|
|
|
|
|
|
|
async def app(request: Request) -> Response: |
|
|
async def app(request: Request) -> Response: |
|
|
response: Union[Response, None] = None |
|
|
response: Union[Response, None] = None |
|
|
async with AsyncExitStack() as file_stack: |
|
|
file_stack = request.scope.get("fastapi_middleware_astack") |
|
|
|
|
|
assert isinstance( |
|
|
|
|
|
file_stack, AsyncExitStack |
|
|
|
|
|
), "fastapi_astack not found in request scope" |
|
|
|
|
|
|
|
|
|
|
|
# Read body and auto-close files |
|
|
try: |
|
|
try: |
|
|
body: Any = None |
|
|
body: Any = None |
|
|
if body_field: |
|
|
if body_field: |
|
@ -293,8 +300,13 @@ def get_request_handler( |
|
|
status_code=400, detail="There was an error parsing the body" |
|
|
status_code=400, detail="There was an error parsing the body" |
|
|
) |
|
|
) |
|
|
raise http_error from e |
|
|
raise http_error from e |
|
|
|
|
|
|
|
|
|
|
|
# Solve dependencies and run path operation function, auto-closing dependencies |
|
|
errors: List[Any] = [] |
|
|
errors: List[Any] = [] |
|
|
async with AsyncExitStack() as async_exit_stack: |
|
|
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( |
|
|
solved_result = await solve_dependencies( |
|
|
request=request, |
|
|
request=request, |
|
|
dependant=dependant, |
|
|
dependant=dependant, |
|
@ -321,16 +333,12 @@ def get_request_handler( |
|
|
# If status_code was set, use it, otherwise use the default from the |
|
|
# If status_code was set, use it, otherwise use the default from the |
|
|
# response class, in the case of redirect it's 307 |
|
|
# response class, in the case of redirect it's 307 |
|
|
current_status_code = ( |
|
|
current_status_code = ( |
|
|
status_code |
|
|
status_code if status_code else solved_result.response.status_code |
|
|
if status_code |
|
|
|
|
|
else solved_result.response.status_code |
|
|
|
|
|
) |
|
|
) |
|
|
if current_status_code is not None: |
|
|
if current_status_code is not None: |
|
|
response_args["status_code"] = current_status_code |
|
|
response_args["status_code"] = current_status_code |
|
|
if solved_result.response.status_code: |
|
|
if solved_result.response.status_code: |
|
|
response_args["status_code"] = ( |
|
|
response_args["status_code"] = solved_result.response.status_code |
|
|
solved_result.response.status_code |
|
|
|
|
|
) |
|
|
|
|
|
content = await serialize_response( |
|
|
content = await serialize_response( |
|
|
field=response_field, |
|
|
field=response_field, |
|
|
response_content=raw_response, |
|
|
response_content=raw_response, |
|
@ -351,6 +359,8 @@ def get_request_handler( |
|
|
_normalize_errors(errors), body=body |
|
|
_normalize_errors(errors), body=body |
|
|
) |
|
|
) |
|
|
raise validation_error |
|
|
raise validation_error |
|
|
|
|
|
|
|
|
|
|
|
# Return response |
|
|
if response is None: |
|
|
if response is None: |
|
|
raise FastAPIError( |
|
|
raise FastAPIError( |
|
|
"No response object was returned. There's a high chance that the " |
|
|
"No response object was returned. There's a high chance that the " |
|
@ -370,11 +380,10 @@ def get_websocket_app( |
|
|
embed_body_fields: bool = False, |
|
|
embed_body_fields: bool = False, |
|
|
) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]: |
|
|
) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]: |
|
|
async def app(websocket: WebSocket) -> None: |
|
|
async def app(websocket: WebSocket) -> None: |
|
|
async with AsyncExitStack() as async_exit_stack: |
|
|
async_exit_stack = websocket.scope.get("fastapi_inner_astack") |
|
|
# TODO: remove this scope later, after a few releases |
|
|
assert isinstance( |
|
|
# This scope fastapi_astack is no longer used by FastAPI, kept for |
|
|
async_exit_stack, AsyncExitStack |
|
|
# compatibility, just in case |
|
|
), "fastapi_inner_astack not found in request scope" |
|
|
websocket.scope["fastapi_astack"] = async_exit_stack |
|
|
|
|
|
solved_result = await solve_dependencies( |
|
|
solved_result = await solve_dependencies( |
|
|
request=websocket, |
|
|
request=websocket, |
|
|
dependant=dependant, |
|
|
dependant=dependant, |
|
|