我正在使用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文档说明:
将在不带任何参数的情况下调用该函数。如果函数返回非None值,则将其处理为视图中的返回值,并停止进一步的请求处理。
我认为这意味着如果我返回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
块。我的失败是我的实施问题,对Flask有所了解吗?
答案 0 :(得分:1)
您可以检查请求端点是否是视图函数之一,以避免运行时错误。 return None
在技术上等同于return
,但如果你什么都不做,python中的函数会自动返回None
。确保将“http://”替换为“https://”而不仅仅是“http”,因为字符串“http”可能发生在URL中的任何其他位置。并且request.is_secure
可能是检查请求是否安全的更好方法,而不是检查X-Forwarded-Proto
标头。试试以下内容:
@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/。