From 0dc96907fac595035371d8ca0ed9fcbac67c3a4f Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Sat, 18 Jul 2026 20:07:32 +0530 Subject: [PATCH] resolve {ENV_VAR} placeholders in spec before serving - app.py: add _resolve_env and _resolve_spec_env_vars to replace {ENV_VAR} patterns (e.g. {AUTH_SERVER}) with os.environ values so the frontend receives resolved URLs via /openapi.json --- openapi_first/app.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/openapi_first/app.py b/openapi_first/app.py index 3bde288..efe9e7b 100644 --- a/openapi_first/app.py +++ b/openapi_first/app.py @@ -32,12 +32,35 @@ Notes: - Alter FastAPI dependency injection semantics. """ +import os +import re + from fastapi import FastAPI from .binder import bind_routes from .loader import load_openapi from .security import make_security_dependencies, parse_security_schemes +_env_pattern = re.compile(r"\{(\w+)\}") + + +def _resolve_env(value: str) -> str: + """Replace {ENV_VAR} placeholders with values from os.environ.""" + def _replace(m: re.Match) -> str: + return os.environ.get(m.group(1), m.group(0)) + return _env_pattern.sub(_replace, value) + + +def _resolve_spec_env_vars(obj): + """Recursively resolve {ENV_VAR} in all string values of the spec.""" + if isinstance(obj, str): + return _resolve_env(obj) + if isinstance(obj, dict): + return {k: _resolve_spec_env_vars(v) for k, v in obj.items()} + if isinstance(obj, list): + return [_resolve_spec_env_vars(v) for v in obj] + return obj + class OpenAPIFirstApp(FastAPI): """ @@ -107,7 +130,7 @@ class OpenAPIFirstApp(FastAPI): super().__init__(**fastapi_kwargs) # Load and validate OpenAPI specification - self._openapi_spec = load_openapi(openapi_path) + self._openapi_spec = _resolve_spec_env_vars(load_openapi(openapi_path)) # Parse security schemes and build per-route dependencies security_schemes = parse_security_schemes(self._openapi_spec)