DEV Community

Cover image for Easily add Swagger UI to a plain Flask API project with an OpenAPI specification file
Sanjan Grero
Sanjan Grero

Posted on

Easily add Swagger UI to a plain Flask API project with an OpenAPI specification file

This is a simple guide on how to add Swagger UI to your plain flask API project without using any additional libraries.
As I wanted a way to get Swagger UI implemented in my POC work in order to quickly show the intended functions to stakeholders. And there was no simple way to do it. All the youtube videos or online articles pointed to using libraries like flask-swagger-ui or FastAPI etc. I didn’t want to use any of those and even the official Swagger UI recommends running it as a docker container, which is overkill for something so simple. So this is the way I managed to do it.

Step 1: Download Swagger UI GitHub repo

Download Swagger UI from GitHub and extract it. We are basically interested in the dist directory in this archive.

Step 2: Copy the files from dist to your project directory

  • In your project directory create 2 directories templates and static
  • Move index.html from dist to templates directory and rename it to swaggerui.html
  • Inside static directory, create 3 more directories, css,img and js
  • Move .js files from dist to static/js
  • Move .css files from dist to static/css
  • Move .png files from dist to static/img

Your project directory should now look like this

.
├── static
│   ├── css
│   │   └── swagger-ui.css
│   ├── img
│   │   ├── favicon-16x16.png
│   │   └── favicon-32x32.png
│   └── js
│       ├── swagger-ui-bundle.js
│       ├── swagger-ui-standalone-preset.js
│       └── swagger-ui.js
└── templates
    ├── swaggerui.html

Step 3: Edit swaggerui.html and replace all static url with Jinja2 template tags

7    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/swagger-ui.css') }}">
8    <link rel="icon" type="image/png" href="{{ url_for('static', filename='img/favicon-32x32.png') }}" sizes="32x32"/>
9    <link rel="icon" type="image/png" href="{{ url_for('static', filename='img/favicon-16x16.png') }}" sizes="16x16"/>
36   <script src="{{ url_for('static', filename='js/swagger-ui-bundle.js') }}"> </script>
37   <script src="{{ url_for('static', filename='js/swagger-ui-standalone-preset.js') }}"> </script>

Step 4: Write your API spec in OpenAPI format

  • Go to swagger editor and write your API spec in YAML. Here is a Sample API spec:
  • Go to File menu in Swagger editor and click on Convert and save as JSON
  • Place the downloaded openapi.json file in your projects' static directory
  • Update the reference for the source json file (line 42) in swaggerui.html file to refer to the spec file in static directory
url: "{{ url_for('static', filename='openapi.json') }}",

Step 5: Return swaggerui.html with flask render_template in your preferred route

  • Create hello_api.py in your project directory with the following code
  • Run the app with command: python3 hello_api.py from your project directory
  • Your SwaggerUI documentation should be accessible on http://localhost:5000/api/docs

I have created a boilerplate flask app for anyone to use this setup with ease.

GitHub logo sanjan / flask_swagger

Boilerplate to build a flask API with swagger ui documentation

Latest comments (7)

Collapse
 
shivendra2407 profile image
Shivendra Srivastava

Hi Sanjan,
I am using connexion to create FlaskAPP and then adding my yaml to it using something like
app = connexion.App(...)
app.add_api('openapi.yaml', arguments={'title': 'testapp'})

This properly serves my endpoints on a beautiful swagger page with all the documentation. But I need to do some customization on the swagger page, like change the color coding on the endpoints and change the page logo.

It is not picking my static files, although I found a solution on the readthedocs website for using SwaggerUIOptions class, it doesnt work for me.
Do u happen to know a way to serve the static files with connexion app?

Collapse
 
jamesprenticez profile image
James Prentice

God sent thanks

Collapse
 
karantir profile image
Dmitry Krupnov

For those who reads this in 2022.

1) The URL to openapi.json is now defined in swagger-initializer.js, so, to get the URL, you, for example, have to render it first as a custom node attribute in your swaggerui.html:

...
 <body>
    <div id="swagger-ui" openapi-url="{{ url_for('static', filename='openapi.yaml') }}">
...
Enter fullscreen mode Exit fullscreen mode

And then obtain the URL in swagger-initializer.js, like that:

window.onload = function() {
  window.ui = SwaggerUIBundle({
    url: document.getElementById("swagger-ui").getAttribute('openapi-url'),
    dom_id: '#swagger-ui',
    ...
  });
};
Enter fullscreen mode Exit fullscreen mode

2) You may use openapi.yaml directly, no need to convert to JSON.

And, btw, this way of using swagger in you Flask app is the most generic, clean and easy. Packages like flasgger, flask-apispec etc., are great, but buggy and brings unnecessary semantics to your code. Thank you Sanjan to share it.

Collapse
 
prudhvi239 profile image
Prudhvi239

Hi Sanjan, I'm trying to change the names of static, templates folder to my desired name. But, it's not accepting.

I have changed the name of directories used in the swaggerui.html also. Still the same issue.

Is there any way we can use our desired name for these two folders ?

Collapse
 
sanjan profile image
Sanjan Grero

these are the default folders looked at by flask's render template. but you can customize them if you want. have a look at: stackoverflow.com/questions/310028...

Collapse
 
sathyasarathi90 profile image
Sathyasarathi

You sir, deserve a trophy!

Collapse
 
menilek profile image
Menilek Techane

This was really easy to follow! Big thanks