diff --git a/fastapi/routing.py b/fastapi/routing.py index 9be2b44bc..3ac99a9c1 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -435,6 +435,31 @@ def get_request_handler( if isinstance(raw_response, Response): if raw_response.background is None: raw_response.background = solved_result.background_tasks + elif solved_result.background_tasks: + from starlette.background import BackgroundTask, BackgroundTasks + + # Create a new BackgroundTasks to hold both + combined_tasks = BackgroundTasks() + + # Add existing response tasks + if isinstance(raw_response.background, BackgroundTasks): + combined_tasks.tasks.extend(raw_response.background.tasks) + elif isinstance(raw_response.background, BackgroundTask): + combined_tasks.tasks.append(raw_response.background) + + # Add dependency tasks + # solved_result.background_tasks is always BackgroundTasks (from dependencies/utils.py) + if isinstance(solved_result.background_tasks, BackgroundTasks): + combined_tasks.tasks.extend( + solved_result.background_tasks.tasks + ) + elif isinstance( + solved_result.background_tasks, BackgroundTask + ): # pragma: no cover + # Should not happen for BackgroundTasks dependency but safe to handle + combined_tasks.tasks.append(solved_result.background_tasks) + + raw_response.background = combined_tasks response = raw_response else: response_args: Dict[str, Any] = { diff --git a/tests/test_issue_11215.py b/tests/test_issue_11215.py new file mode 100644 index 000000000..00e4cfa82 --- /dev/null +++ b/tests/test_issue_11215.py @@ -0,0 +1,24 @@ +from fastapi import BackgroundTasks, FastAPI +from fastapi.testclient import TestClient +from starlette.responses import BackgroundTask, Response + +app = FastAPI() + + +@app.get("/") +def endpoint(tasks: BackgroundTasks): + tasks.add_task(lambda: print("Dependency task executed")) + return Response( + content="Custom response", + background=BackgroundTask(lambda: print("Response task executed")), + ) + + +client = TestClient(app) + + +def test_issue_11215(capsys): + client.get("/") + captured = capsys.readouterr() + assert "Dependency task executed" in captured.out + assert "Response task executed" in captured.out diff --git a/tests/test_issue_11215_coverage.py b/tests/test_issue_11215_coverage.py new file mode 100644 index 000000000..1eaa96fc5 --- /dev/null +++ b/tests/test_issue_11215_coverage.py @@ -0,0 +1,29 @@ +from fastapi import BackgroundTasks, FastAPI +from fastapi.testclient import TestClient +from starlette.background import BackgroundTasks as StarletteBackgroundTasks +from starlette.responses import Response + +app = FastAPI() + + +@app.get("/") +def endpoint(tasks: BackgroundTasks): + tasks.add_task(lambda: print("Dependency task")) + + response_tasks = StarletteBackgroundTasks() + response_tasks.add_task(lambda: print("Response task")) + + return Response( + content="Custom response", + background=response_tasks, + ) + + +client = TestClient(app) + + +def test_issue_11215_response_background_tasks_collection(capsys): + client.get("/") + captured = capsys.readouterr() + assert "Dependency task" in captured.out + assert "Response task" in captured.out