Python,Flask:如何为所有响应设置响应头

45

我想将所有我的HTTP响应头设置为以下内容:

response.headers["X-Frame-Options"] = "SAMEORIGIN"

我查看了这个问题,但它只更改一个特定控制器的标头。我想在“before_request”函数中更改所有标头,类似于以下逻辑。我该怎么做?

@app.before_request
def before_request():
    # response.headers["X-Frame-Options"] = "SAMEORIGIN"

1
请注意,X-Frame-Options已被frame-ancestors指令所取代。有关frame-ancestors的更多信息,请访问https://www.w3.org/TR/CSP2/#directive-frame-ancestors,并使用开源库实现Flask CSP:https://github.com/twaldear/flask-csp。 - potench
3个回答

86
在Flask中,可以使用@app.after_request()钩子来设置头部信息。在这个钩子函数中,你会得到一个响应对象,可以在上面设置头部信息。
@app.after_request
def apply_caching(response):
    response.headers["X-Frame-Options"] = "SAMEORIGIN"
    return response

当这个钩子运行时,Flask.request上下文仍然可用,因此您仍然可以基于请求来改变响应。


2
只是为了补充一下,你应该使用 @app.before_request 来获取你的头部令牌并检查其有效性(头部应该在 JavaScript 中发送请求),然后你的 after request 是你应该更改响应头的地方。 - John Ruddell
@JohnRuddell 在存储中,Flask不强制执行或提供令牌验证。断言你应该这样做根本不正确。 - kevr
1
@kevr 如果您拥有一个提供对锁定API进行验证的令牌(例如带有“Bearer”令牌头的JWT),那么before_request是一种检查令牌有效性的方法。这就是我想说的全部内容。 - John Ruddell
不过,它不应该这样,所以我被难住了:https://github.com/pallets/flask/blob/2433522d2967b8a5e46f16de587a8fac5088a47c/flask/app.py#L1431 - opyate
我喜欢Martijn Pieters的回答的简洁性,但如果引起了冲突的X-Frame-Options头,则会有一个我怀疑是gunicorn或Flask堆栈下的其他东西设置为DENY。在这种冲突的情况下,浏览器会回退到DENY,所以我还是像开始一样。进一步的研究导致对他的回答进行了这个小调整,现在对我有用:response.headers["Content-Security-Policy"] = "frame-ancestors 'self'" - macnewbold
显示剩余4条评论

8
“@app.after_request() hook” 对我的用例来说不够适用。我的用例是这样的:我有一个 Google Cloud 函数,我想为所有响应设置 CORS 标头。可能会有多个响应,因为我必须验证输入并在出现问题时返回,我必须处理数据并在某些情况下提前返回等等。因此,我创建了一个帮助函数如下所示:
# Helper function to return a response with status code and CORS headers
def prepare_response(res_object, status_code):
    response = flask.jsonify(res_object)
    response.headers.set('Access-Control-Allow-Origin', '*')
    response.headers.set('Access-Control-Allow-Methods', 'GET, POST')
    return response, status_code

因此,当我想返回响应时(总是带有CORS标头),我现在可以调用此函数,并且不需要重复设置响应标头以启用CORS。

0
我们可以使用 WSGI 中间件在 Python Flask 应用程序中优雅地设置所有响应的响应标头。
使用中间件在 Flask 应用程序上下文中设置响应标头的方式是线程安全的,并且可以用于设置自定义和动态属性,读取请求标头。如果我们从任何辅助类设置自定义/动态响应标头,则这尤其有帮助。
文件:middleware.py
import flask
from flask import request, g

class SimpleMiddleWare(object):
    """
    Simple WSGI middleware
    """

    def __init__(self, app):
        self.app = app
        self._header_name = "any_request_header"

    def __call__(self, environ, start_response):
        """
        middleware to capture request header from incoming http request
        """
        request_id_header = environ.get(self._header_name)  # reading all request headers
        environ[self._header_name] = request_id_header  

        def new_start_response(status, response_headers, exc_info=None):
            """
            set custom response headers
            """
            # set the above captured request header as response header
            response_headers.append((self._header_name, request_id_header))
            # example to access flask.g values set in any class thats part of the Flask app & then set that as response header
            values = g.get(my_response_header, {})
            if values.get('x-custom-header'):
                response_headers.append(('x-custom-header', values.get('x-custom-header')))
            return start_response(status, response_headers, exc_info)

        return self.app(environ, new_start_response)

从主类调用中间件

文件:main.py

from flask import Flask
import asyncio
from gevent.pywsgi import WSGIServer
from middleware import SimpleMiddleWare

    app = Flask(__name__)
    app.wsgi_app = SimpleMiddleWare(app.wsgi_app)

g在import语句中是什么?values = g.get(my_response_header, {})。另外,my_response_header是什么? - user6308605

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接