Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions reflex/istate/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from urllib.parse import _NetlocResultMixinStr, parse_qsl, urlsplit

from reflex_base import constants
from reflex_base.config import get_config
from reflex_base.utils import console, format
from reflex_base.utils.serializers import serializer
from reflex_base.vars.base import (
Expand Down Expand Up @@ -360,7 +361,12 @@ def from_router_data(cls, router_data: dict) -> "PageData":
"""
host = router_data.get(constants.RouteVar.HEADERS, {}).get("origin", "")
path = router_data.get(constants.RouteVar.PATH, "")
raw_path = router_data.get(constants.RouteVar.ORIGIN, "")
# raw_path is the browser-visible URL path, so it includes the configured
# frontend_path prefix. path remains the matched route pattern, which is
# defined without the prefix.
raw_path = get_config().prepend_frontend_path(
router_data.get(constants.RouteVar.ORIGIN, "")
)
return cls(
host=host,
path=path,
Expand Down Expand Up @@ -447,7 +453,9 @@ def from_router_data(cls, router_data: dict) -> "RouterData":
_page=PageData.from_router_data(router_data),
url=ReflexURL(
router_data.get(constants.RouteVar.HEADERS, {}).get("origin", "")
+ router_data.get(constants.RouteVar.ORIGIN, "")
+ get_config().prepend_frontend_path(
router_data.get(constants.RouteVar.ORIGIN, "")
)
),
route_id=router_data.get(constants.RouteVar.PATH, ""),
)
Expand Down
73 changes: 73 additions & 0 deletions tests/integration/tests_playwright/test_frontend_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from __future__ import annotations

import re
from collections.abc import Generator

import httpx
Expand Down Expand Up @@ -107,6 +108,25 @@ def _chunk(chunk_type: bytes, data: bytes) -> bytes:

# ---- Pages ----

def _router_info():
return rx.fragment(
rx.input(
value=FPState.router.url,
read_only=True,
id="router-url",
),
rx.input(
value=FPState.router.url.path,
read_only=True,
id="router-url-path",
),
rx.input(
value=FPState.router.page.raw_path, # pyright: ignore[reportDeprecated]
read_only=True,
id="router-page-raw-path",
),
)

@rx.page("/", on_load=FPState.on_load_index)
def index():
return rx.box(
Expand All @@ -117,6 +137,7 @@ def index():
read_only=True,
id="token",
),
_router_info(),
# Links to app-relative paths.
rx.link("go to static", href="/static-page", id="link-static"),
rx.link("go to dynamic 7", href="/dynamic/7", id="link-dynamic"),
Expand Down Expand Up @@ -169,6 +190,7 @@ def static_page():
read_only=True,
id="token",
),
_router_info(),
rx.link("go home", href="/", id="link-home"),
rx.link("go to dynamic 7", href="/dynamic/7", id="link-dynamic"),
rx.box(
Expand All @@ -186,6 +208,7 @@ def dynamic_page():
read_only=True,
id="token",
),
_router_info(),
rx.link("go home", href="/", id="link-home"),
rx.link("go to static", href="/static-page", id="link-static"),
rx.box(
Expand Down Expand Up @@ -458,6 +481,56 @@ def test_navigate_back_and_forth(frontend_path_app: AppHarness, page: Page):
expect(log).to_contain_text("dynamic-7")


def test_router_includes_frontend_path(
frontend_path_app: AppHarness, page: Page, frontend_path: str
):
"""State.router.url and State.router.page expose paths prefixed with frontend_path."""
base = _navigate(frontend_path_app, page)

prefix = "/" + frontend_path.strip("/") if frontend_path else ""

# Index page: in-app path is "/".
expected_path = f"{prefix}/"
expect(page.locator("#router-url-path")).to_have_value(expected_path)
expect(page.locator("#router-page-raw-path")).to_have_value(expected_path)
expect(page.locator("#router-url")).to_have_value(
re.compile(rf".+{re.escape(expected_path)}$")
)
expect(page.locator("#router-url")).to_have_value(f"{base}/")
Comment thread
masenf marked this conversation as resolved.

# Client-side navigation to static page.
page.click("#link-static")
expect(page.locator("#page-id")).to_have_text("static page")
expected_path = f"{prefix}/static-page"
expect(page.locator("#router-url-path")).to_have_value(expected_path)
expect(page.locator("#router-page-raw-path")).to_have_value(expected_path)
expect(page.locator("#router-url")).to_have_value(
re.compile(rf".+{re.escape(expected_path)}$")
)
expect(page.locator("#router-url")).to_have_value(f"{base}/static-page")

# Client-side navigation to dynamic page.
page.click("#link-dynamic")
expect(page.locator("#page-id")).to_contain_text("dynamic page")
expected_path = f"{prefix}/dynamic/7"
expect(page.locator("#router-url-path")).to_have_value(expected_path)
expect(page.locator("#router-page-raw-path")).to_have_value(expected_path)
expect(page.locator("#router-url")).to_have_value(
re.compile(rf".+{re.escape(expected_path)}$")
)
expect(page.locator("#router-url")).to_have_value(f"{base}/dynamic/7")

# Direct (full-page-load) navigation to dynamic page with different id.
_navigate(frontend_path_app, page, "/dynamic/42")
expected_path = f"{prefix}/dynamic/42"
expect(page.locator("#router-url-path")).to_have_value(expected_path)
expect(page.locator("#router-page-raw-path")).to_have_value(expected_path)
expect(page.locator("#router-url")).to_have_value(
re.compile(rf".+{re.escape(expected_path)}$")
)
expect(page.locator("#router-url")).to_have_value(f"{base}/dynamic/42")


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
Expand Down
Loading