Flask中JWT解码装饰器引发端点函数覆盖断言错误
问题
编写Flask端点时添加JWT解码装饰器后,持续抛出错误:
AssertionError: View function mapping is overwriting an existing endpoint function
尝试通过装饰器解码JWT令牌,将payload传递给被装饰函数并返回响应,代码片段如下:
def get_config(section): with open('./config/configurations.yml',"r") as file: config = yaml.safe_load(file) return config[section] def decode_jwt_token(token, secret_key, algo): try: decoded_payload = jwt.decode(token,secret_key,algorithms=[algo]) return decoded_payload except jwt.ExpiredSignatureError: print("Token has expired") except jwt.InvalidTokenError: print("Invalid Token") def decodeJWT(func): def wrapper(**kwargs): config = get_config("jwt") auth_header = request.headers.get("Authorization") if auth_header and auth_header.startswith('Bearer'): token = auth_header.split(' ')[1] payload = decode_jwt_token(token, config["secret"], config["jwt_algorithm"]) return func(payload=payload) else: return jsonify({'message': 'Invalid Token'}), 401 return wrapper @app.route("/test",methods=["GET"]) @decodeJWT def test(**kwargs): payload = kwargs.get("payload",None) if payload is None: return jsonify({'message': 'Token is invalid'}), 401 return jsonify({'message': 'This is a secure message', 'data': payload}), 200
完整报错信息:
Traceback (most recent call last): File "C:\Users\al90935\Documents\flask_rest_api\app.py", line 45, in <module> def test(**kwargs): File "C:\Users\al90935\Documents\flask_env\lib\site-packages\flask\sansio\scaffold.py", line 362, in decorator self.add_url_rule(rule, endpoint, f, **options) File "C:\Users\al90935\Documents\flask_env\lib\site-packages\flask\sansio\scaffold.py", line 47, in wrapper_func return f(self, *args, **kwargs) File "C:\Users\al90935\Documents\flask_env\lib\site-packages\flask\sansio\app.py", line 657, in add_url_rule raise AssertionError( AssertionError: View function mapping is overwriting an existing endpoint function: wrapper
请问哪里出错了?是否与传递payload参数有关?
原因与解决方法
这个错误和传递payload参数无关,核心问题是Flask默认用视图函数的名称作为endpoint标识,而你的装饰器返回的wrapper函数没有保留原视图函数的元数据(包括函数名),导致Flask将所有被该装饰器修饰的视图都识别为同名的wrapper端点,从而触发覆盖冲突。
解决方法是给装饰器的wrapper函数添加functools.wraps装饰器,它会把原视图函数的名称、文档字符串等元数据复制到wrapper上,让Flask能正确识别每个视图的唯一endpoint。
修改后的装饰器代码如下:
import functools # 需先导入functools模块 def decodeJWT(func): @functools.wraps(func) # 添加这一行,保留原函数元数据 def wrapper(**kwargs): config = get_config("jwt") auth_header = request.headers.get("Authorization") if auth_header and auth_header.startswith('Bearer'): token = auth_header.split(' ')[1] payload = decode_jwt_token(token, config["secret"], config["jwt_algorithm"]) return func(payload=payload) else: return jsonify({'message': 'Invalid Token'}), 401 return wrapper
额外补充两个优化建议:
decode_jwt_token函数在捕获异常后没有返回值,会导致payload为None,建议在异常分支明确返回None,或者直接抛出Flask的HTTP异常(如abort(401)),让错误处理更清晰。- 可以缓存
get_config的结果,避免每次请求都读取yaml文件,提升接口性能。
内容的提问来源于stack exchange,提问作者aiman
相关产品推荐
相关产品推荐

