强制在Flask的before_request()

时间:2017-08-17 18:54:53

标签: python flask ibm-cloud

我正在使用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有所了解吗?

1 个答案:

答案 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/