如何在AppEngine中添加修改响应体的WSGI中间件

2 投票
1 回答
870 浏览
提问于 2025-04-16 08:21

添加一个只修改HTTP头部的中间件(比如FirePython)其实很简单,但当你调用webapp.WSGIApplication(environ, start_response)时,它返回的是[''],而不是一个包含内容的可迭代对象:

def __call__(self, environ, start_response):
    ...
    response.wsgi_write(start_response)
    return ['']

response.wsgi_write实际上是负责输出内容的:

def wsgi_write(self, start_response):
    ...
    write = start_response('%d %s' % self.__status, self.__wsgi_headers)
    write(body)
    self.out.close()

这让通过WSGI中间件修改内容变得有点困难。通常我会这样做:

class Upperware:
    def __init__(self, app):
        self.wrapped_app = app

def __call__(self, environ, start_response):
    for data in self.wrapped_app(environ, start_response):
        return data.upper()

但这样不行,因为wrapped_app的返回值是['']。我该如何让Upperware中间件在Google AppEngine上工作呢?是什么设计决定导致了输出响应而不是返回响应呢?

1 个回答

3

如果你想要拦截请求体的写入,你需要自己定义 start_responsewrite 函数,像这样:

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

  def __call__(self, environ, start_response):
    def my_start_response(status, response_headers, exc_info=None):
      write = start_response(status, response_headers, exc_info)
      def my_write(body_data):
        # Do your middleware handling of writes here
        body_data = body_data.upper()
        write(body_data)
      return my_write
    return self.wrapped_app(environ, my_start_response)

至于为什么 webapp 是这样写的,我就不太清楚了。不过,应该可以改变它的行为,让它返回一个迭代器或列表,而不会出问题,所以你可以随意 提交一个bug

撰写回答