Add fastapi_vue.env accessor with FASTAPI_VUE prefix
This commit is contained in:
@@ -68,3 +68,13 @@ server.run("my_app.app:app", listen=["localhost:8000"])
|
||||
```
|
||||
|
||||
- As a deployment option, environment `FORWARDED_ALLOW_IPS` controls `X-Forwarded` trusted IPs (default: `127.0.0.1,::1`).
|
||||
|
||||
## Environment variables
|
||||
|
||||
The generated project entry point sets `FASTAPI_VUE` to the project's environment prefix (e.g. `MY_APP`), and settings are passed as `<PREFIX>_*` variables. `fastapi_vue.env` resolves them, lazily on each access:
|
||||
|
||||
- `fastapi_vue.env.dev` — running under the devserver (`<PREFIX>_DEV=1`)
|
||||
- `fastapi_vue.env.vite_url`, `fastapi_vue.env.backend_url` — URLs set by the devserver
|
||||
- `fastapi_vue.env.prefix` — the prefix itself
|
||||
|
||||
Value accessors return `None` when `FASTAPI_VUE` or the variable is not set.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""FastAPI Vue integration - serve Vue frontend from FastAPI."""
|
||||
|
||||
from .environ import env
|
||||
from .staticfiles import Frontend
|
||||
|
||||
__all__ = ["Frontend"]
|
||||
__all__ = ["Frontend", "env"]
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
"""Access to the project's fastapi-vue environment variables.
|
||||
|
||||
The project entry point (generated __main__.py) sets FASTAPI_VUE to the
|
||||
project-specific prefix (e.g. "MY_APP"). Project settings are then passed
|
||||
as "<PREFIX>_*" environment variables; this module is the single place
|
||||
that resolves those names.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
PREFIX_VARIABLE = "FASTAPI_VUE"
|
||||
|
||||
|
||||
class _Env:
|
||||
"""Lazy accessors for the project's "<PREFIX>_*" environment variables.
|
||||
|
||||
Evaluated on each access. Value accessors return None when FASTAPI_VUE
|
||||
or the variable itself is not set.
|
||||
"""
|
||||
|
||||
@property
|
||||
def prefix(self) -> str | None:
|
||||
"""Return the project prefix from the FASTAPI_VUE environment variable."""
|
||||
return os.environ.get(PREFIX_VARIABLE) or None
|
||||
|
||||
def _get(self, name: str) -> str | None:
|
||||
prefix = self.prefix
|
||||
return os.environ.get(f"{prefix}_{name}") if prefix else None
|
||||
|
||||
@property
|
||||
def dev(self) -> bool:
|
||||
"""Check whether running under the devserver (<PREFIX>_DEV=1)."""
|
||||
return self._get("DEV") == "1"
|
||||
|
||||
@property
|
||||
def vite_url(self) -> str | None:
|
||||
"""Return the vite devserver URL (<PREFIX>_VITE_URL), if set."""
|
||||
return self._get("VITE_URL")
|
||||
|
||||
@property
|
||||
def backend_url(self) -> str | None:
|
||||
"""Return the backend URL (<PREFIX>_BACKEND_URL), if set."""
|
||||
return self._get("BACKEND_URL")
|
||||
|
||||
|
||||
env = _Env()
|
||||
@@ -15,6 +15,7 @@ from uvicorn import Config, Server
|
||||
from uvicorn.main import STARTUP_FAILURE
|
||||
from uvicorn.supervisors import ChangeReload, Multiprocess
|
||||
|
||||
from .environ import env
|
||||
from .hostutil import parse_endpoints
|
||||
from .logging import (
|
||||
install_access_log,
|
||||
@@ -44,10 +45,16 @@ def _bind_hosts(host: str) -> list[str]:
|
||||
|
||||
|
||||
def _connect_url(endpoints: list[dict]) -> str:
|
||||
"""Return a URL the user can connect to for the first TCP endpoint."""
|
||||
for key, value in sorted(os.environ.items()):
|
||||
if key.endswith("_VITE_URL") and value:
|
||||
return value
|
||||
"""Return a URL the user can connect to for the first TCP endpoint.
|
||||
|
||||
When running under the devserver (<PREFIX>_VITE_URL is set), the vite
|
||||
devserver URL is shown instead, as that is where the page is served.
|
||||
Wildcard binds (0.0.0.0, ::) are shown as localhost, as that is the
|
||||
address a user can actually open. Unix-socket-only setups show plain
|
||||
http://localhost (the typical reverse-proxy target).
|
||||
"""
|
||||
if vite_url := env.vite_url:
|
||||
return vite_url
|
||||
for endpoint in endpoints:
|
||||
host = endpoint.get("host")
|
||||
if host is None:
|
||||
|
||||
@@ -19,6 +19,8 @@ from starlette.exceptions import HTTPException
|
||||
from starlette.routing import Route
|
||||
from zstandard import ZstdCompressor
|
||||
|
||||
from .environ import env
|
||||
|
||||
logger = logging.getLogger("uvicorn.error") # Use FastAPI logging style
|
||||
|
||||
__all__ = ["Frontend"]
|
||||
@@ -287,7 +289,8 @@ class Frontend:
|
||||
|
||||
def _devmode_respond(_request: Request, _name: str = "") -> JSONResponse:
|
||||
"""Return error response directing to Vite server."""
|
||||
at = f" at {env.vite_url}" if env.vite_url else ""
|
||||
return JSONResponse(
|
||||
status_code=409,
|
||||
content={"detail": "[devmode] Use Vite devserver instead."},
|
||||
content={"detail": f"[devmode] Use Vite devserver{at} instead."},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user