Django Response总是Chunked with text / html无法设置Content-Length

时间:2013-03-10 14:59:22

标签: python django http http-headers apache2

在我的Django Application的views.py中,我在尝试设置以下HTTP标头字段后返回一个HttpResponse对象:

# Create a Response Object with the content to return 
response = HttpResponse("%s"%(output_display),mimetype='text/html')
response['Cache-Control'] = 'must-revalidate, max-age=20'
response['Vary'] = 'Accept-Encoding'
response['Transfer-Encoding'] = 'gzip'
#response['Content-Encoding'] = 'gzip'
response['Connection'] = 'close'
#response['Content-Type'] = 'text/html'
response['Content-Length'] = '%s'%(len(output_display))
return response

然后我使用带有FireFox的Live HTTP Headers插件捕获输出,它看起来像:

HTTP/1.1 200 OK
Date: Sun, 10 Mar 2013 14:55:09 GMT
Server: Apache/2.2.22 (Ubuntu)
Transfer-Encoding: gzip, chunked   <---------- Why 'chunked'?
Vary: Accept-Encoding
Connection: close
Cache-Control: must-revalidate, max-age=20
Content-Encoding: gzip
Content-Type: text/html <---------------------- No Content-Length even though I set it?
X-Pad: avoid browser bug

我正在尝试使用Apache2的mem_cache进行缓存,因此我需要设置Content-Length,并且不能将“chunked”用于Transfer-Encoding。

我的Apache2 mem_cache.conf看起来像(仅用于测试的大数字):

<IfModule mod_mem_cache.c>
        CacheEnable mem /
        MCacheSize 10000
        MCacheMaxObjectCount 10000000
        MCacheMinObjectSize 1
        MCacheMaxObjectSize 10000000
        MCacheMaxStreamingBuffer 10000000
</IfModule>

但即使我在响应代码中明确设置了Content-Length和Transfer-Encoding,也会自动插入'chunked',因此我的Content-Length不受尊重。为什么是这样?如何解决此问题以获得所需的响应?谢谢 -

1 个答案:

答案 0 :(得分:0)

我最近在使用mod_wsgi应用程序时遇到了类似的问题;我试图更新使用其内置磁盘缓存的apache配置,改为使用socache / memcache。

磁盘缓存正在运行,但是切换到memcache或shmcb无效。如果我发出了要缓存的资源的请求,则该请求不会存储在缓存中(CacheDetailHeader对此很有帮助)。在调试时检查日志,发现消息:

[Wed Dec 05 18:52:16.571002 2018] [cache_socache:debug] \
[pid 884:tid 140422596777728] mod_cache_socache.c(389): \
[client 127.0.0.1:56576] AH02346: URL 'http://127.0.1.1:80/cacheme/c?' \
had no explicit size, ignoring, referer: http://127.0.0.1/

似乎socache不喜欢没有显式大小的对象。我尝试将这些mod_memcache设置的较新的socache等效项设置为足够大的值:CacheSocacheMaxSizeCacheSocacheReadSize

我知道正在设置Content-Length头并将其传递到某个地方;当我故意对它进行计算时,它会出现在mod_wsgi日志中。

一些发现:

  1. 不要自己设置Transfer-Encoding头,因为WSGI规范禁止这样做:

      

    Who set the Transfer-Encoding: chunked header?

  2. 即使您自己设置了Content-Length标头,它也会被Apache压缩。这会改变长度;当Apache不知道长度是多少时,它将切换为分块并删除Content-Length标头。

我发现有:

  • Content-Type: text/html

  • Content-Length设置为我的utf-8编码大小

在python / mod_wsgi应用程序中设置,然后:

  • SetEnv no-gzip 1

在apache配置中设置,对象将其放入shmcb缓存。

当apache gzip压缩对象时,它会将标头更改为socache不接受的标头。

我到处寻找使它们兼容的方法,但是在这个问题上找不到太多。在mod_cache文档中有提及重新排序缓存/放气过滤器的内容:

  

https://httpd.apache.org/docs/2.4/mod/mod_cache.html#finecontrol

如果我输入指令以重新排序缓存/放气过滤器,则此方法有效:

# within a directory
SetOutputFilter CACHE;DEFLATE

奇怪的是,在发生高速缓存未命中时,服务器返回了压缩的内容,但是在高速缓存命中时,服务器返回了未编码的text / html。这看起来很奇怪,但是我对FilterChain指令的理解还不够好,无法尝试一下。

在与php / content-length相关的问题中,我也发现了一些提及:

  

https://serverfault.com/questions/183843/content-length-not-sent-when-gzip-compression-enabled-in-apache

那里的答案发现,如果他们将DeflateBufferSize设置为足够大的值,则将设置内容长度。

我无法使用它。

因此,似乎在选择缓存还是gzip压缩之间陷入了困境。