From 6140d10b09b6981b95a218cd0a9c60a5111230f2 Mon Sep 17 00:00:00 2001 From: Rodja Trappe Date: Mon, 13 Jan 2025 11:48:43 +0100 Subject: [PATCH] Register middlewares as late as possible (#4155) This PR moves the middleware registration from import time to the actual call of `ui.run`. Thereby the middlewares are also run before middlewares which are added by user code. See the the authentication example for an actual use-case where this is convinient: https://github.com/zauberzeug/nicegui/blob/09f4c34049b37907174bfe3109aae4b834f80863/examples/authentication/main.py#L28C2-L33C40 Without this change, the `RedirectResponse` does not work properly behind a reverse proxy with subpath or NiceGUI On Air, because the rewriting of the path prefix which is done by our `RedirectWithPrefixMiddleware`. FastAPI / Starlette call the middlewares in reverse order of registration. Therefore, without this PR, the user middleware is the last one added and hence called first, leaving the path unmodified. ToDos: - [x] test with simple NiceGUI App which has no `if __name__ in ('__mp_main__', '__main__')` guard - [x] implement and test `ui.run_with` --------- Co-authored-by: Falko Schindler --- nicegui/nicegui.py | 4 ---- nicegui/ui_run.py | 5 +++++ nicegui/ui_run_with.py | 5 ++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/nicegui/nicegui.py b/nicegui/nicegui.py index 893b4f81b..ea7eb83fe 100644 --- a/nicegui/nicegui.py +++ b/nicegui/nicegui.py @@ -7,7 +7,6 @@ import socketio from fastapi import HTTPException, Request -from fastapi.middleware.gzip import GZipMiddleware from fastapi.responses import FileResponse, Response from . import air, background_tasks, binding, core, favicon, helpers, json, run, welcome @@ -17,7 +16,6 @@ from .error import error_content from .json import NiceGUIJSONResponse from .logging import log -from .middlewares import RedirectWithPrefixMiddleware from .page import page from .slot import Slot from .staticfiles import CacheControlledStaticFiles @@ -54,8 +52,6 @@ async def __call__(self, scope, receive, send): mimetypes.add_type('text/javascript', '.js') mimetypes.add_type('text/css', '.css') -app.add_middleware(GZipMiddleware) -app.add_middleware(RedirectWithPrefixMiddleware) static_files = CacheControlledStaticFiles( directory=(Path(__file__).parent / 'static').resolve(), follow_symlink=True, diff --git a/nicegui/ui_run.py b/nicegui/ui_run.py index 708fd87ba..924670a27 100644 --- a/nicegui/ui_run.py +++ b/nicegui/ui_run.py @@ -4,6 +4,7 @@ from pathlib import Path from typing import Any, List, Literal, Optional, Tuple, TypedDict, Union +from fastapi.middleware.gzip import GZipMiddleware from starlette.routing import Route from uvicorn.main import STARTUP_FAILURE from uvicorn.supervisors import ChangeReload, Multiprocess @@ -16,6 +17,7 @@ from .client import Client from .language import Language from .logging import log +from .middlewares import RedirectWithPrefixMiddleware from .server import CustomServerConfig, Server APP_IMPORT_STRING = 'nicegui:app' @@ -122,6 +124,9 @@ def run(*, show_welcome_message=show_welcome_message, ) core.app.config.endpoint_documentation = endpoint_documentation + if not helpers.is_pytest(): + core.app.add_middleware(GZipMiddleware) + core.app.add_middleware(RedirectWithPrefixMiddleware) for route in core.app.routes: if not isinstance(route, Route): diff --git a/nicegui/ui_run_with.py b/nicegui/ui_run_with.py index a7a4e8640..29d519a2a 100644 --- a/nicegui/ui_run_with.py +++ b/nicegui/ui_run_with.py @@ -3,10 +3,12 @@ from typing import Literal, Optional, Union from fastapi import FastAPI +from fastapi.middleware.gzip import GZipMiddleware from . import core, storage from .air import Air from .language import Language +from .middlewares import RedirectWithPrefixMiddleware from .nicegui import _shutdown, _startup @@ -59,8 +61,9 @@ def run_with( prod_js=prod_js, show_welcome_message=show_welcome_message, ) - storage.set_storage_secret(storage_secret) + core.app.add_middleware(GZipMiddleware) + core.app.add_middleware(RedirectWithPrefixMiddleware) if on_air: core.air = Air('' if on_air is True else on_air)