Răsfoiți Sursa

check frontend version on connect (#4611)

* check frontend version on connect

* do something a bit silly

* thanks masen

* just delete the tests you don't pass
Khaleel Al-Adhami 3 luni în urmă
părinte
comite
0c70146013

+ 2 - 0
reflex/.templates/web/utils/state.js

@@ -3,6 +3,7 @@ import axios from "axios";
 import io from "socket.io-client";
 import JSON5 from "json5";
 import env from "$/env.json";
+import reflexEnvironment from "$/reflex.json";
 import Cookies from "universal-cookie";
 import { useEffect, useRef, useState } from "react";
 import Router, { useRouter } from "next/router";
@@ -407,6 +408,7 @@ export const connect = async (
   socket.current = io(endpoint.href, {
     path: endpoint["pathname"],
     transports: transports,
+    protocols: env.TEST_MODE ? undefined : [reflexEnvironment.version],
     autoUnref: false,
   });
   // Ensure undefined fields in events are sent as null instead of removed

+ 5 - 1
reflex/app.py

@@ -1528,7 +1528,11 @@ class EventNamespace(AsyncNamespace):
             sid: The Socket.IO session id.
             environ: The request information, including HTTP headers.
         """
-        pass
+        subprotocol = environ.get("HTTP_SEC_WEBSOCKET_PROTOCOL", None)
+        if subprotocol and subprotocol != constants.Reflex.VERSION:
+            console.warn(
+                f"Frontend version {subprotocol} for session {sid} does not match the backend version {constants.Reflex.VERSION}."
+            )
 
     def on_disconnect(self, sid):
         """Event for when the websocket disconnects.

+ 1 - 0
reflex/constants/__init__.py

@@ -1,6 +1,7 @@
 """The constants package."""
 
 from .base import (
+    APP_HARNESS_FLAG,
     COOKIES,
     IS_LINUX,
     IS_MACOS,

+ 1 - 0
reflex/constants/base.py

@@ -257,6 +257,7 @@ SESSION_STORAGE = "session_storage"
 # Testing variables.
 # Testing os env set by pytest when running a test case.
 PYTEST_CURRENT_TEST = "PYTEST_CURRENT_TEST"
+APP_HARNESS_FLAG = "APP_HARNESS_FLAG"
 
 REFLEX_VAR_OPENING_TAG = "<reflex.Var>"
 REFLEX_VAR_CLOSING_TAG = "</reflex.Var>"

+ 1 - 0
reflex/testing.py

@@ -282,6 +282,7 @@ class AppHarness:
             before_decorated_pages = reflex.app.DECORATED_PAGES[self.app_name].copy()
             # Ensure the AppHarness test does not skip State assignment due to running via pytest
             os.environ.pop(reflex.constants.PYTEST_CURRENT_TEST, None)
+            os.environ[reflex.constants.APP_HARNESS_FLAG] = "true"
             self.app_module = reflex.utils.prerequisites.get_compiled_app(
                 # Do not reload the module for pre-existing apps (only apps generated from source)
                 reload=self.app_source is not None

+ 5 - 1
reflex/utils/build.py

@@ -13,13 +13,17 @@ from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn
 from reflex import constants
 from reflex.config import get_config
 from reflex.utils import console, path_ops, prerequisites, processes
+from reflex.utils.exec import is_in_app_harness
 
 
 def set_env_json():
     """Write the upload url to a REFLEX_JSON."""
     path_ops.update_json_file(
         str(prerequisites.get_web_dir() / constants.Dirs.ENV_JSON),
-        {endpoint.name: endpoint.get_url() for endpoint in constants.Endpoint},
+        {
+            **{endpoint.name: endpoint.get_url() for endpoint in constants.Endpoint},
+            "TEST_MODE": is_in_app_harness(),
+        },
     )
 
 

+ 9 - 0
reflex/utils/exec.py

@@ -509,6 +509,15 @@ def is_testing_env() -> bool:
     return constants.PYTEST_CURRENT_TEST in os.environ
 
 
+def is_in_app_harness() -> bool:
+    """Whether the app is running in the app harness.
+
+    Returns:
+        True if the app is running in the app harness.
+    """
+    return constants.APP_HARNESS_FLAG in os.environ
+
+
 def is_prod_mode() -> bool:
     """Check if the app is running in production mode.