Django Response 总是用 text/html 分块无法设置 Content-Length [英] Django Response always Chunked with text/html cannot set Content-Length
问题描述
在我的 Django 应用程序的 views.py 中,我在尝试设置以下 HTTP 标头字段后返回一个 HttpResponse 对象:
In my Django Application's views.py , I return an HttpResponse object after attempting to set the following HTTP Header fields:
# 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 插件捕获输出,它看起来像:
I then capture the output using the Live HTTP Headers plugin with FireFox, and it looks like:
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 进行缓存,因此我需要设置内容长度并且不能为传输编码设置分块".
I am trying to cache using Apache2's mem_cache, so I need the Content-Length to be set and cannot have 'chunked' for Transfer-Encoding.
我的 Apache2 mem_cache.conf 看起来像(大量仅用于测试):
My Apache2 mem_cache.conf looks like ( large numbers just for testing ):
<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 没有得到遵守.为什么是这样?如何解决此问题以获得所需的响应?谢谢-
But even though I explicitly set the Content-Length and Transfer-Encoding in my response code, 'chunked' is inserted automatically and therefore my Content-Length is not honored. Why is this? How can I fix this to get the desired response? Thanks -
推荐答案
我最近在使用 mod_wsgi 应用程序时遇到了类似的问题;我试图更新一个使用其内置磁盘缓存的 apache 配置,改为使用 socache/memcache.
I came across a similar issue recently with a mod_wsgi application; I was trying to update an apache configuration that was using its built-in disk cache, to use socache/memcache instead.
磁盘缓存工作正常,但切换到 memcache 或 shmcb 不起作用.如果我发出对我想要缓存的资源的请求,它不会将它存储在缓存中(CacheDetailHeader
对此很有帮助).在调试时检查日志,我发现了消息:
The disk cache was working, but switching to memcache or shmcb didn't work. If I issued a request for a resource I wanted cached, it wouldn't store it in the cache (CacheDetailHeader
is helpful for this). Checking the logs at debug, I found the message:
[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 等效项设置为足够大的值:CacheSocacheMaxSize
和 CacheSocacheReadSize
.
It seems that socache doesn't like objects that don't have explicit sizes. I tried setting the newer, socache equivalents of those mod_memcache settings to sufficiently large values: CacheSocacheMaxSize
and CacheSocacheReadSize
.
我知道 Content-Length
标头已被设置并传递到某个地方;当我故意错误计算它时,它出现在 mod_wsgi 日志中.
I know that the Content-Length
header was being set and made it through to somewhere; it showed up in the mod_wsgi logs when I deliberately miscalculated it.
我发现的一些事情:
不要自己设置
Transfer-Encoding
标头,因为这是 WSGI 规范禁止的:
Don't set
Transfer-Encoding
header yourself, as this is forbidden by the WSGI specification:
即使您自己设置 Content-Length
标头,它也会被 apache 压缩.这会改变长度;当 Apache 不知道长度是多少时,它会切换到分块并删除 Content-Length
标头.
Even though you're setting the Content-Length
header yourself, it's also being gzipped by apache. This changes the length; when Apache doesn't know what the length will be, it switches to chunked and removes the Content-Length
header.
我发现:
内容类型:text/html
Content-Length
设置为我的 utf-8 编码大小
Content-Length
set to my utf-8 encoding size
在 python/mod_wsgi 应用程序中设置,并且:
set in the python/mod_wsgi application, and:
SetEnv no-gzip 1
在 apache 配置中设置,该对象将其放入 shmcb 缓存中.
set in the apache configuration, that the object made it into a shmcb cache.
看起来当 apache gzip 一个对象时,它会将标头更改为不被 socache 接受.
It looks like when apache gzips an object, it changes the headers to that it isn't accepted by socache.
我四处寻找使它们兼容的方法,但在这个问题上找不到太多.在 mod_cache 文档中有一些提到重新排序缓存/放气过滤器:
I looked around for ways to make them compatible, but couldn't find too much on this issue. There is some mention of reordering the cache/deflate filters in the mod_cache documentation:
https://httpd.apache.org/docs/2.4/mod/mod_cache.html#finecontrol
如果我放入一个指令来重新排序缓存/放气过滤器,这会起作用:
This worked if I put in a directive to reorder the cache/deflate filters:
# within a directory
SetOutputFilter CACHE;DEFLATE
奇怪的是,在缓存未命中时,服务器返回 gzipped 内容,但在缓存命中时,服务器返回未编码的文本/html.这看起来很奇怪,但我对 FilterChain 指令的理解不够好,无法尝试.
Curiously, on a cache miss, the server returned gzipped content, but on a cache hit, the server returned unencoded text/html. This looks odd, but I haven't understood the FilterChain directives well enough to try those out.
我还在一个与 php/content-length 相关的问题中发现了这一点:
I also found some mention of this in a related issue with php/content-length:
那里的答案发现,如果他们将 DeflateBufferSize
设置为足够大的值,则将设置 content-length.
The answer there found that if they set the DeflateBufferSize
to a large-enough value, then content-length would be set.
我无法让它工作.
所以看起来人们在选择缓存还是 gzip 之间陷入了困境.
So it looks like one is stuck between choosing cached or gzipped.
这篇关于Django Response 总是用 text/html 分块无法设置 Content-Length的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!