Plugin

Vite Plugin for Litestar.

This module provides the VitePlugin class for integrating Vite with Litestar. The plugin handles:

  • Static file serving configuration

  • Jinja2 template callable registration

  • Vite dev server process management

  • Async asset loader initialization

  • Development proxies for Vite HTTP and HMR WebSockets (with hop-by-hop header filtering)

Example:

from litestar import Litestar
from litestar_vite import VitePlugin, ViteConfig

app = Litestar(
    plugins=[VitePlugin(config=ViteConfig(dev_mode=True))],
)
class litestar_vite.plugin.ProxyHeadersMiddleware[source]

Bases: AbstractMiddleware

ASGI middleware for secure proxy header handling.

Only processes X-Forwarded-* headers when the direct caller (scope[“client”]) is in the trusted hosts list. This prevents header spoofing attacks.

Handles:
  • X-Forwarded-Proto: Sets scope[“scheme”] (http/https/ws/wss)

  • X-Forwarded-For: Sets scope[“client”] to the real client IP

  • X-Forwarded-Host: Optionally sets the Host header

Security:

Never blindly trusts headers from any client. Validates caller IP against trusted hosts before reading headers. Validates scheme values to only allow http/https/ws/wss.

Example:

from litestar_vite import VitePlugin, ViteConfig
from litestar_vite.config import RuntimeConfig

# Trust all proxies (Railway, Heroku, container environments)
app = Litestar(
    plugins=[VitePlugin(config=ViteConfig(
        runtime=RuntimeConfig(trusted_proxies="*")
    ))]
)

# Trust specific proxy IPs
app = Litestar(
    plugins=[VitePlugin(config=ViteConfig(
        runtime=RuntimeConfig(trusted_proxies=["10.0.0.0/8", "172.16.0.0/12"])
    ))]
)
__init__(app: ASGIApp, trusted_hosts: list[str] | str = '127.0.0.1', handle_forwarded_host: bool = True) None[source]

Initialize the proxy headers middleware.

Parameters:
  • app – The ASGI application to wrap.

  • trusted_hosts – Hosts to trust for X-Forwarded-* headers. Defaults to “127.0.0.1” (localhost only).

  • handle_forwarded_host – Whether to handle X-Forwarded-Host header for Host header rewriting. Defaults to True.

class litestar_vite.plugin.StaticFilesConfig[source]

Bases: object

Configuration for static file serving.

This configuration is passed to Litestar’s static files router.

__init__(after_request: AfterRequestHookHandler | None = None, after_response: AfterResponseHookHandler | None = None, before_request: BeforeRequestHookHandler | None = None, cache_control: CacheControlHeader | None = None, exception_handlers: ExceptionHandlersMap | None = None, guards: list[Guard] | None = None, middleware: Sequence[Middleware] | None = None, opt: dict[str, Any] | None = None, security: Sequence[SecurityRequirement] | None = None, tags: Sequence[str] | None = None) None
class litestar_vite.plugin.TrustedHosts[source]

Bases: object

Container for trusted proxy hosts and networks.

Provides efficient lookup for IP addresses and CIDR networks. Following Uvicorn’s security model for proxy header validation.

Supports:
  • Wildcard “*” to trust all hosts (for controlled environments)

  • IPv4 addresses: “192.168.1.1”

  • IPv6 addresses: “::1”

  • CIDR notation: “10.0.0.0/8”, “fd00::/8”

  • Literals for non-IP hosts (e.g., Unix socket paths)

__contains__(host: str | None) bool[source]

Check if a host is trusted.

Parameters:

host – The host to check. Can be an IP address or literal.

Returns:

True if the host is trusted, False otherwise.

__init__(trusted_hosts: list[str] | str) None[source]

Initialize trusted hosts container.

Parameters:

trusted_hosts – A single host, comma-separated string, or list of hosts. Use “*” to trust all hosts (only in controlled environments).

get_trusted_client_host(x_forwarded_for: str) str[source]

Extract the real client IP from X-Forwarded-For header.

The X-Forwarded-For header contains a comma-separated list of IPs. Each proxy appends the client IP to the list. We find the first untrusted host (reading from right to left) which is the real client.

Parameters:

x_forwarded_for – The X-Forwarded-For header value.

Returns:

The first untrusted host in the chain, or the original client if all hosts are trusted.

class litestar_vite.plugin.VitePlugin[source]

Bases: InitPluginProtocol, CLIPlugin

Vite plugin for Litestar.

