-
-
Notifications
You must be signed in to change notification settings - Fork 476
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Attaching to a FastAPI instance with another storage_secret breaks session storage #2578
Comments
I've been having similar issues. I haven't figured it out yet, but so far: I need to add TLS to server (i.e. https using Let's Encrypt). I can't find any documentation under NiceGui on hosting a https site which is required these days so I have been trying to run nicegui under FastAPI using ui.run_with. It breaks when I try to add AuthMiddleware to core.api. As an aside: there are two api's one for fastapi and one for core in ui. In addition, middleware can be added to either fastapi or ui (or both?). I can't find documentation dealing with this and it's somewhat confusing and/or convoluted to follow what is going on. Irrespective, when adding AuthMiddleware, dispatch of BaseHTTPMiddleware needs to be replaced. This calls: if not app.storage.user.get('authenticated', False): right at the beginning which calls (from the storage module): @property
def browser(self) -> Union[ReadOnlyDict, Dict]:
"""Small storage that is saved directly within the user's browser (encrypted cookie).
The data is shared between all browser tabs and can only be modified before the initial request has been submitted.
Therefore it is normally better to use `app.storage.user` instead,
which can be modified anytime, reduces overall payload, improves security and has larger storage capacity.
"""
request: Optional[Request] = request_contextvar.get()
if request is None:
if self._is_in_auto_index_context():
raise RuntimeError('app.storage.browser can only be used with page builder functions '
'(https://nicegui.io/documentation/page)')
raise RuntimeError('app.storage.browser needs a storage_secret passed in ui.run()')
if request.state.responded:
return ReadOnlyDict(
request.session,
'the response to the browser has already been built, so modifications cannot be sent back anymore'
)
return request.session This breaks in the very first line as request is None (it shouldn't be None). request_contextvar is declared at the beginning of storage.py: request_contextvar: contextvars.ContextVar[Optional[Request]] = contextvars.ContextVar('request_var', default=None) and it shouldn't be None. In the nicegui authentication example, which uses run(), not run_with(), it is not None at the same location. So far, I can't figure out why it is None when run_with() is used. I tried checking if it might be a different thread, but so far it doesn't seem to be. Still working on it, but getting close to giving up on nicegui because of the difficult getting TLS working (it's alway a pain), but it seems starlette-admin might have it working? I'd prefer to stay with nicegui, but I am running out of time trying to get TLS without documentation or even an example? Any suggestions are appreciated as I'm running out of hair! |
Update:
def run_with(...) -> None:
...
storage.set_storage_secret(storage_secret=storage_secret, target_app=app)
... and change set_storage_secret to something like this: def set_storage_secret(storage_secret: Optional[str] = None, target_app = None) -> None:
if not target_app:
from nicegui import app
target_app = app
# this logic prevent repeat add middleware to user_middleware
if any(m.cls in [SessionMiddleware, RequestTrackingMiddleware] for m in target_app.user_middleware):
return
"""Set storage_secret and add request tracking middleware."""
if any(m.cls == SessionMiddleware for m in target_app.user_middleware):
# NOTE not using "add_middleware" because it would be the wrong order
target_app.user_middleware.append(RequestTrackingMiddleware)
elif storage_secret is not None:
target_app.add_middleware(RequestTrackingMiddleware)
target_app.add_middleware(SessionMiddleware, secret_key=storage_secret)
and in main app should apply ui.run_with before app.add_middleware too: ui.run_with(app_fastapi, storage_secret="some secret")
app.add_middleware(AuthMiddleware) and voila those middleware will execute in correct order in the outside main fast api app. @falkoschindler please take a look, thank you. |
Description
I noticed that when attaching to a FastAPI instance using
ui.run_with
one has to use the same secret like the FastAPI SessionMiddleware - otherwise the session data is not persistence across page reloads. This seems to be problematic in two ways:Debugging, took me a while, so I would recommend to improve the feedback if the user tries to set another password and/or to improve the web examples for attaching to an existing FastAPI instance (e.g. show the example how to attach to an app with a installed middleware).
When writing the MRCE I also noticed, that initializing NiceGUI will break all endpoints defined later in the code via FastAPI. I don't know if this is problematic, but it seems weird. You may have a look at this.
MRCE:
File 1: main.py
File 2: ng_page.py
Expected/ideal behavior:
The text was updated successfully, but these errors were encountered: