Published in 10:36 of 02/23/2016 by Bruno Rocha
Bruno Rocha There is more to life than increasing its speed!

Published in 10:36 of 02/23/2016

←Home

Flasgger - API playground with Flask and Swagger UI

What is Swagger?

Swagger is a simple yet powerful representation of your RESTful API. With the largest ecosystem of API tooling on the planet, thousands of developers are supporting Swagger in almost every modern programming language and deployment environment. With a Swagger-enabled API, you get interactive documentation, client SDK generation and discoverability.

What is Swagger UI?

Swagger UI is a dependency-free collection of HTML, Javascript, and CSS assets that dynamically generate beautiful documentation and sandbox from a Swagger-compliant API. Because Swagger UI has no dependencies, you can host it in any server environment, or on your local machine. Head over to the online demo to see what it looks like for any publically accessible Swagger definition.

What is Flask? (duhhhh!!)

Flask is a microframework for Python based on Werkzeug, Jinja 2 and good intentions. Why it is awesome? because it is simple yet powerful, talking is cheaper look at the code!

from flask import Flask, jsonify, request
app = Flask(__name__)

@app.route('my_awesome_api', methods=['POST'])
def my_awesome_endpoint():
    data = request.json
    return jsonify(data=data, meta={"status": "ok"})

app.run()

Run the above script and then you can start posting to the API

curl -XPOST http://localhost:5000/my_awesome_api -d '{"python": "is awesome"}'
{
    "data": {"python": "is awesome"},
    "meta": {"status": "ok"}
}

What is Flasgger?

Flasgger is a Flask extension to help the creation of Flask APIs with documentation and live playground powered by SwaggerUI. You can define your API structure using YAML files and Flasgger creates all the specifications for you and you can use the same schema to validate the data.

GITHUB REPO: https://github.com/rochacbruno/flasgger

Install it

pip install flasgger

Create your app

You can put API specs directly in docstrings

import random
from flask import Flask, jsonify, request
from flasgger import Swagger

app = Flask(__name__)
Swagger(app)

@app.route('/api/<string:language>/', methods=['GET'])
def index(language):
    """
    This is the language awesomeness API
    Call this api passing a language name and get back its features
    ---
    tags:
      - Awesomeness Language API
    parameters:
      - name: language
        in: path
        type: string
        required: true
        description: The language name
      - name: size
        in: query
        type: integer
        description: size of awesomeness
    responses:
      500:
        description: Error The language is not awesome!
      200:
        description: A language with its awesomeness
        schema:
          id: awesome
          properties:
            language:
              type: string
              description: The language name
              default: Lua
            features:
              type: array
              description: The awesomeness list
              items:
                type: string
              default: ["perfect", "simple", "lovely"]

    """

    language = language.lower().strip()
    features = [
        "awesome", "great", "dynamic", 
        "simple", "powerful", "amazing", 
        "perfect", "beauty", "lovely"
    ]
    size = int(request.args.get('size', 1))
    if language in ['php', 'vb', 'visualbasic', 'actionscript']:
        return "An error occurred, invalid language for awesomeness", 500
    return jsonify(
        language=language,
        features=random.sample(features, size)
    )


app.run(debug=True)

Try it!

Now run your app and access http://localhost:5000/apidocs/index.html and you will play with Swagger UI!

Screenshot Flasgger

NOTE: All the default urls can be changed in configuration.

It is also possible to use a separate file for specs

Create your api specification in a separated YML file

In a file index.yml put the specs definitions

    This is the language awesomeness API
    Call this api passing a language name and get back its features
    ---
    tags:
      - Awesomeness Language API
    parameters:
      - name: language
        in: path
        type: string
        required: true
        description: The language name
      - name: size
        in: query
        type: integer
        description: size of awesomeness
    responses:
      500:
        description: Error The language is not awesome!
      200:
        description: A language with its awesomeness
        schema:
          id: awesome
          properties:
            language:
              type: string
              description: The language name
              default: Lua
            features:
              type: array
              description: The awesomeness list
              items:
                type: string
              default: ["perfect", "simple", "lovely"]

and then change the code to read from it using swag_from decorator

import random
from flask import Flask, jsonify, request
from flasgger import Swagger
from flasgger.utils import swag_from

app = Flask(__name__)
Swagger(app)

@app.route('/api/<string:language>/', methods=['GET'])
@swag_from('index.yml')
def index(language):
    language = language.lower().strip()
    features = [
        "awesome", "great", "dynamic", 
        "simple", "powerful", "amazing", 
        "perfect", "beauty", "lovely"
    ]
    size = int(request.args.get('size', 1))
    if language in ['php', 'vb', 'visualbasic', 'actionscript']:
        return "An error occurred, invalid language for awesomeness", 500
    return jsonify(
        language=language,
        features=random.sample(features, size)
    )


app.run(debug=True)

validation

If you put the specs in a separate file it is also possible to use the same specs to validate the input

from flasgger.utils import swag_from, validate, ValidationError

@app.route('/api/<string:language>/', methods=['GET'])
@swag_from('index.yml')
def index(language):
    ...
    try:
        validate(data, 'awesome', 'index.yml', root=__file__)
    except ValidationError as e:
        return "Validation Error: %s" % e, 400
    ...

More information

You can find more information and some examples in the github repository

Contribute

Please share your thoughts about ir, open issues, give ideas and PullRequests are always welcome!

Let's Swag!

  • Microservices with Python, RabbitMQ and Nameko in python · 17:05 of 03/04/2016
  • ESEngine - Elasticsearch Object Doctype Mapper for Python in python · 12:56 of 02/25/2016
  • Dynaconf - Let your settings to be Dynamic in python · 13:39 of 02/14/2016

  • comments powered by Disqus Go Top