diff --git a/reflex/config.py b/reflex/config.py index f3d40dc37..891911ca6 100644 --- a/reflex/config.py +++ b/reflex/config.py @@ -615,13 +615,13 @@ class Config(Base): loglevel: constants.LogLevel = constants.LogLevel.DEFAULT # The port to run the frontend on. NOTE: When running in dev mode, the next available port will be used if this is taken. - frontend_port: int = constants.DefaultPorts.FRONTEND_PORT + frontend_port: int | None = None # The path to run the frontend on. For example, "/app" will run the frontend on http://localhost:3000/app frontend_path: str = "" # The port to run the backend on. NOTE: When running in dev mode, the next available port will be used if this is taken. - backend_port: int = constants.DefaultPorts.BACKEND_PORT + backend_port: int | None = None # The backend url the frontend will connect to. This must be updated if the backend is hosted elsewhere, or in production. api_url: str = f"http://localhost:{backend_port}" diff --git a/reflex/reflex.py b/reflex/reflex.py index 70aa16a05..340fdfd71 100644 --- a/reflex/reflex.py +++ b/reflex/reflex.py @@ -127,8 +127,8 @@ def _run( env: constants.Env = constants.Env.DEV, frontend: bool = True, backend: bool = True, - frontend_port: int = config.frontend_port, - backend_port: int = config.backend_port, + frontend_port: int | None = None, + backend_port: int | None = None, backend_host: str = config.backend_host, loglevel: constants.LogLevel = config.loglevel, ): @@ -161,17 +161,28 @@ def _run( # Find the next available open port if applicable. if frontend: + autoswitch_frontend = not bool(frontend_port or config.frontend_port) frontend_port = processes.handle_port( "frontend", - frontend_port, - constants.DefaultPorts.FRONTEND_PORT, + ( + frontend_port + or config.frontend_port + or constants.DefaultPorts.FRONTEND_PORT + ), + autoswitch=autoswitch_frontend, ) if backend: + autoswitch_backend = not bool(backend_port or config.backend_port) + backend_port = processes.handle_port( "backend", - backend_port, - constants.DefaultPorts.BACKEND_PORT, + ( + backend_port + or config.backend_port + or constants.DefaultPorts.BACKEND_PORT + ), + autoswitch=autoswitch_backend, ) # Apply the new ports to the config. @@ -249,7 +260,7 @@ def _run( # Start the frontend and backend. with processes.run_concurrently_context(*commands): # In dev mode, run the backend on the main thread. - if backend and env == constants.Env.DEV: + if backend and backend_port and env == constants.Env.DEV: backend_cmd( backend_host, int(backend_port), loglevel.subprocess_level(), frontend ) diff --git a/reflex/utils/processes.py b/reflex/utils/processes.py index c92fb7d1a..c7a90320b 100644 --- a/reflex/utils/processes.py +++ b/reflex/utils/processes.py @@ -116,7 +116,7 @@ def change_port(port: int, _type: str) -> int: return new_port -def handle_port(service_name: str, port: int, default_port: int) -> int: +def handle_port(service_name: str, port: int, autoswitch: bool) -> int: """Change port if the specified port is in use and is not explicitly specified as a CLI arg or config arg. otherwise tell the user the port is in use and exit the app. @@ -126,7 +126,7 @@ def handle_port(service_name: str, port: int, default_port: int) -> int: Args: service_name: The frontend or backend. port: The provided port. - default_port: The default port number associated with the specified service. + autoswitch: Whether to automatically switch the port. Returns: The port to run the service on. @@ -134,13 +134,13 @@ def handle_port(service_name: str, port: int, default_port: int) -> int: Raises: Exit:when the port is in use. """ - if is_process_on_port(port): - if port == int(default_port): - return change_port(port, service_name) - else: - console.error(f"{service_name.capitalize()} port: {port} is already in use") - raise typer.Exit() - return port + if not is_process_on_port(port): + return port + if autoswitch: + return change_port(port, service_name) + else: + console.error(f"{service_name.capitalize()} port: {port} is already in use") + raise typer.Exit() def new_process(