Skip to content

Commit bbcf31e

Browse files
committed
missing Headers
1 parent bd54058 commit bbcf31e

5 files changed

Lines changed: 71 additions & 17 deletions

File tree

examples/minimal.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44

55
app,rt = fast_app( hdrs=[Script(src='example.js')])
66

7+
@rt('/rnd', host='b.localhost')
8+
def rnd2(): return P("I am not random!")
9+
710
@rt
811
def rnd(): return P(random())
912

1013
@rt
1114
def index(): return Titled( 'Hello', Div(P('click'), hx_post=rnd))
1215

13-
serve(log_level=logging.WARNING)
16+
print(app.routes)
17+
#serve(log_level=logging.WARNING)
18+
serve()
1419

fasthtml/_modidx.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
'fasthtml/core.py'),
6666
'fasthtml.core.HostRoute': ('api/core.html#hostroute', 'fasthtml/core.py'),
6767
'fasthtml.core.HostRoute.__init__': ('api/core.html#hostroute.__init__', 'fasthtml/core.py'),
68+
'fasthtml.core.HostRoute.__repr__': ('api/core.html#hostroute.__repr__', 'fasthtml/core.py'),
6869
'fasthtml.core.HostRoute.matches': ('api/core.html#hostroute.matches', 'fasthtml/core.py'),
6970
'fasthtml.core.HtmxHeaders': ('api/core.html#htmxheaders', 'fasthtml/core.py'),
7071
'fasthtml.core.HtmxHeaders.__bool__': ('api/core.html#htmxheaders.__bool__', 'fasthtml/core.py'),

fasthtml/core.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,10 @@ def matches(self, scope):
616616
if not self.host_regex.match(host): return Match.NONE, {}
617617
return super().matches(scope)
618618

619+
def __repr__(self) -> str:
620+
methods = sorted(self.methods or [])
621+
return f"{self.__class__.__name__}(path={self.path!r}, name={self.name!r}, methods={methods!r}, host={self.host!r})"
622+
619623
# %% ../nbs/api/00_core.ipynb #e0accf76
620624
@patch
621625
def add_route(self:FastHTML, route):

fasthtml/starlette.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
88
from starlette.middleware.trustedhost import TrustedHostMiddleware
99
from starlette.responses import Response, HTMLResponse, FileResponse, JSONResponse as JSONResponseOrig, RedirectResponse, StreamingResponse
10-
from starlette.requests import Request, HTTPConnection, FormData
10+
from starlette.requests import Request, HTTPConnection, FormData, Headers
1111
from starlette.staticfiles import StaticFiles
1212
from starlette.exceptions import HTTPException
1313
from starlette._utils import is_async_callable
@@ -22,3 +22,4 @@
2222
from starlette.background import BackgroundTask, BackgroundTasks
2323
from starlette.websockets import WebSocketDisconnect, WebSocket
2424

25+