This plugin integrates Vite with Litestar, providing:

  • Static file serving configuration

  • Jinja2 template callables for asset tags

  • Vite dev server process management

  • Async asset loader initialization

Example:

from litestar import Litestar
from litestar_vite import VitePlugin, ViteConfig

app = Litestar(
    plugins=[
        VitePlugin(config=ViteConfig(dev_mode=True))
    ],
)
__init__(config: ViteConfig | None = None, asset_loader: ViteAssetLoader | None = None, static_files_config: StaticFilesConfig | None = None) None[source]

Initialize the Vite plugin.

Parameters:
  • config – Vite configuration. Defaults to ViteConfig() if not provided.

  • asset_loader – Optional pre-initialized asset loader.

  • static_files_config – Optional configuration for static file serving.

property config: ViteConfig

Get the Vite configuration.

Returns:

The ViteConfig instance.

property asset_loader: ViteAssetLoader

Get the asset loader instance.

Lazily initializes the loader if not already set.

Returns:

The ViteAssetLoader instance.

property spa_handler: AppHandler | None

Return the configured SPA handler when SPA mode is enabled.

Returns:

The AppHandler instance, or None when SPA mode is disabled/not configured.

property proxy_client: AsyncClient | None

Return the shared httpx.AsyncClient for proxy requests.

The client is initialized during app lifespan (dev mode only) and provides connection pooling, TLS session reuse, and HTTP/2 multiplexing benefits.

Returns:

The shared AsyncClient instance, or None if not initialized or not in dev mode.

on_cli_init(cli: Group) None[source]

Register CLI commands.

Parameters:

cli – The Click command group to add commands to.

on_app_init(app_config: AppConfig) AppConfig[source]

Configure the Litestar application for Vite.

This method wires up supporting configuration for dev/prod operation:

  • Adds types used by generated handlers to the signature namespace.

  • Ensures a consistent NotFound handler for asset/proxy lookups.

  • Registers optional Inertia and Jinja integrations.

  • Configures static file routing when enabled.

  • Configures dev proxy middleware based on proxy_mode.

  • Creates/initializes the SPA handler where applicable and registers lifespans.

Parameters:

app_config – The Litestar application configuration.

Returns:

The modified application configuration.

server_lifespan(app: Litestar) Iterator[None][source]

Server-level lifespan context manager (runs ONCE per server, before workers).

This is called by Litestar CLI before workers start. It handles: - Environment variable setup (with logging) - Vite dev server process start/stop (ONE instance for all workers) - Type export on startup

Note: SPA handler and asset loader initialization happens in the per-worker lifespan method, which is auto-registered in on_app_init.

Hotfile behavior: the hotfile is written before starting the dev server to ensure proxy middleware and SPA handlers can resolve a target URL immediately on first request.

Parameters:

app – The Litestar application instance.

Yields:

None

lifespan(app: Litestar) AsyncIterator[None][source]

Worker-level lifespan context manager (runs per worker process).

This is auto-registered in on_app_init and handles per-worker initialization: - Environment variable setup (silently - each worker needs process-local env vars) - Shared proxy client initialization (dev mode only, for ViteProxyMiddleware/SSRProxyController) - Asset loader initialization - SPA handler initialization - Route metadata injection

Note: The Vite dev server process is started in server_lifespan, which runs ONCE per server before workers start.

Parameters:

app – The Litestar application instance.

Yields:

None

class litestar_vite.plugin.ViteProcess[source]

Bases: object

Manages the Vite development server process.

This class handles starting and stopping the Vite dev server process, with proper thread safety and graceful shutdown. It registers signal handlers for SIGTERM and SIGINT to ensure child processes are terminated even if Python is killed externally.

__init__(executor: JSExecutor) None[source]

Initialize the Vite process manager.

Parameters:

executor – The JavaScript executor to use for running Vite.

start(command: list[str], cwd: Path | str | None) None[source]

Start the Vite process.

Parameters:
  • command – The command to run (e.g., [“npm”, “run”, “dev”]).

  • cwd – The working directory for the process.

If the process exits immediately, this method captures stdout/stderr and raises a ViteProcessError with diagnostic details.

Raises:

ViteProcessError – If the process fails to start.

stop(timeout: float = 5.0) None[source]

Stop the Vite process and all its child processes.

Uses process groups to ensure child processes (node, astro, nuxt, vite, etc.) are terminated along with the parent npm/npx process.

Parameters:

timeout – Seconds to wait for graceful shutdown before killing.

Raises:

ViteProcessError – If the process fails to stop.

