From d8b6b4f7b6eb14a578eeb5977dbf57bdf1986834 Mon Sep 17 00:00:00 2001 From: Asad Ali <42726454+dmp990@users.noreply.github.com> Date: Thu, 29 Oct 2026 14:40:42 +0000 Subject: [PATCH 1/2] Fix session:dict injection and 'session'-prefixed body params in _find_p --- fasthtml/core.py | 6 +-- nbs/api/00_core.ipynb | 98 +++++++++++++++++++++++++++---------------- 2 files changed, 64 insertions(+), 40 deletions(-) diff --git a/fasthtml/core.py b/fasthtml/core.py index 09c2acb4..53414dc6 100644 --- a/fasthtml/core.py +++ b/fasthtml/core.py @@ -274,10 +274,8 @@ async def _find_p(conn, data, hdrs, arg:str, p:Parameter): if issubclass(anno, Starlette): return conn.scope['app'] if issubclass(anno, HTTPConnection): return conn if issubclass(anno, State): return conn.scope['app'].state - if anno is dict: return data - if _is_body(anno): - if 'session'.startswith(arg.lower()): return conn.scope.get('session', {}) - return await _from_body(conn, p, data) + if anno is dict: return conn.scope.get('session', {}) if 'session'.startswith(arg.lower()) else data + if _is_body(anno): return await _from_body(conn, p, data) if (msg := _check_anno(arg, anno)): return warn(msg) # Special param names with no annotations if anno is empty: diff --git a/nbs/api/00_core.ipynb b/nbs/api/00_core.ipynb index a5ace4a8..60b6acb2 100644 --- a/nbs/api/00_core.ipynb +++ b/nbs/api/00_core.ipynb @@ -182,7 +182,7 @@ { "data": { "text/plain": [ - "datetime.datetime(2026, 3, 30, 14, 0)" + "datetime.datetime(2026, 10, 29, 14, 0)" ] }, "execution_count": null, @@ -842,7 +842,25 @@ "execution_count": null, "id": "28bfbbc1", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Did not find CR at end of boundary (5)\n" + ] + }, + { + "data": { + "text/plain": [ + "'Invalid multipart data.'" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "bad = b'--xyzXX\\r\\nContent-Disposition: form-data; name=\"a\"\\r\\n\\r\\n1\\r\\n--xyz--\\r\\n'\n", "res = client.post('/', content=bad, headers={'content-type':'multipart/form-data; boundary=xyz'})\n", @@ -863,7 +881,18 @@ "execution_count": null, "id": "2aaa8fbe", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "'Invalid JSON body'" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "res = client.post('/', json=[1,2])\n", "test_eq(res.status_code, 400)\n", @@ -912,10 +941,8 @@ " if issubclass(anno, Starlette): return conn.scope['app']\n", " if issubclass(anno, HTTPConnection): return conn\n", " if issubclass(anno, State): return conn.scope['app'].state\n", - " if anno is dict: return data\n", - " if _is_body(anno):\n", - " if 'session'.startswith(arg.lower()): return conn.scope.get('session', {})\n", - " return await _from_body(conn, p, data)\n", + " if anno is dict: return conn.scope.get('session', {}) if 'session'.startswith(arg.lower()) else data\n", + " if _is_body(anno): return await _from_body(conn, p, data)\n", " if (msg := _check_anno(arg, anno)): return warn(msg)\n", " # Special param names with no annotations\n", " if anno is empty:\n", @@ -1739,7 +1766,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "morph head-support preload class-tools loading-states multi-swap path-deps remove-me debug ws chunked-transfer\n" + "morph head-support preload class-tools loading-states multi-swap path-deps remove-me debug ws ws4 chunked-transfer sse4 live multipart\n" ] } ], @@ -2920,13 +2947,7 @@ "\n", "\n", "