flask默认不自动处理options请求,必须在methods参数中显式添加'options'才能避免405错误;推荐返回204状态码并设置access-control-allow-*响应头。

Flask 默认不拒绝非标准方法,但 app.route() 不会自动注册它们——你得显式声明 methods 列表,否则 405 Method Not Allowed 是必然结果。
为什么 OPTIONS 请求总返回 405?
因为 app.route('/api', methods=['GET', 'POST']) 只允许这两个方法,即使浏览器自动发 OPTIONS 预检请求,Flask 也严格按列表匹配。没写进去,就直接拒掉,不进视图函数。
-
methods参数是白名单,不是“除了这些都放行” - Flask 不像某些框架默认添加
HEAD或OPTIONS——它只加HEAD(当GET存在时),OPTIONS必须手动加 - 如果你用 CORS,前端跨域 POST/PUT 带自定义 header,浏览器一定先发
OPTIONS,不处理就卡死
手动注册 OPTIONS 的两种写法
最直白的是在 methods 列表里加上 'OPTIONS':
@app.route('/api/user', methods=['GET', 'POST', 'OPTIONS'])
def user_handler():
if request.method == 'OPTIONS':
return '', 204 # 空响应 + 204 是 CORS 预检推荐做法
# 其他逻辑...
更省事的是用 @app.after_request 统一加头,但注意:这不能替代路由级 OPTIONS 处理,因为 405 错误发生在路由匹配阶段,after_request 根本不会触发。
- 必须确保
methods包含'OPTIONS',否则连函数都进不去 - 返回状态码建议用
204 No Content,不是200;CORS 规范明确要求预检成功时用 204 - 别忘了设响应头:
Access-Control-Allow-Methods、Access-Control-Allow-Headers等需由你代码显式写入response.headers
用 add_url_rule() 动态注册 OPTIONS 路由
当你要批量为多个 endpoint 补 OPTIONS,又不想每个都改装饰器,可以绕过 @app.route,直接调 app.add_url_rule():
app.add_url_rule(
'/api/data',
'data_options',
view_func=lambda: ('', 204),
methods=['OPTIONS']
)
这种写法适合自动化场景,比如从配置文件读出所有 API 路径,统一补上 OPTIONS 视图。
-
view_func可以是 lambda,也可以是普通函数,只要它能返回合法响应 - 注意
endpoint名不能重复,否则启动时报AssertionError - 这种方式和装饰器等价,但更灵活——你可以用循环批量注册,而不用硬编码每个路由
真正容易被忽略的点是:即使你写了 methods=['GET', 'POST', 'OPTIONS'],如果视图函数内部没处理 request.method == 'OPTIONS' 分支,或者返回了带 body 的 200,有些老版本浏览器或代理仍可能拒绝后续请求。预检响应必须干净、无 body、状态码规范。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











