【问题标题】:Python, Flask: How to set response header for all responsesPython,Flask:如何为所有响应设置响应标头
【发布时间】:2015-08-23 09:24:43
【问题描述】:

我想将我所有的 http 标头响应设置为这样的:

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

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

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

【问题讨论】:

标签: python flask http-headers


【解决方案1】:

我们可以使用 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)

【讨论】:

    【解决方案2】:

    @app.after_request() hook 不适合我的用例。

    我的用例如下:我有一个谷歌云功能,我想为所有响应设置 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 所需的 response.headers 设置。

    【讨论】:

      【解决方案3】:

      @app.after_request() hook 中设置标头,此时您有一个响应对象来设置标头:

      @app.after_request
      def apply_caching(response):
          response.headers["X-Frame-Options"] = "SAMEORIGIN"
          return response
      

      flask.request context 在此钩子运行时仍然可用,因此此时您仍然可以根据请求改变响应。

      【讨论】:

      • 只是为了补充这一点。您应该使用@app.before_request 来获取您的标头令牌并检查其有效性..(标头应与 javascirpt 中的请求一起发送)然后您的请求后是您应该更改响应标头的地方
      • @JohnRuddell 在库存中,Flask 不强制执行或提供令牌验证。断言你应该这样做是不正确的。
      • @kevr 如果您有一个为锁定的 api 提供验证的令牌(例如带有“Bearer”令牌标头的 JWT),那么 before_request 是一种检查令牌有效性的方法。这就是我想说的。
      • @opyate:那是您在那里进行的相当大的编辑。您能否使用评论指出将来的其他问题?我在 SO 上相当活跃,并且总是乐于接受建议。
      • @opyate:我回滚了那个编辑。破解after_requests_func 映射是一个更高级的主题,也许应该成为单独的问答对的主题。
      猜你喜欢
      • 2014-11-09
      • 2018-09-12
      • 2015-10-18
      • 2018-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多