I am fairly new to Flask applications. While my application works for all the endpoints as expected when I tried to add jwt authorization I encountered this issue. I have tried this solution app.app_context().push() based on some other questions that have been posted.
Any help would be greatly appreciated. I would also like to use the decorator in multiple apis, should I include the token_required function in each one, or best practise would be to be imported?
Error:
Traceback (most recent call last): File "C:/Users/Gerasimos/Documents/Python/api_mongo/main.py", line 1, in <module> from app import create_app File "C:UsersGerasimosDocumentsPythonapi_mongoapp.py", line 2, in <module> from users.api import users File "C:UsersGerasimosDocumentsPythonapi_mongousersapi.py", line 60, in <module> @token_required File "C:UsersGerasimosDocumentsPythonapi_mongousersapi.py", line 31, in token_required return decorated() File "C:UsersGerasimosDocumentsPythonapi_mongousersapi.py", line 29, in decorated return jsonify({'message' : 'Token is invalid!'}), 401 File "C:UsersGerasimosAppDataLocalProgramsPythonPython37-32libsite-packagesflaskjson__init__.py", line 309, in jsonify if current_app.config['JSONIFY_PRETTYPRINT_REGULAR'] or current_app.debug: File "C:UsersGerasimosAppDataLocalProgramsPythonPython37-32libsite-packageswerkzeuglocal.py", line 347, in __getattr__ return getattr(self._get_current_object(), name) File "C:UsersGerasimosAppDataLocalProgramsPythonPython37-32libsite-packageswerkzeuglocal.py", line 306, in _get_current_object return self.__local() File "C:UsersGerasimosAppDataLocalProgramsPythonPython37-32libsite-packagesflaskglobals.py", line 51, in _find_app raise RuntimeError(_app_ctx_err_msg) RuntimeError: Working outside of application context. 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(). See the documentation for more information.
My application structure:
main.py
from app import create_app app = create_app() if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True)
app.py
from flask import Flask from users.api import users from auth.api import auth def create_app(settings_overrides=None): app = Flask(__name__) configure_settings(app, settings_overrides) configure_blueprints(app) return app def configure_settings(app, settings_override): app.config.update({ 'DEBUG': True, 'TESTING': True, 'JSON_SORT_KEYS': False }) if settings_override: app.config.update(settings_override) def configure_blueprints(app): app.register_blueprint(users, url_prefix='/api') app.register_blueprint(auth, url_prefix='/api')
usersapi.py
from flask import Blueprint, request, Response, jsonify from pymongo import MongoClient import json from validation.RegistrationValidator import UserSchema from validation.UpdateUserValidator import UpdateUserSchema from marshmallow import ValidationError from functools import wraps import jwt client = MongoClient('localhost', 27017) database = client['python_crud_api'] users_collection = database['users'] users = Blueprint('users', __name__) SECRET_KEY = "hrtegwfjnvwivmwrhriwcg" def token_required(f): @wraps(f) def decorated(*args, **kwargs): try: token = request.headers.get('Authorization') data = jwt.decode(token, SECRET_KEY) return f(*args, **kwargs) except: headers = {'Content-Type': 'application/json'} return jsonify({'message' : 'Token is invalid!'}), 401 # Response(json.dumps({"message": "Unauthorized user"}), 401, headers=headers) return decorated() @users.route('/user', methods=['GET']) @token_required def get_users(): headers = {'Content-Type': 'application/json'} all_users = users_collection.find() result = [] # When a user is returned the password must not be in the response body for user in all_users: result.append({'username': user['username'], 'email': user['email']}) return Response(json.dumps({"Users": result}), status=200, headers=headers)
Advertisement
Answer
return decorated
not return decorated()
in token_required
. Otherwise, you’ll be calling the wrapped function whenever you define a decorated function.