This is my first blog post, so I'll be succinct. This is more of a step-by-step tutorial, but if you're only interested in the code, feel free to check it.
Let's start defining our goal: we want to change our Swagger UI favicon using a local image.
Step 1: Create our FastAPI application
Let's create a simple FastAPI application with a single endpoint.
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def home():
...
Let's run our uvicorn
server: python -m uvicorn main:app --reload
, and use a HTTP client to see what we get from it. I'll be using httpie
, but feel free to use curl
or any other HTTP client of your choice.
Note that we've used
--reload
flag on the uvicorn command. To know more about the CLI options, checkuvicorn
documentation.
❯ http :8000
HTTP/1.1 200 OK
content-length: 4
content-type: application/json
date: Tue, 18 Jan 2022 22:05:38 GMT
server: uvicorn
null
Now that we're sure that our application works, let's go to the next step.
Step 2: Replace the default docs page
Following the ycd snippet on his comment, we'd need to replace the default swagger endpoint. The problem with this approach is that we lose internal logic, as the original endpoint does more than what is in there.
In any case, let's start adding the snippet mentioned above.
from fastapi import FastAPI
from fastapi.openapi.docs import get_swagger_ui_html
app = FastAPI(docs_url=None)
@app.get("/docs", include_in_schema=False)
async def swagger_ui_html():
return get_swagger_ui_html(
openapi_url="/openapi.json",
title="FastAPI",
swagger_favicon_url="https://placekitten.com/200/300"
)
@app.get("/")
async def home():
...
We still have uvicorn
running, and as the reload flag is set, we can see the changes. Go to your browser, and access http://127.0.0.1:8000/docs#/.
As you can see, the favicon has changed.
Step 3: Serve the local favicon
FastAPI is able to serve files from a given directory thanks to Starlette's StaticFiles
class, and that's exactly what we're going to do.
Let's create a directory with our favicon, and serve that image.
from fastapi import FastAPI
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.staticfiles import StaticFiles
app = FastAPI(docs_url=None)
app.mount("/static", StaticFiles(directory="static"), name="static")
@app.get("/docs", include_in_schema=False)
async def swagger_ui_html():
return get_swagger_ui_html(
openapi_url="/openapi.json",
title="FastAPI",
swagger_favicon_url="/static/favicon.png"
)
@app.get("/")
async def home():
...
At this point, we need to create a folder called "static", or any other name, just remember to change the name on the directory
argument on the StaticFiles
instantiation. On this folder, we'll add our image (on our case it's going to be a favicon.png
).
Pay attention on the snippet above that we've changed the value of swagger_favicon_url
on the get_swagger_ui_html
function. If you access the docs page now, you'll see the favicon.
Our goal has been accomplished, but that's not quite the end of it.
Step 4: Improve with details
As I've said at the beginning, the internal FastAPI docs endpoint has more logic than what we've used. So let's add those to our solution.
from fastapi import FastAPI, Request
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
app = FastAPI(docs_url=None, redoc_url=None)
app.mount("/static", StaticFiles(directory="static"), name="static")
@app.get("/docs", include_in_schema=False)
async def swagger_ui_html(req: Request) -> HTMLResponse:
root_path = req.scope.get("root_path", "").rstrip("/")
openapi_url = root_path + app.openapi_url
oauth2_redirect_url = app.swagger_ui_oauth2_redirect_url
if oauth2_redirect_url:
oauth2_redirect_url = root_path + oauth2_redirect_url
return get_swagger_ui_html(
openapi_url=openapi_url,
title=app.title + " - Swagger UI",
oauth2_redirect_url=oauth2_redirect_url,
init_oauth=app.swagger_ui_init_oauth,
swagger_favicon_url="/static/favicon.png",
swagger_ui_parameters=app.swagger_ui_parameters,
)
@app.get("/")
def home():
return RedirectResponse("/docs")
There are two things to notice on the above improvements: the body of the swagger_ui_html
endpoint function has changed, and the /
endpoint has been changed to redirect to the /docs
endpoint. On the first, we're concerned about the OAuth2 integration with the Swagger UI, and on the second is just to show you something different. :)
That's it.
Thanks for reading until here, and please, give me some feedback and ideas. I'm planning to write daily posts.
Top comments (0)