From 8317f23a43197867f3c909db6c05038a7c133770 Mon Sep 17 00:00:00 2001 From: Tung Lam Date: Mon, 17 Aug 2026 03:14:54 +0000 Subject: [PATCH] fix redirect background tasks --- fasthtml/core.py | 7 ++++++- nbs/api/00_core.ipynb | 20 ++++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/fasthtml/core.py b/fasthtml/core.py index 46b4d1b9..42b17940 100644 --- a/fasthtml/core.py +++ b/fasthtml/core.py @@ -429,6 +429,7 @@ def is_full_page(req, resp): def _part_resp(req, resp): "Partition response into HTTP headers, background tasks, and content" resp = flat_tuple(resp) + resp = flat_tuple(o.__response__(req) if hasattr(o, '__response__') else o for o in resp) resp = resp + tuple(getattr(req, 'injects', ())) http_hdrs,resp = partition(resp, risinstance(HttpHeader)) tasks,resp = partition(resp, risinstance(BackgroundTask)) @@ -471,7 +472,11 @@ def _resp(req, resp, cls=empty, status_code=200): if not (isinstance(cls, type) and issubclass(cls, Response)): cls=empty if isinstance(resp, FileResponse) and not os.path.exists(resp.path): raise HTTPException(404, resp.path) resp,kw = _part_resp(req, resp) - if isinstance(resp, Response): return resp + if isinstance(resp, Response): + if tasks := kw.get('background'): + if resp.background: tasks.tasks.insert(0, resp.background) + resp.background = tasks + return resp if cls is not empty: return cls(resp, status_code=status_code, **kw) if _is_ft_resp(resp): cts = _xt_cts(req, resp) diff --git a/nbs/api/00_core.ipynb b/nbs/api/00_core.ipynb index d8827e07..1046fde1 100644 --- a/nbs/api/00_core.ipynb +++ b/nbs/api/00_core.ipynb @@ -1480,6 +1480,7 @@ "def _part_resp(req, resp):\n", " \"Partition response into HTTP headers, background tasks, and content\"\n", " resp = flat_tuple(resp)\n", + " resp = flat_tuple(o.__response__(req) if hasattr(o, '__response__') else o for o in resp)\n", " resp = resp + tuple(getattr(req, 'injects', ()))\n", " http_hdrs,resp = partition(resp, risinstance(HttpHeader))\n", " tasks,resp = partition(resp, risinstance(BackgroundTask))\n", @@ -1546,7 +1547,11 @@ " if not (isinstance(cls, type) and issubclass(cls, Response)): cls=empty\n", " if isinstance(resp, FileResponse) and not os.path.exists(resp.path): raise HTTPException(404, resp.path)\n", " resp,kw = _part_resp(req, resp)\n", - " if isinstance(resp, Response): return resp\n", + " if isinstance(resp, Response):\n", + " if tasks := kw.get('background'):\n", + " if resp.background: tasks.tasks.insert(0, resp.background)\n", + " resp.background = tasks\n", + " return resp\n", " if cls is not empty: return cls(resp, status_code=status_code, **kw)\n", " if _is_ft_resp(resp):\n", " cts = _xt_cts(req, resp)\n", @@ -2970,7 +2975,18 @@ " print(\"Background task completed!\")\n", " return P(\"Task started\"), BackgroundTask(long_running_task)\n", "\n", - "response = cli.get(\"/background\")" + "response = cli.get(\"/background\")\n", + "\n", + "task_runs = []\n", + "\n", + "@app.get(\"/background-redirect\")\n", + "def background_redirect():\n", + " return Redirect(\"/\"), BackgroundTask(task_runs.append, True)\n", + "\n", + "response = cli.get(\"/background-redirect\", follow_redirects=False)\n", + "test_eq(response.status_code, 303)\n", + "test_eq(response.headers[\"location\"], \"/\")\n", + "test_eq(task_runs, [True])" ] }, {