Connexion: Passing configuration objects to routes

Created on 12 Jan 2016  路  15Comments  路  Source: zalando/connexion

Hi,
thanks for this awesome project, I set up a whole api with authentication and everything in 2 hours tops!!
Now I want to pass a configuration file for when I start an api; let's say I have a test api, a dev api and a production api, that all three should make requests on different databases (test, dev, prod), how can I pass the configuration to every function of every route?

Eg I want to be able to achieve this:

  /channel:
    get:
      tags: [Channel]
      operationId: app.elastic.channel
      summary: Get channels
      responses:
        200:
          description: Return Channels
          schema:
            type: array
            items:
              $ref: '#/definitions/Channels'

and in app/elastic.py i got the function:

def channel(config=configuration_object):
    print "{}".format(config) 

In Flask there is the app['config'] and current_app utilities that make this work, but I wonder how it can be achieved here.

Many thanks for the help!

question

Most helpful comment

Ok, found it!

api.py

import connexion

app = connexion.App(__name__)
app.add_api('app/settings/api.yaml')

application = app.app # at this point we got flask
application.config['environment'] = 'test'

if __name__ == '__main__':
    app.run(port=8080, server='gevent')

routes.py

from flask import current_app

def channels():
    print current_app.config['environment'] # prints out 'test'
    return "Hello world"

Does the job pretty well. So I have a shell script that sets the environment everytime (test, dev, prod, qa)

Thanks buddy!

All 15 comments

@KarimJedda thanks for the positive feedback!

What do you want to achieve exactly? Do you want to have different configurations for different routes (operations)? Or do you want to use a global configuration?

Note: you can also use custom classes (with instance or static methods) to encapsulate your operations (example operationId: "mymodule.mysubmodule.MyClass.my_static_method").

You're welcome @hjacobs thanks for this amazing tool!

Well I want to use a global configuration for every route. This means if I start the api in development mode, i want the /channel route to call the function get_channel with configuration=dev. If I start the api in test mode, I want it to call the function get_channel with configuration=test.

This means, I want to put a global configuration variable somewhere here and make it available in all the route functions:

app = connexion.App(__name__)
app.add_api('app/settings/api.yaml')
application = app.app 

if __name__ == '__main__':
    app.run(port=8080, server='gevent')

It would be amazing to find a solution, because I am using a service to start lots of apis and I define the configuration at the service level. ( awesome_utility start --env=test, or awesome_utility start --env=dev ..)

Ok, found it!

api.py

import connexion

app = connexion.App(__name__)
app.add_api('app/settings/api.yaml')

application = app.app # at this point we got flask
application.config['environment'] = 'test'

if __name__ == '__main__':
    app.run(port=8080, server='gevent')

routes.py

from flask import current_app

def channels():
    print current_app.config['environment'] # prints out 'test'
    return "Hello world"

Does the job pretty well. So I have a shell script that sets the environment everytime (test, dev, prod, qa)

Thanks buddy!

When I try to do this exact same pattern, I get this exception

This typically means that you attempted to use functionality that needed to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().

Anyone have a fix for this? I'm trying to do this:

__init__.py

import connexion


def create_app():
    app = connexion.FlaskApp(__name__, specification_dir='./')

    # app.app is the Flask app
    app.app.config.from_envvar('APP_CONFIG_PATH')

    app.add_api('api.yml')

    from db import db_session

    @app.app.teardown_appcontext
    def shutdown_session(exception=None):
        db_session.remove()

    return app


if __name__ == "__main__":
    create_app().run(port=5050)

db.py

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from flask import current_app


with current_app.app_context():
    engine = create_engine(current_app.config.get('DATABASE_URI'), echo=True)
    db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))

Base = declarative_base()
Base.query = db_session.query_property()


def init_db():
    Base.metadata.create_all(bind=engine)

As you can see, I'm doing my best to follow Flask best practices by using an app factory and env-specific configuration files. While I'm able to store them in app.app.config, I can't access them anywhere else. I tried add app_context() above, but that does give me the error RuntimeError: Working outside of application context.

It appears this issue is still a problem in connexion 2.x. Can this issue be re-opened?

I'm also struggling with this. I cannot access the config variables or context stored when creating the app.

Are we just missing something or is this indeed an issue?

I gave up and did something else...

Still an issue.

Same problem as above, flask.current_app cannot get the context.

Sorry to +1, but can anyone comment on a workaround for this?

Sorry to +1, but can anyone comment on a workaround for this?

I'd suggest to open a new issue and reference this one there.

I tried with app_context and looks like it is working:

with app.app.app_context():
    current_app.config['env'] = 'dev'

so in the routes file or whatever file you call in openapi file use this:

env = current_app.config['env']

I tried with app_context and looks like it is working:

with app.app.app_context():
    current_app.config['env'] = 'dev'

so in the routes file or whatever file you call in openapi file use this:

env = current_app.config['dev']

It should probably say env = current_app.config['env']?

I tried with app_context and looks like it is working:

with app.app.app_context():
    current_app.config['env'] = 'dev'

so in the routes file or whatever file you call in openapi file use this:

env = current_app.config['dev']

It should probably say env = current_app.config['env']?

Sorry, I did a typo mistake. Updated the comment. Thanks.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rudyces picture rudyces  路  3Comments

acidjunk picture acidjunk  路  5Comments

FRNCSCM picture FRNCSCM  路  4Comments

bioslikk picture bioslikk  路  4Comments

davidnazw picture davidnazw  路  4Comments