在处理内容后在WSGI中间件中设置适当的HTTP Content-Length标头

问题描述 投票:1回答:2

[我在基于Werkzeug的应用程序中设置了一个中间件,为我做一些JSON转义和操作(尤其是为基于Angular的REST客户端在JSON前面加上转义字符串)。

我想将整个逻辑保留在中间件层中,不要在基本视图类或基本应用程序中添加任何技巧。

因为我的中间件操纵了内容,所以我从标头中剥离了Content-Length标头,但我想成为一个好的网民,并向客户提供该信息。

不幸的是,在我操纵内容的那一刻,似乎不再有办法调整标题了。我是否必须进一步进行此操作?包装第二个中间件吗?

这是中间件的代码:

class ContentManipulatingMiddle(object):
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        app = self.app

        def start_unpack_data(status, response_headers, exc_info=None):
            # we need to strip content-length
            response_headers = [ (name, value)
                for name, value in response_headers
                if name.lower() != 'content-length' ]

            return start_response(status, response_headers, exc_info)

        app_iter = app(environ, start_unpack_data)

        data = []
        for item in app_iter:
            # do some content manipulation
            data.append(manipulate_content(item))

        # content length has changed, i should reset the content-length header
        # but at this point, how?

        return data
python http-headers wsgi middleware werkzeug
2个回答
0
投票

您无需担心删除/添加/更改content-length标头,当服务器发送响应时,它将由服务器自动处理。发送错误的长度标题可能会给您的网站查看器/ Internet浏览器造成问题。

您可以在此处测试Content-length标头-http://www.dekho-ji.com/website-diagnostics-curl-http-request-response-headers-online


0
投票

能够通过将内部应用程序不允许更改为start_response来更改标题,而改为提供一个收集器伪函数:

class MyMiddleware:
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        inner_status = None
        inner_headers = []
        inner_exc_info = None

        def start_response_collector(status, headers, exc_info=None):
            # Just collects the inner response headers, to be modified before sending to client
            nonlocal inner_status, inner_headers, inner_exc_info
            inner_status = status
            inner_headers = headers
            inner_exc_info = exc_info
            # Not calling start_response(), as we will modify the headers first.
            return None

        # populates the inner_* vars, as triggers inner call of the collector closure
        response_iter = self.app(environ, start_response_collector)

        # removes the content-length, if exists
        headers = [(k, v) for k, v in inner_headers if k.lower() != 'content-length']

        inner_body = b"".join(response_iter)

        ### MANIPULATE YOUR `inner_body` HERE ###
        # E.g. producing a final_body
        final_body = b'DEADBEEF'

        final_body_length = len(final_body)
        headers.append(('Content-Length', str(final_body_length)))

        # Remember to send the modified headers!
        start_response(inner_status, headers, inner_exc_info)
        return final_body
© www.soinside.com 2019 - 2024. All rights reserved.