mirror of https://github.com/tiangolo/fastapi.git
✨ Make Swagger UI and ReDoc parameterizable to host offline assets for docs (#112)
This commit is contained in:
parent
56ab106bbb
commit
f54d8d57a4
|
|
@ -1,80 +1,77 @@
|
||||||
from starlette.responses import HTMLResponse
|
from starlette.responses import HTMLResponse
|
||||||
|
|
||||||
|
|
||||||
def get_swagger_ui_html(*, openapi_url: str, title: str) -> HTMLResponse:
|
def get_swagger_ui_html(
|
||||||
return HTMLResponse(
|
*,
|
||||||
"""
|
openapi_url: str,
|
||||||
|
title: str,
|
||||||
|
swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui-bundle.js",
|
||||||
|
swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui.css",
|
||||||
|
swagger_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png",
|
||||||
|
) -> HTMLResponse:
|
||||||
|
html = f"""
|
||||||
<! doctype html>
|
<! doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui.css">
|
<link type="text/css" rel="stylesheet" href="{swagger_css_url}">
|
||||||
<link rel="shortcut icon" href="https://fastapi.tiangolo.com/img/favicon.png">
|
<link rel="shortcut icon" href="{swagger_favicon_url}">
|
||||||
<title>
|
<title>{title}</title>
|
||||||
"""
|
|
||||||
+ title
|
|
||||||
+ """
|
|
||||||
</title>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="swagger-ui">
|
<div id="swagger-ui">
|
||||||
</div>
|
</div>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui-bundle.js"></script>
|
<script src="{swagger_js_url}"></script>
|
||||||
<!-- `SwaggerUIBundle` is now available on the page -->
|
<!-- `SwaggerUIBundle` is now available on the page -->
|
||||||
<script>
|
<script>
|
||||||
|
const ui = SwaggerUIBundle({{
|
||||||
const ui = SwaggerUIBundle({
|
url: '{openapi_url}',
|
||||||
url: '"""
|
|
||||||
+ openapi_url
|
|
||||||
+ """',
|
|
||||||
dom_id: '#swagger-ui',
|
dom_id: '#swagger-ui',
|
||||||
presets: [
|
presets: [
|
||||||
SwaggerUIBundle.presets.apis,
|
SwaggerUIBundle.presets.apis,
|
||||||
SwaggerUIBundle.SwaggerUIStandalonePreset
|
SwaggerUIBundle.SwaggerUIStandalonePreset
|
||||||
],
|
],
|
||||||
layout: "BaseLayout",
|
layout: "BaseLayout"
|
||||||
deepLinking: true
|
|
||||||
|
|
||||||
})
|
}})
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
)
|
return HTMLResponse(html)
|
||||||
|
|
||||||
|
|
||||||
def get_redoc_html(*, openapi_url: str, title: str) -> HTMLResponse:
|
def get_redoc_html(
|
||||||
return HTMLResponse(
|
*,
|
||||||
"""
|
openapi_url: str,
|
||||||
|
title: str,
|
||||||
|
redoc_js_url: str = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js",
|
||||||
|
redoc_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png",
|
||||||
|
) -> HTMLResponse:
|
||||||
|
|
||||||
|
html = f"""
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>
|
<title>{title}</title>
|
||||||
"""
|
|
||||||
+ title
|
|
||||||
+ """
|
|
||||||
</title>
|
|
||||||
<!-- needed for adaptive design -->
|
<!-- needed for adaptive design -->
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
||||||
<link rel="shortcut icon" href="https://fastapi.tiangolo.com/img/favicon.png">
|
<link rel="shortcut icon" href="{redoc_favicon_url}">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
ReDoc doesn't change outer page styles
|
ReDoc doesn't change outer page styles
|
||||||
-->
|
-->
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {{
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<redoc spec-url='"""
|
<redoc spec-url="{openapi_url}"></redoc>
|
||||||
+ openapi_url
|
<script src="{redoc_js_url}"> </script>
|
||||||
+ """'></redoc>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
)
|
return HTMLResponse(html)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html
|
||||||
|
|
||||||
|
|
||||||
|
def test_strings_in_generated_swagger():
|
||||||
|
sig = inspect.signature(get_swagger_ui_html)
|
||||||
|
swagger_js_url = sig.parameters.get("swagger_js_url").default
|
||||||
|
swagger_css_url = sig.parameters.get("swagger_css_url").default
|
||||||
|
swagger_favicon_url = sig.parameters.get("swagger_favicon_url").default
|
||||||
|
html = get_swagger_ui_html(openapi_url="/docs", title="title")
|
||||||
|
body_content = html.body.decode()
|
||||||
|
assert swagger_js_url in body_content
|
||||||
|
assert swagger_css_url in body_content
|
||||||
|
assert swagger_favicon_url in body_content
|
||||||
|
|
||||||
|
|
||||||
|
def test_strings_in_custom_swagger():
|
||||||
|
swagger_js_url = "swagger_fake_file.js"
|
||||||
|
swagger_css_url = "swagger_fake_file.css"
|
||||||
|
swagger_favicon_url = "swagger_fake_file.png"
|
||||||
|
html = get_swagger_ui_html(
|
||||||
|
openapi_url="/docs",
|
||||||
|
title="title",
|
||||||
|
swagger_js_url=swagger_js_url,
|
||||||
|
swagger_css_url=swagger_css_url,
|
||||||
|
swagger_favicon_url=swagger_favicon_url,
|
||||||
|
)
|
||||||
|
body_content = html.body.decode()
|
||||||
|
assert swagger_js_url in body_content
|
||||||
|
assert swagger_css_url in body_content
|
||||||
|
assert swagger_favicon_url in body_content
|
||||||
|
|
||||||
|
|
||||||
|
def test_strings_in_generated_redoc():
|
||||||
|
sig = inspect.signature(get_redoc_html)
|
||||||
|
redoc_js_url = sig.parameters.get("redoc_js_url").default
|
||||||
|
redoc_favicon_url = sig.parameters.get("redoc_favicon_url").default
|
||||||
|
html = get_redoc_html(openapi_url="/docs", title="title")
|
||||||
|
body_content = html.body.decode()
|
||||||
|
assert redoc_js_url in body_content
|
||||||
|
assert redoc_favicon_url in body_content
|
||||||
|
|
||||||
|
|
||||||
|
def test_strings_in_custom_redoc():
|
||||||
|
redoc_js_url = "fake_redoc_file.js"
|
||||||
|
redoc_favicon_url = "fake_redoc_file.png"
|
||||||
|
html = get_redoc_html(
|
||||||
|
openapi_url="/docs",
|
||||||
|
title="title",
|
||||||
|
redoc_js_url=redoc_js_url,
|
||||||
|
redoc_favicon_url=redoc_favicon_url,
|
||||||
|
)
|
||||||
|
body_content = html.body.decode()
|
||||||
|
assert redoc_js_url in body_content
|
||||||
|
assert redoc_favicon_url in body_content
|
||||||
Loading…
Reference in New Issue