@@ -213,6 +213,11 @@ class BaseConfig:
213213 dataclasses .field (default = ("*" ,))
214214 )
215215
216+ # Allowed hosts for the Vite dev server. Set to True to allow all hosts,
217+ # or provide a list of hostnames (e.g. ["myservice.local"]) to allow specific ones.
218+ # Prevents 403 errors in Docker, Codespaces, reverse proxies, etc.
219+ vite_allowed_hosts : bool | list [str ] = False
220+
216221 # Whether to use React strict mode.
217222 react_strict_mode : bool = True
218223
@@ -254,8 +259,8 @@ class BaseConfig:
254259 # List of plugins to use in the app.
255260 plugins : list [Plugin ] = dataclasses .field (default_factory = list )
256261
257- # List of fully qualified import paths of plugins to disable in the app (e.g. reflex.plugins.sitemap.SitemapPlugin) .
258- disable_plugins : list [str ] = dataclasses .field (default_factory = list )
262+ # List of plugin types to disable in the app.
263+ disable_plugins : list [type [ Plugin ] ] = dataclasses .field (default_factory = list )
259264
260265 # The transport method for client-server communication.
261266 transport : Literal ["websocket" , "polling" ] = "websocket"
@@ -353,6 +358,9 @@ def _post_init(self, **kwargs):
353358 for key , env_value in env_kwargs .items ():
354359 setattr (self , key , env_value )
355360
361+ # Normalize disable_plugins: convert strings and Plugin subclasses to instances.
362+ self ._normalize_disable_plugins ()
363+
356364 # Add builtin plugins if not disabled.
357365 if not self ._skip_plugins_checks :
358366 self ._add_builtin_plugins ()
@@ -369,16 +377,52 @@ def _post_init(self, **kwargs):
369377 msg = f"{ self ._prefixes [0 ]} REDIS_URL is required when using the redis state manager."
370378 raise ConfigError (msg )
371379
380+ def _normalize_disable_plugins (self ):
381+ """Normalize disable_plugins list entries to Plugin subclasses.
382+
383+ Handles backward compatibility by converting strings (fully qualified
384+ import paths) and Plugin instances to their associated classes.
385+ """
386+ normalized : list [type [Plugin ]] = []
387+ for entry in self .disable_plugins :
388+ if isinstance (entry , type ) and issubclass (entry , Plugin ):
389+ normalized .append (entry )
390+ elif isinstance (entry , Plugin ):
391+ normalized .append (type (entry ))
392+ elif isinstance (entry , str ):
393+ console .deprecate (
394+ feature_name = "Passing strings to disable_plugins" ,
395+ reason = "pass Plugin classes directly instead, e.g. disable_plugins=[SitemapPlugin]" ,
396+ deprecation_version = "0.8.28" ,
397+ removal_version = "0.9.0" ,
398+ )
399+ try :
400+ from reflex .environment import interpret_plugin_class_env
401+
402+ normalized .append (
403+ interpret_plugin_class_env (entry , "disable_plugins" )
404+ )
405+ except Exception :
406+ console .warn (
407+ f"Failed to import plugin from string { entry !r} in disable_plugins. "
408+ "Please pass Plugin subclasses directly." ,
409+ )
410+ else :
411+ console .warn (
412+ f"reflex.Config.disable_plugins should contain Plugin subclasses, but got { entry !r} ." ,
413+ )
414+ self .disable_plugins = normalized
415+
372416 def _add_builtin_plugins (self ):
373417 """Add the builtin plugins to the config."""
374418 for plugin in _PLUGINS_ENABLED_BY_DEFAULT :
375419 plugin_name = plugin .__module__ + "." + plugin .__qualname__
376- if plugin_name not in self .disable_plugins :
420+ if plugin not in self .disable_plugins :
377421 if not any (isinstance (p , plugin ) for p in self .plugins ):
378422 console .warn (
379423 f"`{ plugin_name } ` plugin is enabled by default, but not explicitly added to the config. "
380424 "If you want to use it, please add it to the `plugins` list in your config inside of `rxconfig.py`. "
381- f"To disable this plugin, set `disable_plugins ` to ` { [ plugin_name , * self . disable_plugins ]!r } ` ." ,
425+ f"To disable this plugin, add ` { plugin . __name__ } ` to the ` disable_plugins` list ." ,
382426 )
383427 self .plugins .append (plugin ())
384428 else :
@@ -389,16 +433,9 @@ def _add_builtin_plugins(self):
389433 )
390434
391435 for disabled_plugin in self .disable_plugins :
392- if not isinstance (disabled_plugin , str ):
393- console .warn (
394- f"reflex.Config.disable_plugins should only contain strings, but got { disabled_plugin !r} . "
395- )
396- if not any (
397- plugin .__module__ + "." + plugin .__qualname__ == disabled_plugin
398- for plugin in _PLUGINS_ENABLED_BY_DEFAULT
399- ):
436+ if disabled_plugin not in _PLUGINS_ENABLED_BY_DEFAULT :
400437 console .warn (
401- f"`{ disabled_plugin } ` is disabled in the config, but it is not a built-in plugin. "
438+ f"`{ disabled_plugin !r } ` is disabled in the config, but it is not a built-in plugin. "
402439 "Please remove it from the `disable_plugins` list in your config inside of `rxconfig.py`." ,
403440 )
404441
0 commit comments