From 2d2015332bcb23985288309b53fff7a9473fea73 Mon Sep 17 00:00:00 2001 From: AnshMNSoni Date: Tue, 13 Jan 2026 10:32:03 +0530 Subject: [PATCH] Fix Annotated forward reference dependencies and HTTPBasic header regression --- fastapi/dependencies/utils.py | 17 +++++++++--- fastapi/security/http.py | 51 +++++------------------------------ 2 files changed, 21 insertions(+), 47 deletions(-) diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index e964036b4..00769e728 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -279,11 +279,22 @@ def get_dependant( type_hints = {} signature_params = endpoint_signature.parameters + unwrapped = inspect.unwrap(call) + globalns = getattr(unwrapped, "__globals__", {}) for param_name, param in signature_params.items(): - # Inject fully resolved Annotated types (including forward refs) - if param_name in type_hints: - param = param.replace(annotation=type_hints[param_name]) + annotation = param.annotation + + # Resolve ForwardRef inside Annotated without destroying metadata + if get_origin(annotation) is Annotated: + args = list(get_args(annotation)) + inner = args[0] + if isinstance(inner, ForwardRef): + inner = evaluate_forwardref(inner, globalns, globalns) + args[0] = inner + annotation = Annotated[inner, *args[1:]] # ✅ correct reconstruction + param = param.replace(annotation=annotation) + is_path_param = param_name in path_param_names param_details = analyze_param( param_name=param_name, diff --git a/fastapi/security/http.py b/fastapi/security/http.py index 25cb4e376..7646e7f44 100644 --- a/fastapi/security/http.py +++ b/fastapi/security/http.py @@ -142,55 +142,18 @@ class HTTPBasic(HTTPBase): def __init__( self, *, - scheme_name: Annotated[ - Optional[str], - Doc( - """ - Security scheme name. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - realm: Annotated[str, Doc("HTTP Basic authentication realm.")] = "fastapi", - description: Annotated[ - Optional[str], - Doc( - """ - Security scheme description. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - auto_error: Annotated[ - bool, - Doc( - """ - By default, if the HTTP Basic authentication is not provided (a - header), `HTTPBasic` will automatically cancel the request and send the - client an error. - - If `auto_error` is set to `False`, when the HTTP Basic authentication - is not available, instead of erroring out, the dependency result will - be `None`. - - This is useful when you want to have optional authentication. - - It is also useful when you want to have authentication that can be - provided in one of multiple optional ways (for example, in HTTP Basic - authentication or in an HTTP Bearer token). - """ - ), - ] = True, - ): + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True, +): self.model = HTTPBaseModel(scheme="basic", description=description) self.scheme_name = scheme_name or self.__class__.__name__ - self.realm = realm self.auto_error = auto_error + def make_authenticate_headers(self) -> dict[str, str]: - return {"WWW-Authenticate": f'Basic realm="{self.realm}"'} + return {"WWW-Authenticate": "Basic"} + async def __call__( # type: ignore self, request: Request