Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integrating Swagger/OpenAPI generated python server with existing Flask application

I am interested in integrating a swagger-codegen generated Python server with an existing Flask application. swagger-codegen generates a Python implementation based on the Connexion library from a Swagger API specification.

The examples I have found all seem to expect that connexion.App manages the entire flask application.

import connexion

app = connexion.App(__name__, specification_dir='swagger/')
app.add_api('my_api.yaml')
app.run(port=8080)

However, I have existing blueprints, config and sqlalchemy models I would like to integrate with the generated Connexion API. It looks like connexion.App.app is the underlying Flask app. One option might be to reach in and extend the Connexion Flask application, perhaps something like this:

import connexion

app = connexion.App(__name__, specification_dir='swagger/')

app.app.config.from_pyfile('...')
db.init_app(app.app)
for blueprint in my_blueprints:
    app.app.register_blueprint(blueprint)

app.add_api('my_api.yaml')

app.run(port=8080)

Trying to piggyback on the heavily customized Connexion Flask app seems simpler than integrating the bare blueprint from connexion.Api into my existing Flask app. However, I cannot easily tell whether Connexion is designed to play nicely with non-Connexion managed blueprints.

What is the best way to integrate the Connexion Swagger defined API within an existing, traditional Flask application? Has anyone gone down this path?

like image 413
user650881 Avatar asked Jan 16 '17 13:01

user650881


1 Answers

It works to create the connexion.App and then extend the Flask instance from connexion.App(...).app.

It is easiest to stick with an Application Factory. In addition to being a generally useful pattern, it integrates well with the generated tests.

One gotcha is that the connexion Models seem to be expected from the controller, particularly if response validation is enabled, but they are not handled by the default JSON serializer. The model comes with a JSONEncoder class that helps with Model serialization but it needs to be connected in create_app.

def create_app():
    connexionApp = connexion.App(__name__, specification_dir='swagger')
    app = connexionApp.app

    # This allows the connexion models to be serialized to JSON    
    app.json_encoder = JSONEncoder

    # normal configuration

    # The return value is a `connexion.Api`.
    # If needed, the api blueprint is available at `connexion.Api.blueprint`
    connexionApp.add_api('swagger.yaml')

    return app
like image 174
user650881 Avatar answered Sep 30 '22 22:09

user650881