Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lite_bootstrap/bootstrappers/fastapi_bootstrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ class FastAPISwaggerInstrument(SwaggerInstrument[FastAPIConfig]):
def bootstrap(self) -> None:
config = self.bootstrap_config
application = config.app
if config.swagger_path != application.docs_url:
if application.docs_url is not None and config.swagger_path != application.docs_url:
warn_at_caller(f"swagger_path differs from docs_url, {application.docs_url} will be used for docs path")
if config.swagger_offline_docs:
enable_offline_docs(application, static_path=config.swagger_static_path)
Expand Down
53 changes: 27 additions & 26 deletions lite_bootstrap/helpers/fastapi_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

if import_checker.is_fastapi_installed:
from fastapi import FastAPI, Request
from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html, get_swagger_ui_oauth2_redirect_html
from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from starlette.routing import Route
Expand Down Expand Up @@ -42,11 +42,12 @@ def enable_offline_docs(
msg = "No app.openapi_url specified"
raise ConfigurationError(msg)

docs_url: str = app.docs_url or "/docs"
redoc_url: str = app.redoc_url or "/redoc"
swagger_ui_oauth2_redirect_url: str = app.swagger_ui_oauth2_redirect_url or "/docs/oauth2-redirect"
docs_url = app.docs_url
redoc_url = app.redoc_url
if not docs_url and not redoc_url:
return

replaced_urls = (docs_url, redoc_url, swagger_ui_oauth2_redirect_url)
replaced_urls = (docs_url, redoc_url)
app.router.routes = [
route
for route in app.router.routes
Expand All @@ -58,26 +59,26 @@ def enable_offline_docs(
static_dir_path = pathlib.Path(__file__).parent.parent / "static/fastapi_docs"
app.mount(static_path, StaticFiles(directory=static_dir_path), name="static")

@app.get(docs_url, include_in_schema=False)
async def custom_swagger_ui_html(request: Request) -> HTMLResponse:
root_path = _safe_root_path(request.scope.get("root_path", ""))
return get_swagger_ui_html(
openapi_url=f"{root_path}{app_openapi_url}",
title=f"{app.title} - Swagger UI",
oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
swagger_js_url=f"{root_path}{static_path}/swagger-ui-bundle.js",
swagger_css_url=f"{root_path}{static_path}/swagger-ui.css",
)
if docs_url:

@app.get(swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect() -> HTMLResponse:
return get_swagger_ui_oauth2_redirect_html()
@app.get(docs_url, include_in_schema=False)
async def custom_swagger_ui_html(request: Request) -> HTMLResponse:
root_path = _safe_root_path(request.scope.get("root_path", ""))
return get_swagger_ui_html(
openapi_url=f"{root_path}{app_openapi_url}",
title=f"{app.title} - Swagger UI",
oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
swagger_js_url=f"{root_path}{static_path}/swagger-ui-bundle.js",
swagger_css_url=f"{root_path}{static_path}/swagger-ui.css",
)

@app.get(redoc_url, include_in_schema=False)
async def redoc_html(request: Request) -> HTMLResponse:
root_path = _safe_root_path(request.scope.get("root_path", ""))
return get_redoc_html(
openapi_url=f"{root_path}{app_openapi_url}",
title=f"{app.title} - ReDoc",
redoc_js_url=f"{root_path}{static_path}/redoc.standalone.js",
)
if redoc_url:

@app.get(redoc_url, include_in_schema=False)
async def redoc_html(request: Request) -> HTMLResponse:
root_path = _safe_root_path(request.scope.get("root_path", ""))
return get_redoc_html(
openapi_url=f"{root_path}{app_openapi_url}",
title=f"{app.title} - ReDoc",
redoc_js_url=f"{root_path}{static_path}/redoc.standalone.js",
)
27 changes: 27 additions & 0 deletions tests/test_fastapi_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,33 @@ def test_fastapi_bootstrapper_docs_url_differ(fastapi_config: FastAPIConfig) ->
bootstrapper.teardown()


def test_offline_docs_respect_both_disabled_routes() -> None:
app = fastapi.FastAPI(docs_url=None, redoc_url=None)
config = FastAPIConfig(application=app, swagger_offline_docs=True)
bootstrapper = FastAPIBootstrapper(bootstrap_config=config)

with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
application = bootstrapper.bootstrap()

with TestClient(application) as client:
assert client.get("/docs").status_code == status.HTTP_404_NOT_FOUND
assert client.get("/redoc").status_code == status.HTTP_404_NOT_FOUND

assert not caught


def test_offline_swagger_ui_works_with_redoc_disabled() -> None:
app = fastapi.FastAPI(redoc_url=None)
config = FastAPIConfig(application=app, swagger_offline_docs=True)

with TestClient(FastAPIBootstrapper(bootstrap_config=config).bootstrap()) as client:
response = client.get("/docs")
assert response.status_code == status.HTTP_200_OK
assert f"{config.swagger_static_path}/swagger-ui-bundle.js" in response.text
assert client.get("/redoc").status_code == status.HTTP_404_NOT_FOUND


def test_fastapi_bootstrapper_apps_and_kwargs_warning(fastapi_config: FastAPIConfig) -> None:
with pytest.warns(UserWarning, match="application_kwargs must be used without application") as caught:
dataclasses.replace(fastapi_config, application=fastapi.FastAPI(), application_kwargs={"title": "some title"})
Expand Down
Loading