Flask API仅支持GET访问,POST请求返回405错误排查求助
问题描述
我用Python Flask搭建了Import服务作为API接收JSON文件,通过Keycloak做身份校验,同时部署了一个Vue应用和另一个运行正常的Flask后端应用。所有服务都用NGINX配置部署。向Import服务发送GET请求能得到200响应,但发送POST请求时,虽然能从Keycloak成功获取access token,却返回405错误。不确定问题出在Flask应用还是NGINX,相关代码如下:
Flask 代码
require_auth = ResourceProtector() validator = ClientCredsTokenValidator("https://myEndpoint/energy/data") require_auth.register_token_validator(validator) @app.route('/energy/data', methods=['POST']) @require_auth("energy_data") def energy_data_api(): data = request.json print(request.headers) # res = add_new_data(data, 'add-energy-data') ####DB Entry response = "JSON ARRIVED" print(response) return jsonify(message=response), 200
NGINX 配置
server { listen 80; server_name my.domain; return 301 https://$host$request_uri; } upstream backend { server my.domainIP:5000; } upstream import { server my.domainIP:5001; } server { listen 443 ssl; server_name my.domain; ssl_certificate /etc/nginx/certs/fullchain.pem; ssl_certificate_key /etc/nginx/certs/privkey.pem; location / { try_files $uri $uri/ /index.html; root /usr/share/nginx/html; index index.html; } location /getUser { include uwsgi_params; uwsgi_pass backend; } location /action { include uwsgi_params; uwsgi_pass backend; } location /energy/data { include uwsgi_params; uwsgi_pass import; } location /masterData/update { include uwsgi_params; uwsgi_pass import; } }
可能的原因与解决方法
1. 请求URL的斜杠差异导致重定向
Flask默认对路由的斜杠严格匹配:/energy/data 和 /energy/data/ 会被视为两个不同的路径。如果你的POST请求URL末尾带斜杠,Flask会返回301重定向到不带斜杠的版本,而客户端在重定向时会把POST请求转为GET请求,最终触发405错误(因为你的路由只支持POST)。
解决方法:
在Flask路由中添加strict_slashes=False,关闭斜杠严格匹配:
@app.route('/energy/data', methods=['POST'], strict_slashes=False) @require_auth("energy_data") def energy_data_api(): # 原有代码不变
2. HTTP转HTTPS的重定向导致请求方法变更
你的NGINX配置会把80端口的HTTP请求301重定向到HTTPS。如果客户端发送的是HTTP的POST请求,经过301重定向后,请求方法会被转为GET,导致Flask收到GET请求但路由只支持POST,返回405。
解决方法:
确保客户端直接发送HTTPS的POST请求,避免经过HTTP到HTTPS的重定向。如果无法修改客户端,可改用307重定向(307会保留请求方法和请求体):
server { listen 80; server_name my.domain; return 307 https://$host$request_uri; }
3. uWSGI未正确传递请求方法
如果NGINX的uwsgi_params文件中缺少uwsgi_method $request_method;配置,Flask无法正确识别请求方法,可能默认把所有请求当作GET处理,导致POST请求被判定为不允许的方法。
解决方法:
检查/etc/nginx/uwsgi_params文件,确保包含以下内容:
uwsgi_method $request_method;
如果没有,手动添加后重启NGINX。
4. 验证Flask实际接收的请求方法
在Flask代码中添加打印请求方法的日志,确认实际收到的请求类型:
@app.route('/energy/data', methods=['POST']) @require_auth("energy_data") def energy_data_api(): print(f"Received request method: {request.method}") # 添加这行 data = request.json print(request.headers) # 原有代码不变
如果日志打印的是GET,说明请求方法被篡改,回到前几个原因排查;如果是POST,则需要检查Keycloak认证装饰器是否存在逻辑问题,或是否有其他中间件修改了请求。
内容的提问来源于stack exchange,提问作者Pai-Ting Lee