class litestar_vite.plugin.ViteProxyMiddleware[source]

Bases: AbstractMiddleware

ASGI middleware to proxy Vite dev HTTP traffic to internal Vite server.

HTTP requests use httpx.AsyncClient with optional HTTP/2 support for better connection multiplexing. WebSocket traffic (used by Vite HMR) is handled by a dedicated WebSocket route handler created by create_vite_hmr_handler().

The middleware reads the Vite server URL from the hotfile dynamically, ensuring it always connects to the correct Vite server even if the port changes.

__init__(app: ASGIApp, hotfile_path: Path, asset_url: str | None = None, resource_dir: Path | None = None, bundle_dir: Path | None = None, root_dir: Path | None = None, http2: bool = True, plugin: VitePlugin | None = None) None[source]

Initialize the middleware.

Parameters:
  • app – The next ASGI app to call.

  • exclude – A pattern or list of patterns to match against a request’s path. If a match is found, the middleware will be skipped.

  • exclude_opt_key – An identifier that is set in the route handler opt key which allows skipping the middleware.

  • scopes – ASGI scope types, should be a set including either or both ‘ScopeType.HTTP’ and ‘ScopeType.WEBSOCKET’.

litestar_vite.plugin.create_ssr_proxy_controller(target: str | None = None, hotfile_path: Path | None = None, http2: bool = True, plugin: VitePlugin | None = None) type[source]

Create a Controller that proxies to an SSR framework dev server.

This controller is used for SSR frameworks (Astro, Nuxt, SvelteKit) where all non-API requests should be proxied to the framework’s dev server for rendering.

Parameters:
  • target – Static target URL to proxy to. If None, uses hotfile for dynamic discovery.

  • hotfile_path – Path to the hotfile for dynamic target discovery.

  • http2 – Enable HTTP/2 for proxy connections.

  • plugin – Optional VitePlugin reference for accessing shared proxy client.

Returns:

A Litestar Controller class with HTTP and WebSocket handlers for SSR proxy.

litestar_vite.plugin.create_vite_hmr_handler(hotfile_path: Path, hmr_path: str = '/static/vite-hmr', asset_url: str = '/static/') Any[source]

Create a WebSocket route handler for Vite HMR proxy.

This handler proxies WebSocket connections from the browser to the Vite dev server for Hot Module Replacement (HMR) functionality.

Parameters:
  • hotfile_path – Path to the hotfile written by the Vite plugin.

  • hmr_path – The path to register the WebSocket handler at.

  • asset_url – The asset URL prefix to strip when connecting to Vite.

Returns:

A WebsocketRouteHandler that proxies HMR connections.

litestar_vite.plugin.get_litestar_route_prefixes(app: Litestar) tuple[str, ...][source]

Build a cached list of Litestar route prefixes for the given app.

This function collects all registered route paths from the Litestar application and caches them for efficient lookup. The cache is stored in app.state to ensure it’s automatically cleaned up when the app is garbage collected.

Includes: - All registered Litestar route paths - OpenAPI schema path (customizable via openapi_config.path) - Common API prefixes as fallback (/api, /schema, /docs)

Parameters:

app – The Litestar application instance.

Returns:

A tuple of route prefix strings (without trailing slashes).

litestar_vite.plugin.is_litestar_route(path: str, app: Litestar) bool[source]

Check if a path matches a registered Litestar route.

This function determines if a request path should be handled by Litestar rather than proxied to the Vite dev server or served as SPA content.

A path matches if it equals a registered prefix or starts with prefix + “/”.

Parameters:
  • path – The request path to check (e.g., “/schema”, “/api/users”).

  • app – The Litestar application instance.

Returns:

True if the path matches a Litestar route, False otherwise.

litestar_vite.plugin.resolve_litestar_version() str[source]

Return the installed Litestar version string.

Returns:

The installed Litestar version, or “unknown” when unavailable.

litestar_vite.plugin.set_app_environment(app: Litestar) None[source]

Set environment variables derived from the Litestar app instance.

This is called after set_environment() once the app is available, to export app-specific configuration like OpenAPI paths.

Parameters:

app – The Litestar application instance.

litestar_vite.plugin.set_environment(config: ViteConfig, asset_url_override: str | None = None) None[source]

Configure environment variables for Vite integration.

Sets environment variables that can be used by both the Python backend and the Vite frontend during development.

Parameters:
  • config – The Vite configuration.

  • asset_url_override – Optional asset URL to force (e.g., CDN base during build).