From e6e7d7291f7cadfb2782c6ea4d67cafceec5a36b Mon Sep 17 00:00:00 2001 From: malay77patra Date: Tue, 28 Apr 2026 01:30:57 +0530 Subject: [PATCH 1/7] fixed frontend path issue --- reflex/utils/exec.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/reflex/utils/exec.py b/reflex/utils/exec.py index f2cbf387a10..816d6dc11d9 100644 --- a/reflex/utils/exec.py +++ b/reflex/utils/exec.py @@ -13,7 +13,6 @@ from collections.abc import Sequence from pathlib import Path from typing import Any, NamedTuple, TypedDict -from urllib.parse import urljoin from reflex_base import constants from reflex_base.config import get_config @@ -221,8 +220,6 @@ def run_process_and_launch_url( if match: if first_run: url = match.group(1) - if get_config().frontend_path != "": - url = urljoin(url, get_config().frontend_path) notify_frontend(url, backend_present) if backend_present: From 169158099c8357778d564f65a4b68afd4a3492c5 Mon Sep 17 00:00:00 2001 From: malay77patra Date: Tue, 28 Apr 2026 01:41:25 +0530 Subject: [PATCH 2/7] Extended test for fix --- .../tests_playwright/test_frontend_path.py | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index 8434938a894..bca26779ece 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -214,8 +214,8 @@ def bouncer_dynamic(): @pytest.fixture( scope="module", - params=["", "/prefix", "/prefix/nested"], - ids=["no-prefix", "single-level", "two-level"], + params=["", "/prefix", "/prefix/nested", "noslash"], + ids=["no-prefix", "single-level", "two-level", "no-slash"], ) def frontend_path(request: pytest.FixtureRequest) -> str: """Parametrise over no-prefix and various prefix depths. @@ -450,3 +450,23 @@ def test_navigate_back_and_forth(frontend_path_app: AppHarness, page: Page): expect(log).to_contain_text("index") expect(log).to_contain_text("static") expect(log).to_contain_text("dynamic-7") + + +def test_frontend_url_format(frontend_path_app: AppHarness, frontend_path: str): + """Verify that the frontend_url correctly incorporates the frontend_path.""" + url = frontend_path_app.frontend_url + assert url is not None + + from urllib.parse import urlparse + + parsed = urlparse(url) + + expected_path = frontend_path + if expected_path and not expected_path.startswith("/"): + expected_path = f"/{expected_path}" + if expected_path and not expected_path.endswith("/"): + expected_path = f"{expected_path}/" + if not expected_path: + expected_path = "/" + + assert parsed.path == expected_path \ No newline at end of file From 6861966d0cae6f4472e164324a777844d55b6ab5 Mon Sep 17 00:00:00 2001 From: malay77patra Date: Tue, 28 Apr 2026 01:49:27 +0530 Subject: [PATCH 3/7] ruff formatting done --- tests/integration/tests_playwright/test_frontend_path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index bca26779ece..94709949351 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -469,4 +469,4 @@ def test_frontend_url_format(frontend_path_app: AppHarness, frontend_path: str): if not expected_path: expected_path = "/" - assert parsed.path == expected_path \ No newline at end of file + assert parsed.path == expected_path From a64c38fdb40e05bbcbc6f1e5fa9eeaa9b05f12b3 Mon Sep 17 00:00:00 2001 From: malay77patra Date: Fri, 1 May 2026 16:15:35 +0530 Subject: [PATCH 4/7] chore: ignore pyright attribute error for nt module on windows --- reflex/utils/prerequisites.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflex/utils/prerequisites.py b/reflex/utils/prerequisites.py index 06662e53aa0..fd3a70813dc 100644 --- a/reflex/utils/prerequisites.py +++ b/reflex/utils/prerequisites.py @@ -320,7 +320,7 @@ def _safe_getenv(k: str, fallback: str | None = None) -> str | None: try: import nt - if not nt._supports_virtual_terminal(): + if not nt._supports_virtual_terminal(): # pyright: ignore[reportAttributeAccessIssue] return False except (ImportError, AttributeError): return False From 1de6dab4172e3ec9f2215c00b3ff5a520bfc03b1 Mon Sep 17 00:00:00 2001 From: malay77patra Date: Sun, 3 May 2026 02:59:41 +0530 Subject: [PATCH 5/7] Normalizing frontend_path fix --- packages/reflex-base/src/reflex_base/config.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/reflex-base/src/reflex_base/config.py b/packages/reflex-base/src/reflex_base/config.py index 9a522628e6a..9ff2895f5ce 100644 --- a/packages/reflex-base/src/reflex_base/config.py +++ b/packages/reflex-base/src/reflex_base/config.py @@ -348,6 +348,9 @@ def _post_init(self, **kwargs): for key, env_value in env_kwargs.items(): setattr(self, key, env_value) + # Normalize route prefixes to ensure they start with a slash. + self._normalize_paths() + # Normalize disable_plugins: convert strings and Plugin subclasses to instances. self._normalize_disable_plugins() @@ -418,6 +421,14 @@ def _normalize_disable_plugins(self): ) self.disable_plugins = normalized + def _normalize_paths(self): + """Ensure frontend and backend paths start with a slash if provided.""" + if self.frontend_path and not self.frontend_path.startswith("/"): + self.frontend_path = f"/{self.frontend_path}" + + if self.backend_path and not self.backend_path.startswith("/"): + self.backend_path = f"/{self.backend_path}" + def _add_builtin_plugins(self): """Add the builtin plugins to the config.""" for plugin in _PLUGINS_ENABLED_BY_DEFAULT: From c0c8fdf490f0b6bb104b849cba603d532f77cbbd Mon Sep 17 00:00:00 2001 From: malay77patra Date: Sun, 3 May 2026 03:08:45 +0530 Subject: [PATCH 6/7] Added test for the fix --- tests/integration/tests_playwright/test_frontend_path.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index 8434938a894..b3b1303d72f 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -214,8 +214,8 @@ def bouncer_dynamic(): @pytest.fixture( scope="module", - params=["", "/prefix", "/prefix/nested"], - ids=["no-prefix", "single-level", "two-level"], + params=["", "/prefix", "/prefix/nested", "noslash", "noslash/nested"], + ids=["no-prefix", "single-level", "two-level", "noslash-single-level", "noslash-two-level"], ) def frontend_path(request: pytest.FixtureRequest) -> str: """Parametrise over no-prefix and various prefix depths. From 3c760d2159f1bc3d78d4b98970e56fcb0998b138 Mon Sep 17 00:00:00 2001 From: malay77patra Date: Sun, 3 May 2026 03:11:41 +0530 Subject: [PATCH 7/7] Fixed double path logging --- reflex/utils/exec.py | 3 --- tests/integration/tests_playwright/test_frontend_path.py | 8 +++++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/reflex/utils/exec.py b/reflex/utils/exec.py index 0889e9359e1..451607e9bb2 100644 --- a/reflex/utils/exec.py +++ b/reflex/utils/exec.py @@ -13,7 +13,6 @@ from collections.abc import Sequence from pathlib import Path from typing import Any, NamedTuple, TypedDict -from urllib.parse import urljoin from reflex_base import constants from reflex_base.config import get_config @@ -227,8 +226,6 @@ def run_process_and_launch_url( if match: if first_run: url = match.group(1) - if get_config().frontend_path != "": - url = urljoin(url, get_config().frontend_path) notify_frontend(url, backend_present) if backend_present: diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index b3b1303d72f..e204c044079 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -215,7 +215,13 @@ def bouncer_dynamic(): @pytest.fixture( scope="module", params=["", "/prefix", "/prefix/nested", "noslash", "noslash/nested"], - ids=["no-prefix", "single-level", "two-level", "noslash-single-level", "noslash-two-level"], + ids=[ + "no-prefix", + "single-level", + "two-level", + "noslash-single-level", + "noslash-two-level", + ], ) def frontend_path(request: pytest.FixtureRequest) -> str: """Parametrise over no-prefix and various prefix depths.