【发布时间】:2012-10-13 11:24:05
【问题描述】:
我想使用 Javascript 将压缩的 POST 数据发送到我控制的服务器。有什么办法让 HTTP 层处理压缩。
我正在发送 JSON。如果我将内容类型设置为 GZIP/deflate,浏览器是否会自动压缩它,然后带有 deflate mod 的 Apache 会自动解压它,这样我的应用程序就不必考虑压缩数据了吗?
我知道它可以反过来工作,但有什么方法可以让它这样工作?
【问题讨论】:
我想使用 Javascript 将压缩的 POST 数据发送到我控制的服务器。有什么办法让 HTTP 层处理压缩。
我正在发送 JSON。如果我将内容类型设置为 GZIP/deflate,浏览器是否会自动压缩它,然后带有 deflate mod 的 Apache 会自动解压它,这样我的应用程序就不必考虑压缩数据了吗?
我知道它可以反过来工作,但有什么方法可以让它这样工作?
【问题讨论】:
浏览器会自动为您的数据进行 gzip 编码吗?简短的回答是否定的。
长答案是一些用户代理可以做这样的事情,但你肯定不能依赖它。 apache mod_deflate 文档状态:
一些特殊的应用程序确实支持请求压缩,例如一些 WebDAV 客户端。
所以,不,那是行不通的。您需要自己生成适当的 HTTP 请求消息。在这种情况下,适当的标头是 Content-Encoding: gzip 而不是 Content-Type:,因为内容本身是 application/json,您只是希望对 HTTP 请求消息的实体主体进行编码以进行传输。
请注意,您还需要添加适当的 Content-Length: 标头,指定压缩后消息实体主体的大小(以字节为单位) - 或 - 使用 Transfer-Encoding: chunked 发送您的 HTTP 消息并放弃内容长度规范。
在接收端,可以instruct mod_deflate to use an input filter解压信息:
<Location /dav-area>
SetInputFilter DEFLATE
</Location>
如果您只接收几个资源的压缩消息正文,这有点麻烦。相反,您可能应该只使用客户端脚本来检查 Content-Encoding: gzip 标头并手动解压缩请求正文。如何做到这一点说,PHP,完全是另一个问题。如果您需要详细信息,您应该发布另一个问题。
【讨论】:
这是可能的,但我强烈建议不要接受传入服务器的 gzip 压缩数据。主要原因是防止您的服务器获取gzip bombed。在实际解压缩之前通常不可能知道未压缩数据的样子,因此用户可以向您发送一个看起来像无害的 1 KB 或 1 MB 数据但实际上是 100 GB 数据的 Web 请求,然后您的 Web服务器(nginx 或 apache)在接下来的 10 分钟内挂起,试图将其全部解压,最终内存不足/锁定。
【讨论】:
Content-Length 必须是压缩后的大小。请求中没有关于未压缩大小的信息。 (换句话说,Content-Length 是“以字节为单位的网络长度”)
刚刚使用https://github.com/dankogai/js-deflate 实现了这一点 但是,无论出于何种原因,postdata 都会去掉 + 符号并用空格替换它们。
通过 javascript 发送数据:
params.mapdata= btoa(RawDeflate.deflate(JSON.stringify(mapdata)));
通过php接收数据:
$value = gzinflate(base64_decode(preg_replace('/\s/', '+',$value)));
【讨论】:
+ 应该作为%2B 发送。 + 是旧的空白编码。
php://input 获取原始有效负载。对于 Node.js,它默认为您提供原始负载缓冲区。