OpenAPI Metadata for API Endpoints (#1941)
- Updates the `/docs` and `/redoc` API endpoints to have better metadata, including using Browsertrix favicon and our logo for the `/redoc` endpoint. - add new logo file 'docs-logo.svg' to root Based on info at: https://fastapi.tiangolo.com/how-to/extending-openapi/ https://fastapi.tiangolo.com/tutorial/metadata/ --------- Co-authored-by: Henry Wilkinson <henry@wilkinson.graphics>
This commit is contained in:
parent
3bf7967754
commit
b1ccdc4d16
@ -11,6 +11,9 @@ from fastapi import FastAPI, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.routing import APIRouter
|
||||
|
||||
from fastapi.openapi.utils import get_openapi
|
||||
from fastapi.openapi.docs import get_swagger_ui_html, get_redoc_html
|
||||
|
||||
from .db import init_db, await_db_and_migrations, update_and_prepare_db
|
||||
|
||||
from .emailsender import EmailSender
|
||||
@ -34,18 +37,45 @@ from .subs import init_subs_api
|
||||
|
||||
from .crawlmanager import CrawlManager
|
||||
from .utils import run_once_lock, register_exit_handler, is_bool
|
||||
|
||||
from .version import __version__
|
||||
|
||||
API_PREFIX = "/api"
|
||||
app_root = FastAPI(
|
||||
docs_url=API_PREFIX + "/docs",
|
||||
redoc_url=API_PREFIX + "/redoc",
|
||||
openapi_url=API_PREFIX + "/openapi.json",
|
||||
)
|
||||
|
||||
OPENAPI_URL = API_PREFIX + "/openapi.json"
|
||||
|
||||
app_root = FastAPI(docs_url=None, redoc_url=None, OPENAPI_URL=OPENAPI_URL)
|
||||
|
||||
db_inited = {"inited": False}
|
||||
|
||||
|
||||
# ============================================================================
|
||||
def make_schema():
|
||||
"""make custom openapi schema"""
|
||||
schema = get_openapi(
|
||||
title="Browsertrix",
|
||||
description="""\
|
||||
The Browsertrix API provides access to all aspects of the Browsertrix app.
|
||||
|
||||
See [https://docs.browsertrix.com/](https://docs.browsertrix.com/) for more info on deploying Browsertrix\
|
||||
""",
|
||||
summary="Browsertrix Crawling System API",
|
||||
version=__version__,
|
||||
terms_of_service="http://browsertrix.com/terms",
|
||||
contact={
|
||||
"name": "Browsertrix",
|
||||
"url": "https://browsertrix.com/",
|
||||
"email": "info@webrecorder.net",
|
||||
},
|
||||
license_info={
|
||||
"name": "AGPL v3",
|
||||
"url": "https://www.gnu.org/licenses/agpl-3.0.en.html",
|
||||
},
|
||||
routes=app_root.routes,
|
||||
)
|
||||
schema["info"]["x-logo"] = {"url": "/docs-logo.svg"}
|
||||
return schema
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# pylint: disable=too-many-locals, duplicate-code
|
||||
def main():
|
||||
@ -200,7 +230,6 @@ def main():
|
||||
return settings
|
||||
|
||||
# internal routes
|
||||
|
||||
@app.get("/openapi.json", include_in_schema=False)
|
||||
async def openapi() -> JSONResponse:
|
||||
return JSONResponse(app_root.openapi())
|
||||
@ -221,6 +250,31 @@ def main():
|
||||
|
||||
app_root.include_router(app, prefix=API_PREFIX)
|
||||
|
||||
# API Configurations -- needed to provide custom favicon
|
||||
@app_root.get(API_PREFIX + "/docs", include_in_schema=False)
|
||||
def overridden_swagger():
|
||||
return get_swagger_ui_html(
|
||||
openapi_url=OPENAPI_URL,
|
||||
title="Browsertrix API",
|
||||
swagger_favicon_url="/favicon.ico",
|
||||
)
|
||||
|
||||
@app_root.get(API_PREFIX + "/redoc", include_in_schema=False)
|
||||
def overridden_redoc():
|
||||
return get_redoc_html(
|
||||
openapi_url=OPENAPI_URL,
|
||||
title="Browsertrix API",
|
||||
redoc_favicon_url="/favicon.ico",
|
||||
)
|
||||
|
||||
def get_api_schema():
|
||||
if not app_root.openapi_schema:
|
||||
app_root.openapi_schema = make_schema()
|
||||
|
||||
return app_root.openapi_schema
|
||||
|
||||
app_root.openapi = get_api_schema # type: ignore
|
||||
|
||||
|
||||
# ============================================================================
|
||||
@app_root.on_event("startup")
|
||||
|
||||
32
backend/test/test_api.py
Normal file
32
backend/test/test_api.py
Normal file
@ -0,0 +1,32 @@
|
||||
import requests
|
||||
|
||||
from .conftest import API_PREFIX
|
||||
|
||||
|
||||
def test_api_docs():
|
||||
r = requests.get(f"{API_PREFIX}/docs")
|
||||
assert r.status_code == 200
|
||||
|
||||
text = r.text
|
||||
assert "<title>Browsertrix API</title>" in text
|
||||
assert "/favicon.ico" in text
|
||||
assert "/api/openapi.json" in text
|
||||
|
||||
|
||||
def test_api_redoc():
|
||||
r = requests.get(f"{API_PREFIX}/redoc")
|
||||
assert r.status_code == 200
|
||||
|
||||
text = r.text
|
||||
assert "<title>Browsertrix API</title>" in text
|
||||
assert "/favicon.ico" in text
|
||||
assert "/api/openapi.json" in text
|
||||
|
||||
|
||||
def test_api_openapi():
|
||||
r = requests.get(f"{API_PREFIX}/openapi.json")
|
||||
assert r.status_code == 200
|
||||
|
||||
json = r.json()
|
||||
assert json["info"]["title"] == "Browsertrix"
|
||||
assert json["info"]["x-logo"]["url"] == "/docs-logo.svg"
|
||||
1
frontend/src/assets/favicons/docs-logo.svg
Normal file
1
frontend/src/assets/favicons/docs-logo.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 12 KiB |
Loading…
Reference in New Issue
Block a user