Skip to content

Commit 59ed440

Browse files
committed
feat: add Swagger UI support
- Introduced a new SwaggerUI handler to serve the Swagger UI interface. - Updated app configuration to include Swagger UI parameters and routes. - Enhanced Settings class with new fields for Swagger UI configuration. - Ensured compatibility with OpenAPI spec endpoint when using Swagger UI.
1 parent d0b9099 commit 59ed440

File tree

4 files changed

+64
-3
lines changed

4 files changed

+64
-3
lines changed

src/stac_auth_proxy/app.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from starlette_cramjam.middleware import CompressionMiddleware
1414

1515
from .config import Settings
16-
from .handlers import HealthzHandler, ReverseProxyHandler
16+
from .handlers import HealthzHandler, ReverseProxyHandler, SwaggerUI
1717
from .middleware import (
1818
AddProcessTimeHeaderMiddleware,
1919
ApplyCql2FilterMiddleware,
@@ -68,6 +68,10 @@ async def lifespan(app: FastAPI):
6868

6969
app = FastAPI(
7070
openapi_url=None, # Disable OpenAPI schema endpoint, we want to serve upstream's schema
71+
swagger_ui_parameters={
72+
"usePkceWithAuthorizationCodeGrant": True,
73+
"clientId": "stac-auth-proxy",
74+
},
7175
lifespan=lifespan,
7276
root_path=settings.root_path,
7377
)
@@ -78,6 +82,20 @@ async def lifespan(app: FastAPI):
7882
# Handlers (place catch-all proxy handler last)
7983
#
8084

85+
if settings.swagger_ui_url:
86+
assert (
87+
settings.openapi_spec_endpoint
88+
), "openapi_spec_endpoint must be set when using swagger_ui_url"
89+
app.add_route(
90+
settings.swagger_ui_url,
91+
SwaggerUI(
92+
openapi_url=settings.openapi_spec_endpoint,
93+
title=settings.swagger_ui_title,
94+
init_oauth=settings.swagger_ui_init_oauth,
95+
parameters=settings.swagger_ui_parameters,
96+
).route,
97+
include_in_schema=False,
98+
)
8199
if settings.healthz_prefix:
82100
app.include_router(
83101
HealthzHandler(upstream_url=str(settings.upstream_url)).router,

src/stac_auth_proxy/config.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,16 @@ class Settings(BaseSettings):
4545
check_conformance: bool = True
4646
enable_compression: bool = True
4747

48-
openapi_spec_endpoint: Optional[str] = Field(pattern=_PREFIX_PATTERN, default=None)
48+
# OpenAPI / Swagger UI
49+
openapi_spec_endpoint: Optional[str] = Field(
50+
pattern=_PREFIX_PATTERN, default="/api"
51+
)
4952
openapi_auth_scheme_name: str = "oidcAuth"
5053
openapi_auth_scheme_override: Optional[dict] = None
54+
swagger_ui_url: str = "/api.html"
55+
swagger_ui_title: str = "STAC API"
56+
swagger_ui_init_oauth: dict = Field(default_factory=dict)
57+
swagger_ui_parameters: dict = Field(default_factory=dict)
5158

5259
# Auth
5360
enable_authentication_extension: bool = True

src/stac_auth_proxy/handlers/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22

33
from .healthz import HealthzHandler
44
from .reverse_proxy import ReverseProxyHandler
5+
from .swagger_ui import SwaggerUI
56

6-
__all__ = ["ReverseProxyHandler", "HealthzHandler"]
7+
__all__ = ["ReverseProxyHandler", "HealthzHandler", "SwaggerUI"]
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""Swagger UI handler."""
2+
3+
from dataclasses import dataclass, field
4+
5+
from fastapi.openapi.docs import get_swagger_ui_html
6+
from starlette.requests import Request
7+
from starlette.responses import HTMLResponse
8+
9+
10+
@dataclass
11+
class SwaggerUI:
12+
"""Swagger UI handler."""
13+
14+
openapi_url: str
15+
title: str = "STAC API"
16+
# https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/
17+
init_oauth: dict = field(default_factory=dict)
18+
# https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/
19+
parameters: dict = field(default_factory=dict)
20+
oauth2_redirect_url: str = "/docs/oauth2-redirect"
21+
22+
async def route(self, req: Request) -> HTMLResponse:
23+
"""Route handler."""
24+
root_path = req.scope.get("root_path", "").rstrip("/")
25+
openapi_url = root_path + self.openapi_url
26+
oauth2_redirect_url = self.oauth2_redirect_url
27+
if oauth2_redirect_url:
28+
oauth2_redirect_url = root_path + oauth2_redirect_url
29+
return get_swagger_ui_html(
30+
openapi_url=openapi_url,
31+
title=f"{self.title} - Swagger UI",
32+
oauth2_redirect_url=oauth2_redirect_url,
33+
init_oauth=self.init_oauth,
34+
swagger_ui_parameters=self.parameters,
35+
)

0 commit comments

Comments
 (0)