Reputation: 53
I'm working on a Flask API which works fine. I'm now trying to replace the Flask development server with uWSGI but everything breaks. I'm trying to solve this since 2 days, went through tutorials and searched here but couldn't find a solution to the problem. This is the code: app.py
import logging.config
import settings
import utils
from flask import Flask, Blueprint
from flask_restplus import Resource, Api
from flask_cors import CORS
from api.restplus import api
from api.gan.endpoints.client import ns as gan_client_namespace
# create Flask application
app = Flask(__name__)
CORS(app) # needed for cross-domain requests, allow everything by default
# load logging confoguration and create log object
logging.config.fileConfig('logging.conf')
log = logging.getLogger(__name__)
#
@app.route("/")
def hello():
return "Hello World!"
def __get_flask_server_params__():
'''
Returns connection parameters of the Flask application
:return: Tripple of server name, server port and debug settings
'''
server_name = utils.get_env_var_setting('FLASK_SERVER_NAME', settings.DEFAULT_FLASK_SERVER_NAME)
server_port = utils.get_env_var_setting('FLASK_SERVER_PORT', settings.DEFAULT_FLASK_SERVER_PORT)
flask_debug = utils.get_env_var_setting('FLASK_DEBUG', settings.DEFAULT_FLASK_DEBUG)
flask_debug = True if flask_debug == '1' else False
return server_name, server_port, flask_debug
def configure_app(flask_app, server_name, server_port):
'''
Configure Flask application
:param flask_app: instance of Flask() class
'''
flask_app.config['SERVER_NAME'] = server_name + ':' + server_port
flask_app.config['SWAGGER_UI_DOC_EXPANSION'] = settings.RESTPLUS_SWAGGER_UI_DOC_EXPANSION
flask_app.config['RESTPLUS_VALIDATE'] = settings.RESTPLUS_VALIDATE
flask_app.config['RESTPLUS_MASK_SWAGGER'] = settings.RESTPLUS_MASK_SWAGGER
flask_app.config['ERROR_404_HELP'] = settings.RESTPLUS_ERROR_404_HELP
def initialize_app(flask_app, server_name, server_port):
'''
Initialize Flask application with Flask-RestPlus
:param flask_app: instance of Flask() class
'''
blueprint = Blueprint('tf_api', __name__, url_prefix='/tf_api')
configure_app(flask_app, server_name, server_port)
api.init_app(blueprint)
api.add_namespace(gan_client_namespace)
flask_app.register_blueprint(blueprint)
#from werkzeug.contrib.fixers import ProxyFix
#flask_app.wsgi_app = ProxyFix(flask_app.wsgi_app)
def main():
server_name, server_port, flask_debug = __get_flask_server_params__()
initialize_app(app, server_name, server_port)
log.info(
'>>>>> Starting TF Serving client at http://{}/ >>>>>'.format(app.config['SERVER_NAME'])
)
app.run(debug=flask_debug, host=server_name)
if __name__ == '__main__':
main()
When I run this with python app.py
it works fine.
Now I'm just trying to get the same results using uWSGI:
uwsgi --http :8000 --wsgi-file app.py --callable app
The command line message looks fine:
Accessing 0.0.0.0:8000 also works
However, when I try to access the API it fails: 0.0.0.0:8000/tf_api
I've tried everything that came to my mind but didn't manage to solve this. Some of the things I did were:
Include the following code:
from werkzeug.contrib.fixers import ProxyFix flask_app.wsgi_app = ProxyFix(flask_app.wsgi_app)
Remove app.run()
(Flask Gunicorn app can't get __name__ to equal '__main__')
Move the function_calls outside the main function as otherwise they are only called when running app.py directly, similar to (Flask application with Blueprints+uWSGI+nginx returning 404's (no routing?))
I really have no idea what else could be the issue. I found a similar problem but it's not applicable to my situation because it's related to NGINX which I'm not using yet (How to deploy a flask-restplus app with nginx + uwgsi). Any ideas what else I could try? Maybe I'm missing something obvious, didn't sleep much because of this.
Upvotes: 2
Views: 1188
Reputation: 36
Everything inside initialize_app is invisible by wsgi server, this will work
import logging.config
import settings
import utils
from flask import Flask, Blueprint
from flask_restplus import Resource, Api
from flask_cors import CORS
from api.restplus import api
from api.gan.endpoints.client import ns as gan_client_namespace
# create Flask application
app = Flask(__name__)
CORS(app) # needed for cross-domain requests, allow everything by default
# load logging confoguration and create log object
logging.config.fileConfig('logging.conf')
log = logging.getLogger(__name__)
#
@app.route("/")
def hello():
return "Hello World!"
server_name = utils.get_env_var_setting('FLASK_SERVER_NAME', settings.DEFAULT_FLASK_SERVER_NAME)
server_port = utils.get_env_var_setting('FLASK_SERVER_PORT', settings.DEFAULT_FLASK_SERVER_PORT)
flask_debug = utils.get_env_var_setting('FLASK_DEBUG', settings.DEFAULT_FLASK_DEBUG)
flask_debug = True if flask_debug == '1' else False
app.config['SERVER_NAME'] = server_name + ':' + server_port
app.config['SWAGGER_UI_DOC_EXPANSION'] = settings.RESTPLUS_SWAGGER_UI_DOC_EXPANSION
app.config['RESTPLUS_VALIDATE'] = settings.RESTPLUS_VALIDATE
app.config['RESTPLUS_MASK_SWAGGER'] = settings.RESTPLUS_MASK_SWAGGER
app.config['ERROR_404_HELP'] = settings.RESTPLUS_ERROR_404_HELP
blueprint = Blueprint('tf_api', __name__, url_prefix='/tf_api')
api.init_app(blueprint)
api.add_namespace(gan_client_namespace)
flask_app.register_blueprint(blueprint)
def main():
log.info(
'>>>>> Starting TF Serving client at http://{}/ >>>>>'.format(app.config['SERVER_NAME'])
)
app.run(debug=flask_debug, host=server_name)
if __name__ == '__main__':
main()
Upvotes: 2
Reputation: 666
You are calling your app.register_blueprint in a function that will never be seen by the wsgi server.
I'm guessing you have followed some kind of guide that makes these nice functionsfor you to configure/initialise etc the app. But it is purely made for the development server it would seem.
You have to call Blueprint and init_app outside the functions, or create a new wsgi.py file that imports app and then runs the Blueprint and api.init_app commands.
Upvotes: 0