Browse Source
Previously, using Response as a type hint with Depends would fail:
def endpoint(response: Annotated[Response, Depends(modify_response)]):
This was due to an overly strict assertion that prevented Depends
from being used with Response type annotations.
The fix moves the Depends check before the special type handling,
so when a Depends is specified, the dependency is called normally
and its return value used, rather than applying the special
Response injection logic.
This allows patterns like:
- response: Annotated[Response, Depends(modify_response)]
- response: Response = Depends(modify_response)
While still supporting regular Response injection:
- response: Response
Fixes #10127
pull/14794/head
2 changed files with 92 additions and 2 deletions
@ -0,0 +1,89 @@ |
|||
"""Test using Response type hint as dependency annotation.""" |
|||
|
|||
from typing import Annotated |
|||
|
|||
from fastapi import Depends, FastAPI, Response |
|||
from fastapi.testclient import TestClient |
|||
|
|||
|
|||
def test_response_with_depends_annotated(): |
|||
"""Response type hint should work with Annotated[Response, Depends(...)].""" |
|||
app = FastAPI() |
|||
|
|||
def modify_response(response: Response) -> Response: |
|||
response.headers["X-Custom"] = "modified" |
|||
return response |
|||
|
|||
@app.get("/") |
|||
def endpoint(response: Annotated[Response, Depends(modify_response)]): |
|||
return {"status": "ok"} |
|||
|
|||
client = TestClient(app) |
|||
resp = client.get("/") |
|||
|
|||
assert resp.status_code == 200 |
|||
assert resp.json() == {"status": "ok"} |
|||
assert resp.headers.get("X-Custom") == "modified" |
|||
|
|||
|
|||
def test_response_with_depends_default(): |
|||
"""Response type hint should work with Response = Depends(...).""" |
|||
app = FastAPI() |
|||
|
|||
def modify_response(response: Response) -> Response: |
|||
response.headers["X-Custom"] = "modified" |
|||
return response |
|||
|
|||
@app.get("/") |
|||
def endpoint(response: Response = Depends(modify_response)): |
|||
return {"status": "ok"} |
|||
|
|||
client = TestClient(app) |
|||
resp = client.get("/") |
|||
|
|||
assert resp.status_code == 200 |
|||
assert resp.json() == {"status": "ok"} |
|||
assert resp.headers.get("X-Custom") == "modified" |
|||
|
|||
|
|||
def test_response_without_depends(): |
|||
"""Regular Response injection should still work.""" |
|||
app = FastAPI() |
|||
|
|||
@app.get("/") |
|||
def endpoint(response: Response): |
|||
response.headers["X-Direct"] = "set" |
|||
return {"status": "ok"} |
|||
|
|||
client = TestClient(app) |
|||
resp = client.get("/") |
|||
|
|||
assert resp.status_code == 200 |
|||
assert resp.json() == {"status": "ok"} |
|||
assert resp.headers.get("X-Direct") == "set" |
|||
|
|||
|
|||
def test_response_dependency_chain(): |
|||
"""Response dependency should work in a chain of dependencies.""" |
|||
app = FastAPI() |
|||
|
|||
def first_modifier(response: Response) -> Response: |
|||
response.headers["X-First"] = "1" |
|||
return response |
|||
|
|||
def second_modifier( |
|||
response: Annotated[Response, Depends(first_modifier)], |
|||
) -> Response: |
|||
response.headers["X-Second"] = "2" |
|||
return response |
|||
|
|||
@app.get("/") |
|||
def endpoint(response: Annotated[Response, Depends(second_modifier)]): |
|||
return {"status": "ok"} |
|||
|
|||
client = TestClient(app) |
|||
resp = client.get("/") |
|||
|
|||
assert resp.status_code == 200 |
|||
assert resp.headers.get("X-First") == "1" |
|||
assert resp.headers.get("X-Second") == "2" |
|||
Loading…
Reference in new issue