Flask路由执行报错:缺少1个必填位置参数request(GCF场景)
问题根因
两个运行环境对HTTP入口函数的参数传递规则完全不同,原有写法只匹配了其中一个环境的规则,必然出现一边能跑一边崩溃的问题:
- Google Cloud Function(HTTP触发类型)的运行时强制要求入口函数接收1个位置参数
request:平台收到请求后会把封装好的请求对象作为入参传给入口函数,如果函数没定义这个形参,调用时会抛出「传入了多余位置参数」的错误直接崩溃。 - 本地用Flask开发服务调试时,Flask的视图函数默认不会主动传入
request参数:Flask的request是线程隔离的全局对象,直接从flask模块导入使用即可,如果给视图函数硬加request形参,路由匹配执行时没有对应值传入,就会抛出你遇到的TypeError: hello_http() missing 1 required positional argument: 'request'错误。
两种错误写法的对应表现:
def hello_http(request)::匹配GCF参数规则,云端运行正常;不符合Flask视图参数规则,本地运行报错def hello_http()::匹配Flask视图参数规则,本地运行正常;不符合GCF参数规则,云端运行崩溃
兼容方案
不需要维护两套代码,通过入口转发逻辑就可以实现同一份代码同时适配本地调试和云端部署,修正后的完整代码如下:
import firebase_admin from firebase_admin import auth import flask from flask import Flask, request from flask_cors import CORS app = Flask(__name__) CORS(app) firebase_admin.initialize_app() # Flask业务视图,本地调试时直接响应请求,遵循Flask规则不定义request形参 @app.route('/hello_http', methods=['GET']) def hello_http_handler(): if 'token' in request.args: uid = validate(request) if not uid: return ('Unauthorized', 401) response = flask.jsonify({'UID': uid}) print('Headers: ' + str(response.headers)) print('UID: ' + str(uid)) return response return ('bad request!', 400) def validate(req): try: decoded_token = auth.verify_id_token(req.args['token'], check_revoked=True) return decoded_token['uid'] except Exception: return False # GCF指定入口函数,遵循GCF规则接收request入参 def hello_http(request): # 将GCF传入的请求构造为Flask请求上下文,转发给Flask业务逻辑处理 with app.request_context(request.environ): return app.full_dispatch_request() # 本地启动入口,直接运行脚本时启动Flask开发服务 if __name__ == '__main__': app.run()
配置说明
- 本地调试:直接运行脚本即可,测试命令和之前保持一致:
curl -XGET "http://127.0.0.1:5000/hello_http?token=2" - 云端部署:在GCF的函数配置中,将入口点设置为
hello_http即可,不需要修改任何业务代码。
内容的提问来源于stack exchange,提问作者Augusto
相关产品推荐
相关产品推荐

