|
1 | 1 | """openapi.""" |
2 | 2 | from fastapi import FastAPI |
3 | 3 | from fastapi.openapi.utils import get_openapi |
| 4 | +from starlette.requests import Request |
| 5 | +from starlette.responses import JSONResponse |
4 | 6 |
|
5 | 7 | from stac_fastapi.api.config import ApiExtensions |
6 | 8 | from stac_fastapi.types.config import ApiSettings |
7 | 9 |
|
8 | 10 |
|
| 11 | +class VndOaiResponse(JSONResponse): |
| 12 | + """JSON with custom, vendor content-type.""" |
| 13 | + |
| 14 | + media_type = "application/vnd.oai.openapi+json;version=3.0" |
| 15 | + |
| 16 | + |
| 17 | +def update_openapi(app: FastAPI) -> FastAPI: |
| 18 | + """Update OpenAPI response content-type. |
| 19 | +
|
| 20 | + This function modifies the openapi route to comply with the STAC API spec's |
| 21 | + required content-type response header |
| 22 | + """ |
| 23 | + urls = (server_data.get("url") for server_data in app.servers) |
| 24 | + server_urls = {url for url in urls if url} |
| 25 | + |
| 26 | + async def openapi(req: Request) -> JSONResponse: |
| 27 | + root_path = req.scope.get("root_path", "").rstrip("/") |
| 28 | + if root_path not in server_urls: |
| 29 | + if root_path and app.root_path_in_servers: |
| 30 | + app.servers.insert(0, {"url": root_path}) |
| 31 | + server_urls.add(root_path) |
| 32 | + return VndOaiResponse(app.openapi()) |
| 33 | + |
| 34 | + # Remove the default openapi route |
| 35 | + app.router.routes = list( |
| 36 | + filter(lambda r: r.path != app.openapi_url, app.router.routes) |
| 37 | + ) |
| 38 | + # Add the updated openapi route |
| 39 | + app.add_route(app.openapi_url, openapi, include_in_schema=False) |
| 40 | + return app |
| 41 | + |
| 42 | + |
9 | 43 | # TODO: Remove or fix, this is currently unused |
10 | 44 | # and calls a missing method on ApiSettings |
11 | 45 | def config_openapi(app: FastAPI, settings: ApiSettings): |
|
0 commit comments