77 'charset' , 'cors_allow' , 'iframe_scr' , 'all_meths' , 'devtools_loc' , 'parsed_date' , 'snake2hyphens' ,
88 'HtmxHeaders' , 'HttpHeader' , 'HtmxResponseHeaders' , 'form2dict' , 'parse_form' , 'JSONResponse' , 'flat_xt' ,
99 'Beforeware' , 'EventStream' , 'signal_shutdown' , 'uri' , 'decode_uri' , 'flat_tuple' , 'noop_body' , 'respond' ,
10- 'Redirect' , 'get_key' , 'qp' , 'def_hdrs' , 'FastHTML' , 'nested_name' , 'serve' , 'Client' , 'RouteFuncs ' ,
11- 'APIRouter' , 'cookie' , 'reg_re_param' , 'MiddlewareBase' , 'FtResponse' , 'unqid' , 'setup_ws' ]
10+ 'is_full_page' , ' Redirect' , 'get_key' , 'qp' , 'def_hdrs' , 'FastHTML' , 'nested_name' , 'serve' , 'Client' ,
11+ 'RouteFuncs' , ' APIRouter' , 'cookie' , 'reg_re_param' , 'MiddlewareBase' , 'FtResponse' , 'unqid' , 'setup_ws' ]
1212
1313# %% ../nbs/api/00_core.ipynb
1414import json ,uuid ,inspect ,types ,signal ,asyncio ,threading ,inspect
@@ -389,25 +389,35 @@ def respond(req, heads, bdy):
389389 return Html (Head (* heads , * flat_xt (req .hdrs )), body , ** req .htmlkw )
390390
391391# %% ../nbs/api/00_core.ipynb
392- def _xt_cts (req , resp ):
392+ def is_full_page (req , resp ):
393+ is_frag = 'hx-request' in req .headers and 'hx-history-restore-request' not in req .headers
394+ return (resp and not is_frag and not any (getattr (o , 'tag' , '' )== 'html' for o in resp ))
395+
396+ # %% ../nbs/api/00_core.ipynb
397+ def _part_resp (req , resp ):
393398 resp = flat_tuple (resp )
394399 resp = resp + tuple (getattr (req , 'injects' , ()))
395400 http_hdrs ,resp = partition (resp , risinstance (HttpHeader ))
396- http_hdrs = {o .k :str (o .v ) for o in http_hdrs }
397401 tasks ,resp = partition (resp , risinstance (BackgroundTask ))
398- ts = BackgroundTasks ()
399- for t in tasks : ts .tasks .append (t )
402+ kw = {"headers" : {"vary" : "HX-Request, HX-History-Restore-Request" }}
403+ if http_hdrs : kw ['headers' ] |= {o .k :str (o .v ) for o in http_hdrs }
404+ if tasks :
405+ ts = BackgroundTasks ()
406+ for t in tasks : ts .tasks .append (t )
407+ kw ['background' ] = ts
408+ resp = tuple (resp )
409+ if len (resp )== 1 : resp = resp [0 ]
410+ return resp ,kw
411+
412+ # %% ../nbs/api/00_core.ipynb
413+ def _xt_cts (req , resp ):
400414 hdr_tags = 'title' ,'meta' ,'link' ,'style' ,'base'
415+ resp = tuplify (resp )
401416 heads ,bdy = partition (resp , lambda o : getattr (o , 'tag' , '' ) in hdr_tags )
402- if resp and 'hx-request' not in req . headers and not any ( getattr ( o , 'tag' , '' ) == 'html' for o in resp ):
417+ if is_full_page ( req , resp ):
403418 title = [] if any (getattr (o , 'tag' , '' )== 'title' for o in heads ) else [Title (req .app .title )]
404419 resp = respond (req , [* heads , * title ], bdy )
405- return _to_xml (req , resp , indent = fh_cfg .indent ), http_hdrs , ts
406-
407- # %% ../nbs/api/00_core.ipynb
408- def _xt_resp (req , resp , status_code ):
409- cts ,http_hdrs ,tasks = _xt_cts (req , resp )
410- return HTMLResponse (cts , status_code = status_code , headers = http_hdrs , background = tasks )
420+ return _to_xml (req , resp , indent = fh_cfg .indent )
411421
412422# %% ../nbs/api/00_core.ipynb
413423def _is_ft_resp (resp ): return isinstance (resp , _iter_typs + (HttpHeader ,FT )) or hasattr (resp , '__ft__' )
@@ -418,15 +428,18 @@ def _resp(req, resp, cls=empty, status_code=200):
418428 if hasattr (resp , '__response__' ): resp = resp .__response__ (req )
419429 if cls in (Any ,FT ): cls = empty
420430 if isinstance (resp , FileResponse ) and not os .path .exists (resp .path ): raise HTTPException (404 , resp .path )
421- if cls is not empty : return cls (resp , status_code = status_code )
422- if isinstance (resp , Response ): return resp # respect manually set status_code
423- if _is_ft_resp (resp ): return _xt_resp (req , resp , status_code )
431+ resp ,kw = _part_resp (req , resp )
432+ if cls is not empty : return cls (resp , status_code = status_code , ** kw )
433+ if isinstance (resp , Response ): return resp
434+ if _is_ft_resp (resp ):
435+ cts = _xt_cts (req , resp )
436+ return HTMLResponse (cts , status_code = status_code , ** kw )
424437 if isinstance (resp , str ): cls = HTMLResponse
425438 elif isinstance (resp , Mapping ): cls = JSONResponse
426439 else :
427440 resp = str (resp )
428441 cls = HTMLResponse
429- return cls (resp , status_code = status_code )
442+ return cls (resp , status_code = status_code , ** kw )
430443
431444# %% ../nbs/api/00_core.ipynb
432445class Redirect :
@@ -788,8 +801,10 @@ def __init__(self, content, status_code:int=200, headers=None, cls=HTMLResponse,
788801 self .cls ,self .media_type ,self .background = cls ,media_type ,background
789802
790803 def __response__ (self , req ):
791- cts ,httphdrs ,tasks = _xt_cts (req , self .content )
792- if not tasks .tasks : tasks = self .background
804+ resp ,kw = _part_resp (req , self .content )
805+ cts = _xt_cts (req , resp )
806+ tasks ,httphdrs = kw .get ('background' ),kw .get ('headers' )
807+ if not tasks : tasks = self .background
793808 headers = {** (self .headers or {}), ** httphdrs }
794809 return self .cls (cts , status_code = self .status_code , headers = headers , media_type = self .media_type , background = tasks )
795810
0 commit comments