Falcon框架CORS未返回正确Header,预检请求失败问题排查
嘿,看来你在Falcon的CORS配置上踩坑了,我来帮你拆解下问题所在:
首先看你的当前配置:
cors = CORS(allow_all_origins=True, allow_headers_list=['authorization','content-type'], allow_all_methods=True) app = falcon.API(middleware=[ cors.middleware, PeeweeConnectionMiddleware(), MultipartMiddleware(), auth_middleware, ])
用Axios发起请求时,Firefox的预检请求直接失败,报错:
Reason: missing token ‘authorization’ in CORS header ‘Access-Control-Allow-Headers’
你尝试设置allow_all_headers=True后还是没用,而且控制台日志显示:
Aborting response due to unallowed method [pid: 26577|app: 0|req: 1/1] 127.0.0.1 () {42 vars in 697 bytes} [Sun May 20 16:54:29 2018] OPTIONS /api/v1/auth => generated 0 bytes in 1 msecs (HTTP/1.1 200) 5 headers in 164 bytes (0 switches on core 0)
问题根源分析
日志里的「Aborting response due to unallowed method」是关键线索:你的auth_middleware很可能在CORS中间件之前就拦截了OPTIONS预检请求!
因为浏览器发送的OPTIONS预检请求不会携带Authorization头,如果你的认证中间件没有跳过OPTIONS请求,就会直接拒绝这个请求,导致CORS中间件根本没机会设置Access-Control-Allow-Headers这类关键响应头,自然就会报头缺失的错误。
另外,Falcon的CORS中间件在部分旧版本里,allow_all_headers=True和allow_headers_list的优先级可能有冲突,不过这不是核心问题,核心还是中间件的执行顺序和OPTIONS请求的处理逻辑。
解决方案
1. 调整中间件顺序,让认证中间件跳过OPTIONS请求
首先修改你的auth_middleware,让它直接跳过OPTIONS请求的认证检查:
class AuthMiddleware: def process_request(self, req, resp): # 预检请求不需要认证,直接放行 if req.method == 'OPTIONS': return # 你的正常认证逻辑...
然后确保CORS中间件在中间件列表的最前面,保证它先处理请求并设置响应头:
app = falcon.API(middleware=[ cors.middleware, # 放最前面,优先处理CORS PeeweeConnectionMiddleware(), MultipartMiddleware(), auth_middleware, ])
2. 简化CORS配置(可选)
如果还是有问题,可以简化CORS配置,直接允许所有头和方法,避免参数冲突:
cors = CORS(allow_all_origins=True, allow_all_headers=True, allow_all_methods=True)
3. 手动处理OPTIONS请求(兜底方案)
如果上面的方法都无效,可以给对应的路由手动添加OPTIONS请求处理,直接返回正确的CORS头:
class AuthResource: def on_options(self, req, resp): resp.headers['Access-Control-Allow-Origin'] = '*' resp.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS' resp.headers['Access-Control-Allow-Headers'] = 'authorization, content-type' resp.status = falcon.HTTP_200 app.add_route('/api/v1/auth', AuthResource())
内容的提问来源于stack exchange,提问作者Yábir Garcia

