Skip to content

Commit 52ed045

Browse files
committed
refactor: allow configuring external FastAPI app
1 parent 8ed08bc commit 52ed045

File tree

3 files changed

+85
-54
lines changed

3 files changed

+85
-54
lines changed

src/stac_auth_proxy/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
with some internal STAC API.
77
"""
88

9-
from .app import create_app
9+
from .app import configure_app, create_app
1010
from .config import Settings
1111

12-
__all__ = ["create_app", "Settings"]
12+
__all__ = ["create_app", "configure_app", "Settings"]

src/stac_auth_proxy/app.py

Lines changed: 61 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -31,51 +31,10 @@
3131
logger = logging.getLogger(__name__)
3232

3333

34-
def create_app(settings: Optional[Settings] = None) -> FastAPI:
35-
"""FastAPI Application Factory."""
34+
def configure_app(app: FastAPI, settings: Optional[Settings] = None) -> FastAPI:
35+
"""Apply routes and middleware to an existing FastAPI app."""
3636
settings = settings or Settings()
3737

38-
#
39-
# Application
40-
#
41-
42-
@asynccontextmanager
43-
async def lifespan(app: FastAPI):
44-
assert settings
45-
46-
# Wait for upstream servers to become available
47-
if settings.wait_for_upstream:
48-
logger.info("Running upstream server health checks...")
49-
urls = [settings.upstream_url, settings.oidc_discovery_internal_url]
50-
for url in urls:
51-
await check_server_health(url=url)
52-
logger.info(
53-
"Upstream servers are healthy:\n%s",
54-
"\n".join([f" - {url}" for url in urls]),
55-
)
56-
57-
# Log all middleware connected to the app
58-
logger.info(
59-
"Connected middleware:\n%s",
60-
"\n".join([f" - {m.cls.__name__}" for m in app.user_middleware]),
61-
)
62-
63-
if settings.check_conformance:
64-
await check_conformance(
65-
app.user_middleware,
66-
str(settings.upstream_url),
67-
)
68-
69-
yield
70-
71-
app = FastAPI(
72-
openapi_url=None, # Disable OpenAPI schema endpoint, we want to serve upstream's schema
73-
lifespan=lifespan,
74-
root_path=settings.root_path,
75-
)
76-
if app.root_path:
77-
logger.debug("Mounted app at %s", app.root_path)
78-
7938
#
8039
# Handlers (place catch-all proxy handler last)
8140
#
@@ -105,15 +64,6 @@ async def lifespan(app: FastAPI):
10564
prefix=settings.healthz_prefix,
10665
)
10766

108-
app.add_api_route(
109-
"/{path:path}",
110-
ReverseProxyHandler(
111-
upstream=str(settings.upstream_url),
112-
override_host=settings.override_host,
113-
).proxy_request,
114-
methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
115-
)
116-
11767
#
11868
# Middleware (order is important, last added = first to run)
11969
#
@@ -186,3 +136,62 @@ async def lifespan(app: FastAPI):
186136
)
187137

188138
return app
139+
140+
141+
def create_app(settings: Optional[Settings] = None) -> FastAPI:
142+
"""FastAPI Application Factory."""
143+
settings = settings or Settings()
144+
145+
#
146+
# Application
147+
#
148+
149+
@asynccontextmanager
150+
async def lifespan(app: FastAPI):
151+
assert settings
152+
153+
# Wait for upstream servers to become available
154+
if settings.wait_for_upstream:
155+
logger.info("Running upstream server health checks...")
156+
urls = [settings.upstream_url, settings.oidc_discovery_internal_url]
157+
for url in urls:
158+
await check_server_health(url=url)
159+
logger.info(
160+
"Upstream servers are healthy:\n%s",
161+
"\n".join([f" - {url}" for url in urls]),
162+
)
163+
164+
# Log all middleware connected to the app
165+
logger.info(
166+
"Connected middleware:\n%s",
167+
"\n".join([f" - {m.cls.__name__}" for m in app.user_middleware]),
168+
)
169+
170+
if settings.check_conformance:
171+
await check_conformance(
172+
app.user_middleware,
173+
str(settings.upstream_url),
174+
)
175+
176+
yield
177+
178+
app = FastAPI(
179+
openapi_url=None, # Disable OpenAPI schema endpoint, we want to serve upstream's schema
180+
lifespan=lifespan,
181+
root_path=settings.root_path,
182+
)
183+
if app.root_path:
184+
logger.debug("Mounted app at %s", app.root_path)
185+
186+
configure_app(app, settings)
187+
188+
app.add_api_route(
189+
"/{path:path}",
190+
ReverseProxyHandler(
191+
upstream=str(settings.upstream_url),
192+
override_host=settings.override_host,
193+
).proxy_request,
194+
methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
195+
)
196+
197+
return app

tests/test_configure_app.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from fastapi import FastAPI
2+
from fastapi.routing import APIRoute
3+
4+
from stac_auth_proxy import Settings
5+
from stac_auth_proxy.app import configure_app
6+
7+
8+
def test_configure_app_excludes_proxy_route():
9+
app = FastAPI()
10+
settings = Settings(
11+
upstream_url="https://example.com",
12+
oidc_discovery_url="https://example.com/.well-known/openid-configuration",
13+
wait_for_upstream=False,
14+
check_conformance=False,
15+
default_public=True,
16+
)
17+
18+
configure_app(app, settings)
19+
20+
routes = [r.path for r in app.router.routes if isinstance(r, APIRoute)]
21+
assert settings.healthz_prefix in routes
22+
assert "/{path:path}" not in routes

0 commit comments

Comments
 (0)