我正在使用 Python Flask 为 IBM Bluemix 编写一个应用程序。我想强制入站请求为 https。这段代码有效:
# We want to redirect the request to use https. X-Forwarded-Proto is only set in Bluemix runtime.
forwarded_protocol = request.headers.get('X-Forwarded-Proto', None)
if forwarded_protocol is not None:
if forwarded_protocol == 'http':
new_url = request.url.replace('http', 'https', 1)
return redirect(new_url)
我不想将其放在每个路由定义中,而是想在一个地方进行。根据 Flask 文档,我认为我想要的是使用 before_request()
。
Flask 文档指出:
The function will be called without any arguments. If the function returns a non-None value, it’s handled as if it was the return value from the view and further request handling is stopped.
我认为这意味着如果我返回 None
,处理将继续使用请求的路由代码。所以我的实现如下所示:
@app.before_request
def force_https():
# We want to redirect the request to use https. X-Forwarded-Proto is only set in Bluemix runtime.
try:
forwarded_protocol = request.headers.get('X-Forwarded-Proto', None)
if forwarded_protocol is not None:
if forwarded_protocol == 'http':
new_url = request.url.replace('http', 'https', 1)
return redirect(new_url)
else:
return None
else:
return None
except RuntimeError as e:
return None
很明显,我的实现或理解有问题。此方法运行到路由代码后,我无法将控制权移交。而且 before_request()
似乎也在 Flask 启动时、在第一个请求之前被调用,因此有 try/except
block 。我的失败是否与我的实现和对 Flask 的理解有关?
最佳答案
您可以检查请求端点是否是 View 函数之一,以避免运行时错误。 return None
在技术上等同于 return
,但如果您不执行任何操作,Python 中的函数会自动返回 None
。确保将“http://”替换为“https://”,而不仅仅是“http”,因为字符串“http”可能出现在 URL 中的任何其他位置。与检查 X-Forwarded-Proto header 相比,request.is_secure
可能是检查请求是否安全的更好方法。尝试以下操作:
@app.before_request
def force_https():
if request.endpoint in app.view_functions and not request.is_secure:
return redirect(request.url.replace('http://', 'https://'))
您还可以创建自己的装饰器来重定向非安全请求。例如,请参阅以下代码片段:http://flask.pocoo.org/snippets/93/ .
关于python - 通过 Flask 的 before_request() 强制使用 HTTPS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45742972/