Nadun Perera
Nadun Perera

Reputation: 655

404 error when using Google App Engine with flask and flask-restplus

My main.py file in the root folder looks like below.

app = Flask(__name__)

def configure_app(app):
    app.config['SERVER_NAME'] = settings.FLASK_SERVER_NAME
    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

def initialize_app(app):
    configure_app(app)
    blueprint = Blueprint('api', __name__, url_prefix='/api')
    api.init_app(blueprint)
    api.namespaces.pop(0) #this is to remove default namespace from swagger doc
    api.add_namespace(user_namespace)
    app.register_blueprint(blueprint)

def main():
    initialize_app(app)
    app.run(debug=settings.FLASK_DEBUG)


if __name__ == "__main__":
    main()

My app.yaml file looks like below.

runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app

runtime_config:
  python_version: 3

manual_scaling:
  instances: 1
resources:
  cpu: 1
  memory_gb: 0.5
  disk_size_gb: 10

Below is the requirements.txt file.

Flask==1.0.2
flask-restplus==0.11.0
gunicorn==19.9.0

I am running GAE in a flex environment.

I followed the steps in https://cloud.google.com/appengine/docs/flexible/python/quickstart and was able to succesfully deploy the app to app engine.

When I go to the appspot link, I get 404 Errors and gcloud logs tail looks like below.

2018-09-09 01:49:00 default[20180909t113222]  "GET /" 404
2018-09-09 01:49:01 default[20180909t113222]  "GET /favicon.ico" 404
2018-09-09 01:49:09 default[20180909t113222]  "GET /api/" 404

I tried looking for a solution but never found one that is similar to my scenario.

Any help in this very much appreciated.

Thank you.

Upvotes: 6

Views: 1323

Answers (2)

Dustin Ingram
Dustin Ingram

Reputation: 21580

Your main function will not get called when deploying to App Engine. Instead, App Engine uses Gunicorn and the entrypoint you've defined in your app.yaml file.

Since main is not getting called, your initialize_app function is not getting called either, which is adding the endpoints you're looking for.

Instead, you should do something like the following:

app = Flask(__name__)
initialize_app(app)

def configure_app(app):
    ...

def initialize_app(app):
    ... 

if __name__ == "__main__":
    # Only use this for things need to run the app locally,
    # will not be used when deploying to App Engine
    app.run(debug=settings.FLASK_DEBUG)

EDIT: I was able to get this working with this minimal main.py:

from flask import Flask, Blueprint
from flask_restplus import Api

app = Flask(__name__)
api = Api()
blueprint = Blueprint('api', __name__, url_prefix='/api')
api.init_app(blueprint)
app.register_blueprint(blueprint)

Upvotes: 1

Dan Cornilescu
Dan Cornilescu

Reputation: 39834

Your existing code only adds one blueprint, with the /api URL prefix, so it won't be able to handle requests for / or /favicon.ico (which many browsers request by default) - explaining the first 2 404 errors in your request log. If your app is intended to be visited by regular browsers you may want to add other blueprints to cover those URLs as well, otherwise those 404s are expected/normal.

I'm not familiar with flask and blueprints, so I'm unsure if the blueprint you have should, initiated as it presently is, serve already the /api/ URL. If not - that would explain the 3rd 404 in the request log. I suspect you may need to add a route/rule for it in the blueprint, tho.

Upvotes: 2

Related Questions