|
43 | 43 | "outputs": [], |
44 | 44 | "source": [ |
45 | 45 | "#| export\n", |
46 | | - "import json,uuid,inspect,types,signal,asyncio,threading,inspect,random,contextlib\n", |
| 46 | + "import json,uuid,inspect,types,signal,asyncio,threading,inspect,random,contextlib,httpx,itsdangerous\n", |
47 | 47 | "\n", |
48 | 48 | "from fastcore.utils import *\n", |
49 | 49 | "from fastcore.xml import *\n", |
|
61 | 61 | "from copy import copy,deepcopy\n", |
62 | 62 | "from warnings import warn\n", |
63 | 63 | "from dateutil import parser as dtparse\n", |
64 | | - "from httpx import ASGITransport, AsyncClient\n", |
65 | 64 | "from anyio import from_thread\n", |
66 | 65 | "from uuid import uuid4, UUID\n", |
67 | 66 | "from base64 import b85encode,b64encode\n", |
|
131 | 130 | { |
132 | 131 | "data": { |
133 | 132 | "text/plain": [ |
134 | | - "datetime.datetime(2025, 10, 27, 14, 0)" |
| 133 | + "datetime.datetime(2025, 11, 19, 14, 0)" |
135 | 134 | ] |
136 | 135 | }, |
137 | 136 | "execution_count": null, |
|
1646 | 1645 | " same_site='lax', sess_https_only=False, sess_domain=None, key_fname='.sesskey',\n", |
1647 | 1646 | " body_wrap=noop_body, htmlkw=None, nb_hdrs=False, canonical=True, **bodykw):\n", |
1648 | 1647 | " middleware,before,after = map(_list, (middleware,before,after))\n", |
1649 | | - " self.title,self.canonical = title,canonical\n", |
| 1648 | + " self.title,self.canonical,self.session_cookie,self.key_fname = title,canonical,session_cookie,key_fname\n", |
1650 | 1649 | " hdrs,ftrs,exts = map(listify, (hdrs,ftrs,exts))\n", |
1651 | 1650 | " exts = {k:htmx_exts[k] for k in exts}\n", |
1652 | 1651 | " htmlkw = htmlkw or {}\n", |
|
1660 | 1659 | " on_startup,on_shutdown = listify(on_startup) or None,listify(on_shutdown) or None\n", |
1661 | 1660 | " self.lifespan,self.hdrs,self.ftrs = lifespan,hdrs,ftrs\n", |
1662 | 1661 | " self.body_wrap,self.before,self.after,self.htmlkw,self.bodykw = body_wrap,before,after,htmlkw,bodykw\n", |
1663 | | - " secret_key = get_key(secret_key, key_fname)\n", |
| 1662 | + " self.secret_key = get_key(secret_key, key_fname)\n", |
1664 | 1663 | " if sess_cls:\n", |
1665 | | - " sess = Middleware(sess_cls, secret_key=secret_key,session_cookie=session_cookie,\n", |
| 1664 | + " sess = Middleware(sess_cls, secret_key=self.secret_key,session_cookie=session_cookie,\n", |
1666 | 1665 | " max_age=max_age, path=sess_path, same_site=same_site,\n", |
1667 | 1666 | " https_only=sess_https_only, domain=sess_domain)\n", |
1668 | 1667 | " middleware.append(sess)\n", |
|
1986 | 1985 | "class Client:\n", |
1987 | 1986 | " \"A simple httpx ASGI client that doesn't require `async`\"\n", |
1988 | 1987 | " def __init__(self, app, url=\"http://testserver\"):\n", |
1989 | | - " self.cli = AsyncClient(transport=ASGITransport(app), base_url=url)\n", |
| 1988 | + " self.cli = httpx.AsyncClient(transport=httpx.ASGITransport(app), base_url=url)\n", |
1990 | 1989 | "\n", |
1991 | 1990 | " def _sync(self, method, url, **kwargs):\n", |
1992 | 1991 | " async def _request(): return await self.cli.request(method, url, **kwargs)\n", |
|
2888 | 2887 | "name": "stdout", |
2889 | 2888 | "output_type": "stream", |
2890 | 2889 | "text": [ |
2891 | | - "Set to 2025-10-27 07:27:07.025956\n" |
| 2890 | + "Set to 2025-11-19 08:56:35.141231\n" |
2892 | 2891 | ] |
2893 | 2892 | }, |
2894 | 2893 | { |
2895 | 2894 | "data": { |
2896 | 2895 | "text/plain": [ |
2897 | | - "'Session time: 2025-10-27 07:27:07.025956'" |
| 2896 | + "'Session time: 2025-11-19 08:56:35.141231'" |
2898 | 2897 | ] |
2899 | 2898 | }, |
2900 | 2899 | "execution_count": null, |
|
3511 | 3510 | { |
3512 | 3511 | "data": { |
3513 | 3512 | "text/plain": [ |
3514 | | - "'Cookie was set at time 07:28:31.264910'" |
| 3513 | + "'Cookie was set at time 08:56:36.257555'" |
3515 | 3514 | ] |
3516 | 3515 | }, |
3517 | 3516 | "execution_count": null, |
|
3917 | 3916 | " return dict(workspace=dict(root=path, uuid=uuid))" |
3918 | 3917 | ] |
3919 | 3918 | }, |
| 3919 | + { |
| 3920 | + "cell_type": "code", |
| 3921 | + "execution_count": null, |
| 3922 | + "id": "e27908c0", |
| 3923 | + "metadata": {}, |
| 3924 | + "outputs": [], |
| 3925 | + "source": [ |
| 3926 | + "#| export\n", |
| 3927 | + "@patch\n", |
| 3928 | + "def get_client(self:FastHTML, asink=False, **kw):\n", |
| 3929 | + " \"Get an httpx client with session cookes set from `**kw`\"\n", |
| 3930 | + " signer = itsdangerous.TimestampSigner(self.secret_key)\n", |
| 3931 | + " data = b64encode(dumps(kw).encode())\n", |
| 3932 | + " data = signer.sign(data)\n", |
| 3933 | + " client = httpx.AsyncClient() if asink else httpx.Client()\n", |
| 3934 | + " client.cookies.update({self.session_cookie: data.decode()})\n", |
| 3935 | + " return client" |
| 3936 | + ] |
| 3937 | + }, |
3920 | 3938 | { |
3921 | 3939 | "cell_type": "markdown", |
3922 | 3940 | "id": "474e14b4", |
|
0 commit comments