From 350a051a459f5270dfcff8743ea14f5a393e7b9a Mon Sep 17 00:00:00 2001
From: Masen Furer <m_github@0x26.net>
Date: Mon, 26 Feb 2024 19:34:51 -0800
Subject: [PATCH] [REF-1741] Disallow routes with /api prefix (#2711)

---
 reflex/route.py   |  4 ++++
 tests/test_app.py | 22 ++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/reflex/route.py b/reflex/route.py
index 0986f7138..3f50eb96e 100644
--- a/reflex/route.py
+++ b/reflex/route.py
@@ -19,6 +19,10 @@ def verify_route_validity(route: str) -> None:
     pattern = catchall_in_route(route)
     if pattern and not route.endswith(pattern):
         raise ValueError(f"Catch-all must be the last part of the URL: {route}")
+    if route == "api" or route.startswith("api/"):
+        raise ValueError(
+            f"Cannot have a route prefixed with 'api/': {route} (conflicts with NextJS)"
+        )
 
 
 def get_route_args(route: str) -> dict[str, str]:
diff --git a/tests/test_app.py b/tests/test_app.py
index de7e5cdd9..b3153078a 100644
--- a/tests/test_app.py
+++ b/tests/test_app.py
@@ -275,6 +275,28 @@ def test_add_page_set_route_nested(app: App, index_page, windows_platform: bool)
     assert set(app.pages.keys()) == {route.strip(os.path.sep)}
 
 
+def test_add_page_invalid_api_route(app: App, index_page):
+    """Test adding a page with an invalid route to an app.
+
+    Args:
+        app: The app to test.
+        index_page: The index page.
+    """
+    with pytest.raises(ValueError):
+        app.add_page(index_page, route="api")
+    with pytest.raises(ValueError):
+        app.add_page(index_page, route="/api")
+    with pytest.raises(ValueError):
+        app.add_page(index_page, route="/api/")
+    with pytest.raises(ValueError):
+        app.add_page(index_page, route="api/foo")
+    with pytest.raises(ValueError):
+        app.add_page(index_page, route="/api/foo")
+    # These should be fine
+    app.add_page(index_page, route="api2")
+    app.add_page(index_page, route="/foo/api")
+
+
 def test_initialize_with_admin_dashboard(test_model):
     """Test setting the admin dashboard of an app.