6

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.

Dustin Ingram
  • 15,737
  • 2
  • 40
  • 56
Nadun Perera
  • 395
  • 3
  • 13

2 Answers2

2

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.

Dan Cornilescu
  • 37,297
  • 11
  • 54
  • 89
  • Thank you for your reply. Yes I understand about the first 2 404's and that is due to the prefix /api. My apologies for the confusing explanation. I have tested the app in my localhost and it works without any issues when you hit localhost:8080/api. It is just that when I push the app into GAE it does not seem to work. – Nadun Perera Sep 10 '18 at 01:16
  • Note the difference between `/api` (what you mentioned you tried locally) and `/api/`shown in the GAE log. They're typically not the same. Try `localhost:8080/api/` as well. – Dan Cornilescu Sep 10 '18 at 01:18
  • Yes, I can hit either /api or /api/ on my localhost and it works. Thank you for your reply Dan. – Nadun Perera Sep 11 '18 at 09:44
1

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)
Dustin Ingram
  • 15,737
  • 2
  • 40
  • 56
  • Thank you for the reply Dustin, I tried this and still it didn't work, still, I am getting the 404 error when I hit /api/. – Nadun Perera Sep 11 '18 at 09:45
  • @NadunPerera See my edit, I was able to get this working with a minimal `main.py` file, perhaps start there and add back the rest of your original file to see where it stops working. – Dustin Ingram Sep 11 '18 at 17:11
  • thank you so much, this works! The issue was with the `configure_app(app)` where I set the `SERVER_NAME` in a settings file to use `localhost:8080`. After removing that from the settings file, server defaulted back to `localhost:5000` and it worked without any issues in GAE. – Nadun Perera Sep 11 '18 at 23:02