I have set a decorator for functions of my routes to abort(401) if api-key is invalid (or not specified) inside headers of requests.
So I define this function in a dedicated file of my main module (named app) and it is imported inside all of my blueprints definition. But from this file, I have no access to app object to load the API key stored in config. I tried to use current_app, but I have an error telling me I cannot use it outside of the app context. I cannot import directly app object from app module either as it results with a circular importation.
If I declare the decorator inside __init__.py file, I will be faced with the same issue: I will not be able to import require_apikey function from app module as blueprint modules are already imported in app module for blueprint registration.
I assume there are some issues with my design. Could you point my flaws and help me fixing it ?
My project directory looks like this:
project/
- run.py
- app/
- - __init__.py
- - player.py
- - require_apikey.py
And here is the content of these files:
# run.py
from app import app
if __name__ == "__main__":
app.run()
# app/__init__.py
from flask import (
Flask,
render_template,
jsonify)
from app.db import db
from app.player import player
app = Flask(__name__)
app.config.from_object("app.config.Config")
app.register_blueprint(player, url_prefix="/player/")
db.init_app(app)
with app.app_context():
db.create_all()
# app/player.py
from flask import (
Blueprint,
request,
abort,
jsonify)
from app import require_apikey
from app.models.player import Player
from app.db import db
player = Blueprint(__name__, __name__)
@player.route('/', methods=["GET", "POST"])
@require_apikey
def root():
# Do some stuff
# app/require_apikey.py
from functools import wraps
from flask import (
request,
abort,
current_app
)
API_KEY = current_app.config["SECRET_KEY"]
def require_apikey(view_function):
@wraps(view_function)
def decorated_function(*args, **kwargs):
if request.headers.get("api-key") and request.headers.get("api-key") == API_KEY:
return view_function(*args, **kwargs)
else:
abort(401, "Invalid API key")
return decorated_function