CloudRun部署Flask应用HTTPS请求被转为HTTP问题咨询
问题成因
CloudRun采用边缘节点统一终结TLS的架构设计:所有外部发往CloudRun服务的HTTPS请求,会先被GCP官方的边缘代理节点完成TLS解密,之后边缘代理会通过GCP内部私有网络,使用纯HTTP协议将请求转发到你的容器实例。这是官方默认的实现逻辑,不存在请求被劫持降级的安全问题。
你当前的判断逻辑失效、request.url显示为HTTP地址,都是因为Flask默认不识别代理转发的请求头,request.is_secure只会直接读取当前容器收到的请求的协议,因此永远返回False。GCP边缘代理已经将用户真实的请求协议放在X-Forwarded-Proto请求头中,HTTPS请求对应的该头值为https,只需调整逻辑读取该字段即可。
修复方案
你可以任选以下任意一种方案修复判断逻辑:
- 方案1:使用
ProxyFix中间件适配代理场景,无需修改原有校验逻辑
from flask import Flask, request, Response from werkzeug.middleware.proxy_fix import ProxyFix app = Flask(__name__) # 适配CloudRun单代理场景的参数配置 app.wsgi_app = ProxyFix( app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1 ) def beforeRequest(): if not request.is_secure: return Response(f"Invalid protocol. Received request was: {request.url}", status=301)
- 方案2:直接修改校验逻辑,读取
X-Forwarded-Proto头判断原始协议
def beforeRequest(): if request.headers.get("X-Forwarded-Proto", "http") != "https": return Response(f"Invalid protocol. Received request was: {request.url}", status=301)
排查方法
如果仍有疑问,可以通过以下方式验证请求信息:
- 临时在拦截逻辑中打印全量请求头,确认
X-Forwarded-Proto字段的取值,即可确认用户原始请求的真实协议 - 测试时直接返回全量请求头内容,即可直观看到边缘代理携带的所有转发信息,确认参数正确
内容的提问来源于stack exchange,提问作者Manu
相关产品推荐
相关产品推荐

