2

对于我正在开发的应用程序,用户提交带有多部分表单数据(内容类型:multipart/form-data)的 gzip 压缩 HTTP POST 请求(内容编码:GZIP)。我使用 mod_deflate 作为输入过滤器进行解压缩,并通过 mod_wsgi 在 Django 中处理 Web 请求。

一般来说,一切都很好。但是对于某些请求(确定性),从请求到响应几乎有一分钟的延迟。调查显示 django 中的处理立即完成,但来自服务器的响应停止。如果请求不是 GZIPed,则一切正常。

请注意,为了处理 mod_wsgi 中的故障,我将 content-length 设置为未压缩的消息大小。

有没有人遇到过这个问题?有没有办法在处理响应时轻松调试 apache?

4

1 回答 1

5

您认为 mod_wsgi 中存在什么故障?

简单的事实是 WSGI 1.0 不支持改变请求内容的内容长度的可变输入过滤器。因此,在使用 WSGI 1.0 时,从技术上讲,您不能在 Apache 中使用 mod_deflate 来请求内容。您将内容长度设置为实际大小以外的值很可能会填充 mod_deflate 的操作。

如果您希望能够处理压缩的请求内容,您需要跳出 WSGI 1.0 规范并使用非标准代码。

我建议您阅读以下内容:

http://blog.dscpl.com.au/2009/10/details-on-wsgi-10-amendmentsclarificat.html

这解释了这个问题和有关它的建议。

我非常建议您将此问题提交给官方mod_wsgi 邮件列表,以讨论您需要如何编写代码。但是,如果您使用的是 Python 框架之一,您可能会受到限制,因为它们将实现 WSGI 1.0,而您无法做到这一点。


更新 1

根据 mod_wsgi 列表的讨论,原始的 WSGI 应用程序应该包含在以下 WSGI 中间件中。这仅适用于实际提供空字符串作为输入的结束标记的 WSGI 适配器,这是 WSGI 1.0 不需要的。这可能只用于小型上传,因为所有内容都被读入内存。如果需要大量压缩上传,则应将累积的数据写入文件。

class Wrapper(object):

    def __init__(self, application):
        self.__application = application

    def __call__(self, environ, start_response):
        if environ.get('HTTP_CONTENT_ENCODING', '') == 'gzip':
            buffer = cStringIO.StringIO()
            input = environ['wsgi.input']
            blksize = 8192
            length = 0

            data = input.read(blksize)
            buffer.write(data)
            length += len(data)

            while data:
                data = input.read(blksize)
                buffer.write(data)
                length += len(data)

            buffer = cStringIO.StringIO(buffer.getvalue())

            environ['wsgi.input'] = buffer
            environ['CONTENT_LENGTH'] = length

        return self.__application(environ, start_response)


application = Wrapper(original_wsgi_application_callable)
于 2009-10-13T22:22:50.647 回答