Skip to content

Commit b8a950b

Browse files
authored
fix(server): dynamic openapi server url (#1363)
Signed-off-by: Kai Wedekind <[email protected]>
1 parent 828e135 commit b8a950b

File tree

1 file changed

+39
-6
lines changed

1 file changed

+39
-6
lines changed

apps/agentstack-server/src/agentstack_server/application.py

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@
55
import time
66
from collections.abc import Iterable
77
from contextlib import asynccontextmanager, suppress
8+
from importlib.metadata import PackageNotFoundError, version
89

910
import procrastinate
10-
from fastapi import APIRouter, FastAPI, HTTPException
11+
from fastapi import APIRouter, FastAPI, HTTPException, Request
1112
from fastapi.exception_handlers import http_exception_handler
12-
from fastapi.responses import ORJSONResponse
13+
from fastapi.openapi.docs import get_swagger_ui_html
14+
from fastapi.openapi.utils import get_openapi
15+
from fastapi.responses import JSONResponse, ORJSONResponse
1316
from kink import Container, di, inject
1417
from opentelemetry.metrics import CallbackOptions, Observation, get_meter
1518
from procrastinate.exceptions import AlreadyEnqueued
16-
from starlette.requests import Request
1719
from starlette.status import HTTP_401_UNAUTHORIZED, HTTP_500_INTERNAL_SERVER_ERROR
1820

1921
from agentstack_server.api.routes.a2a import router as a2a_router
@@ -46,6 +48,15 @@
4648
logger = logging.getLogger(__name__)
4749

4850

51+
def get_version():
52+
try:
53+
__version__ = version("agentstack-server")
54+
except PackageNotFoundError:
55+
__version__ = "0.1.0"
56+
57+
return __version__
58+
59+
4960
def extract_messages(exc):
5061
if isinstance(exc, BaseExceptionGroup):
5162
return [(exc_type, msg) for e in exc.exceptions for exc_type, msg in extract_messages(e)]
@@ -111,6 +122,28 @@ def mount_routes(app: FastAPI):
111122
app.include_router(server_router, prefix="/api/v1", tags=["provider"])
112123
app.include_router(well_known_router, prefix="/.well-known", tags=["well-known"])
113124

125+
@app.get("/api/v1/openapi.json", include_in_schema=False)
126+
async def custom_openapi(request: Request):
127+
openapi_schema = get_openapi(
128+
title="Agentstack server",
129+
version=get_version(),
130+
routes=app.routes,
131+
)
132+
133+
base_url = str(request.base_url)
134+
openapi_schema["servers"] = [{"url": base_url}]
135+
136+
return JSONResponse(openapi_schema)
137+
138+
@app.get("/api/v1/docs", include_in_schema=False)
139+
async def custom_docs(request: Request):
140+
openapi_url = request.url_for(custom_openapi.__name__)
141+
142+
return get_swagger_ui_html(
143+
openapi_url=openapi_url,
144+
title="BeeAI Platform API Docs",
145+
)
146+
114147
@app.get("/healthcheck")
115148
async def healthcheck():
116149
return "OK"
@@ -169,9 +202,9 @@ async def lifespan(_app: FastAPI, procrastinate_app: procrastinate.App, mcp_serv
169202
app = FastAPI(
170203
lifespan=lifespan,
171204
default_response_class=ORJSONResponse, # better performance then default + handle NaN floats
172-
docs_url="/api/v1/docs",
173-
openapi_url="/api/v1/openapi.json",
174-
servers=[{"url": f"http://localhost:{configuration.port}"}],
205+
docs_url=None,
206+
openapi_url=None,
207+
servers=None,
175208
)
176209

177210
logger.info("Mounting routes...")

0 commit comments

Comments
 (0)