77from uuid import uuid4
88
99from django .urls import reverse
10- from reactpy import component , hooks
10+ from reactpy import component , hooks , html
1111
1212from reactpy_django .javascript_components import HttpRequest
1313from reactpy_django .models import SwitchSession
1919
2020
2121@component
22- def auth_manager ():
23- """Component that can force the client to switch HTTP sessions to match the websocket session.
22+ def session_manager (child ):
23+ """This component can force the client (browser) to switch HTTP sessions,
24+ making it match the websocket session.
2425
2526 Used to force persistent authentication between Django's websocket and HTTP stack."""
2627 from reactpy_django import config
2728
2829 switch_sessions , set_switch_sessions = hooks .use_state (False )
30+ _ , set_rerender = hooks .use_state (uuid4 )
2931 uuid_ref = hooks .use_ref (str (uuid4 ()))
3032 uuid = uuid_ref .current
3133 scope = hooks .use_connection ().scope
@@ -35,11 +37,13 @@ def setup_asgi_scope():
3537 """Store a trigger function in websocket scope so that ReactPy-Django's hooks can command a session synchronization."""
3638 scope .setdefault ("reactpy" , {})
3739 scope ["reactpy" ]["synchronize_session" ] = synchronize_session
38- print ( "configure_asgi_scope" )
40+ scope [ "reactpy" ][ "rerender" ] = rerender
3941
4042 @hooks .use_effect (dependencies = [switch_sessions ])
4143 async def synchronize_session_timeout ():
42- """Ensure that the ASGI scope is available to this component."""
44+ """Ensure that the ASGI scope is available to this component.
45+ This effect will automatically be cancelled if the session is successfully
46+ switched (via dependencies=[switch_sessions])."""
4347 if switch_sessions :
4448 await asyncio .sleep (config .REACTPY_AUTH_TIMEOUT + 0.1 )
4549 await asyncio .to_thread (
@@ -52,43 +56,44 @@ async def synchronize_session():
5256 """Entrypoint where the server will command the client to switch HTTP sessions
5357 to match the websocket session. This function is stored in the websocket scope so that
5458 ReactPy-Django's hooks can access it."""
55- print ("sync command" )
5659 session : SessionBase | None = scope .get ("session" )
5760 if not session or not session .session_key :
58- print ("sync error" )
5961 return
6062
6163 # Delete any sessions currently associated with this UUID
6264 with contextlib .suppress (SwitchSession .DoesNotExist ):
6365 obj = await SwitchSession .objects .aget (uuid = uuid )
6466 await obj .adelete ()
6567
68+ # Begin the process of synchronizing HTTP and websocket sessions
6669 obj = await SwitchSession .objects .acreate (uuid = uuid , session_key = session .session_key )
6770 await obj .asave ()
68-
6971 set_switch_sessions (True )
7072
7173 async def synchronize_session_callback (status_code : int , response : str ):
72- """This callback acts as a communication bridge between the client and server, notifying the server
73- of the client's response to the session switch command."""
74- print ("callback" )
74+ """This callback acts as a communication bridge, allowing the client to notify the server
75+ of the status of session switch command."""
7576 set_switch_sessions (False )
7677 if status_code >= 300 or status_code < 200 :
7778 await asyncio .to_thread (
7879 _logger .warning ,
7980 f"Client returned unexpected HTTP status code ({ status_code } ) while trying to sychronize sessions." ,
8081 )
8182
82- # If a session cookie was generated, send it to the client
83- print ("render" )
83+ async def rerender ():
84+ """Force a rerender of the entire component tree."""
85+ set_rerender (uuid4 ())
86+
87+ # Switch sessions using a client side HttpRequest component, if needed
88+ http_request = None
8489 if switch_sessions :
85- print ("Rendering HTTP request component with UUID " , uuid )
86- return HttpRequest (
90+ http_request = HttpRequest (
8791 {
8892 "method" : "GET" ,
8993 "url" : reverse ("reactpy:switch_session" , args = [uuid ]),
9094 "body" : None ,
9195 "callback" : synchronize_session_callback ,
9296 },
9397 )
94- return None
98+
99+ return html ._ (child , http_request )
0 commit comments