Django与mod_wsgi和gzip

时间:2014-03-24 07:30:06

标签: python django gzip mod-wsgi

我使用Django作为休息服务器。我想要获得一个包含我应该解析的JSON的POST。客户端是一个正在压缩请求的salesforce服务器。

为了让请求膨胀,我在VHost中使用它:              SetInputFilter DEFLATE     

几乎所有东西看起来都很好,但是当我读取request.body或request.read(16000)时 - 输入非常小 - 我总是看到切碎的响应(缺少5个字符)。

有什么建议从哪里开始调试?

1 个答案:

答案 0 :(得分:0)

从技术上讲,WSGI规范不支持将输入过滤器变为中间件或甚至在底层Web服务器中的概念。

具体问题是,变更输入过滤器会改变请求内容的数量,但不会更改WSGI环境字典中的CONTENT_LENGTH值。

WSGI规范指出,只允许有效的WSGI应用程序从请求内容中读取CONTENT_LENGTH个字节。因此,在压缩请求内容的情况下,最终请求大小最终将大于CONTENT_LENGTH指定的大小,Web框架可能会在读取所有数据之前截断请求输入。

您可以在以下网址找到有关此问题的一些详细信息:

虽然推动了规范的变化,但从未发生任何事情。

要解决这个问题,你需要做的是实现一个WSGI中间件,你可以将它包裹在Django应用程序中,如果它通过标头传递检测到,原始内容已被压缩,但你在哪里知道Apache解压缩它,会读取所有请求内容,直到它到达流标记的末尾,忽略CONTENT_LENGTH,甚至在将请求传递给Django之前。完成后,它可以更改CONTENT_LENGTH并用替换流替换wsgi.input,然后返回已读取的内容。

因为内容大小可能非常大且未知大小,所以将其全部读入内存并不一定是个好主意。因此,您可能希望一次在块中读取它并将其写入临时文件。然后将wsgi.input替换为临时文件上的打开文件句柄,并将CONTENT_LENGTH替换为文件的最终大小。

如果您正确搜索Google网上论坛上的mod_wsgi存档,您应该先找到关于此问题的讨论,甚至可能会找到一些示例代码。