nbs/api/00_core.ipynb

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@
8484
"\n",
8585
"from fastcore.test import *\n",
8686
"from starlette.testclient import TestClient\n",
87-
"from starlette.requests import Headers\n",
8887
"from starlette.datastructures import UploadFile"
8988
]
9089
},
@@ -131,7 +130,7 @@
131130
{
132131
"data": {
133132
"text/plain": [
134-
"datetime.datetime(2026, 3, 9, 14, 0)"
133+
"datetime.datetime(2026, 3, 14, 14, 0)"
135134
]
136135
},
137136
"execution_count": null,
@@ -1785,7 +1784,11 @@
17851784
" if self.host:\n",
17861785
" host = Headers(scope=scope).get(\"host\", \"\").split(\":\")[0]\n",
17871786
" if not self.host_regex.match(host): return Match.NONE, {}\n",
1788-
" return super().matches(scope)"
1787+
" return super().matches(scope)\n",
1788+
"\n",
1789+
" def __repr__(self) -> str:\n",
1790+
" methods = sorted(self.methods or [])\n",
1791+
" return f\"{self.__class__.__name__}(path={self.path!r}, name={self.name!r}, methods={methods!r}, host={self.host!r})\""
17891792
]
17901793
},
17911794
{
@@ -2243,7 +2246,7 @@
22432246
"name": "stdout",
22442247
"output_type": "stream",
22452248
"text": [
2246-
"[HostRoute(path='/foo', name='foo', methods=['GET', 'HEAD'])]\n"
2249+
"[HostRoute(path='/foo', name='foo', methods=['GET', 'HEAD'], host=None)]\n"
22472250
]
22482251
},
22492252
{
@@ -2270,6 +2273,54 @@
22702273
"foo.to(param='value')"
22712274
]
22722275
},
2276+
{
2277+
"cell_type": "code",
2278+
"execution_count": null,
2279+
"id": "8836b62c",
2280+
"metadata": {},
2281+
"outputs": [
2282+
{
2283+
"name": "stdout",
2284+
"output_type": "stream",
2285+
"text": [
2286+
"[HostRoute(path='/foo', name='foo', methods=['GET', 'HEAD', 'POST'], host='test.foo'), HostRoute(path='/foo', name='foo', methods=['GET', 'HEAD'], host=None)]\n"
2287+
]
2288+
}
2289+
],
2290+
"source": [
2291+
"@rt(host='test.foo')\n",
2292+
"def foo(): return Div(\"Goodbye World\")\n",
2293+
"\n",
2294+
"print(app.routes)\n",
2295+
"\n",
2296+
"assert \"Goodbye World\" in cli.get('/foo', headers={'host': 'test.foo'}).text\n",
2297+
"assert \"Hello World\" in cli.get('/foo').text"
2298+
]
2299+
},
2300+
{
2301+
"cell_type": "code",
2302+
"execution_count": null,
2303+
"id": "377012de",
2304+
"metadata": {},
2305+
"outputs": [
2306+
{
2307+
"data": {
2308+
"text/plain": [
2309+
"'/foo?param=value'"
2310+
]
2311+
},
2312+
"execution_count": null,
2313+
"metadata": {},
2314+
"output_type": "execute_result"
2315+
}
2316+
],
2317+
"source": [
2318+
"response = cli.get('/foo')\n",
2319+
"assert '<title>My Custom Title</title>' in response.text\n",
2320+
"\n",
2321+
"foo.to(param='value')"
2322+
]
2323+
},
22732324
{
22742325
"cell_type": "code",
22752326
"execution_count": null,
@@ -2371,14 +2422,6 @@
23712422
"text": [
23722423
"Message text was: Hi! with session bar, from client: Address(host='testclient', port=50000)\n"
23732424
]
2374-
},
2375-
{
2376-
"name": "stderr",
2377-
"output_type": "stream",
2378-
"text": [
2379-
"/var/folders/51/b2_szf2945n072c0vj2cyty40000gn/T/ipykernel_76694/1456865336.py:30: UserWarning: `self has no type annotation and is not a recognised special name, so is ignored.\n",
2380-
" if arg!='resp': warn(f\"`{arg} has no type annotation and is not a recognised special name, so is ignored.\")\n"
2381-
]
23822425
}
23832426
],
23842427
"source": [
@@ -3087,13 +3130,13 @@
30873130
"name": "stdout",
30883131
"output_type": "stream",
30893132
"text": [
3090-
"Set to 2026-03-09 16:07:07.828671\n"
3133+
"Set to 2026-03-14 06:34:21.131035\n"
30913134
]
30923135
},
30933136
{
30943137
"data": {
30953138
"text/plain": [
3096-
"'Session time: 2026-03-09 16:07:07.828671'"
3139+
"'Session time: 2026-03-14 06:34:21.131035'"
30973140
]
30983141
},
30993142
"execution_count": null,
@@ -3710,7 +3753,7 @@
37103753
{
37113754
"data": {
37123755
"text/plain": [
3713-
"'Cookie was set at time 16:07:08.723344'"
3756+
"'Cookie was set at time 06:34:21.699929'"
37143757
]
37153758
},
37163759
"execution_count": null,

0 commit comments

Comments
 (0)