使用 curl 时如何正确处理压缩页面?

Posted

技术标签:

【中文标题】使用 curl 时如何正确处理压缩页面?【英文标题】:How to properly handle a gzipped page when using curl? 【发布时间】:2012-01-11 23:21:12 【问题描述】:

我编写了一个 bash 脚本,它使用 curl 从网站获取输出,并对 html 输出进行一系列字符串操作。问题是当我对一个返回其输出 gzip 的站点运行它时。在浏览器中访问该站点可以正常工作。

当我手动运行 curl 时,我得到 gzipped 输出:

$ curl "http://example.com"

这是该特定网站的标题:

HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html; charset=utf-8
X-Powered-By: php/5.2.17
Last-Modified: Sat, 03 Dec 2011 00:07:57 GMT
ETag: "6c38e1154f32dbd9ba211db8ad189b27"
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Cache-Control: must-revalidate
Content-Encoding: gzip
Content-Length: 7796
Date: Sat, 03 Dec 2011 00:46:22 GMT
X-Varnish: 1509870407 1509810501
Age: 504
Via: 1.1 varnish
Connection: keep-alive
X-Cache-Svr: p2137050.pubip.peer1.net
X-Cache: HIT
X-Cache-Hits: 425

我知道返回的数据是 gzip 压缩的,因为这会返回 html,正如预期的那样:

$ curl "http://example.com" | gunzip

我不想通过 gunzip 管道输出,因为脚本在其他站点上按原样运行,而通过 gzip 管道会破坏该功能。

我尝试过的

    更改用户代理(我尝试了浏览器发送的相同字符串,“Mozilla/4.0”等) 男人卷曲 google search 搜索***

一切都是空的

有什么想法吗?

【问题讨论】:

对我来说,问题在于 cURL 无法解压缩 Brotli (curl 7.54.0 (x86_64-apple-darwin17.0) libcurl/7.54.0 LibreSSL/2.0.20 zlib/1.2.11 nghttp2/1.24.0) - 通过从 Accept-Encoding 中删除 br 解决了这个问题。见***.com/questions/18983719/… 这种行为据说已经改变了。单独尝试curl -sSv https://***.com/ |& rg -i 'gzip|accept'--compressed。除非curl 通过Accept-Encoding,否则服务器不会压缩响应。 【参考方案1】:

在相关的错误报告 Raw compressed output when not using --compressed but server returns gzip data #2836 中,开发人员说:

服务器不应发送 content-encoding: gzip 没有客户端发出信号表示可以接受。

此外,当您不使用 --compressed 和 curl 时,您会告诉命令行工具您宁愿存储确切的流(压缩与否)。我在这里没有看到 curl 错误...

因此,如果服务器可以发送 gzip 压缩的内容,请使用 --compressed 让 curl 自动解压缩。

【讨论】:

这并不总是合理或可能的。如果您不拥有的服务器配置不正确,您不太可能让他们修复它。防御性编码是解决这个问题的好方法。请参阅comment by George Lund 了解 Everything is Broken ™ 的另一个原因。【参考方案2】:

如果你设置了--compressed标志,curl会自动解压响应:

curl --compressed "http://example.com"

--压缩 (HTTP) 使用 libcurl 支持的算法之一请求压缩响应,并保存未压缩的文档。如果使用该选项,服务器发送不支持的编码,curl会报错。

gzip 很可能受支持,但您可以通过运行 curl -V 并在“功能”行中的某处查找 libz 来检查:

$ curl -V
...
Protocols: ...
Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz 

请注意,真正有问题的网站是这里的错误。如果curl 没有传递Accept-Encoding: gzip 请求标头,则服务器不应该发送压缩响应。

【讨论】:

这似乎是一个 curl 错误,因为它应该根据响应触发其解码,而不是根据它的请求(假设它确实支持 gzip)。引用 HTTP 1.1:“如果请求中不存在 Accept-Encoding 字段,则服务器可以假设客户端将接受任何内容编码。”但它确实继续说,在这种情况下,服务器不应该对内容进行编码,嗯,去看看。 实际上在我的版本上工作 --comp --compress --compressed 这也设置了请求头:“Accept-Encoding: deflate, gzip”这很好,因为如果服务器提供 gzip 而没有 gzip,你只需要 --compressed 而不是自己添加接受编码头 在 1 分钟内帮助我的 QA 解决方案!谢谢 !也就是说,我的应用程序实际上是使用 Content-Encoding: gzip 发送 gzip 响应。浏览器和现代工具(例如 httpie)会自动处理它。我猜 curl 只需要一个“提示” 令人惊讶的是,设置Accept-Encoding: deflate, gzip 是不够的——即使服务器返回带有Content-Encoding: gzip 的gzip 响应,curl 也不会自动解压缩它。 --compressed 标志是必需的。

以上是关于使用 curl 时如何正确处理压缩页面?的主要内容,如果未能解决你的问题,请参考以下文章

curl 库是不是在页面内执行 javascript?

PHP/Curl/Wordpress 在不刷新页面的情况下发布数据,curl 不起作用

PHP 用curl 如何跳转页面

cURL 使页面永远加载,然后网关超时

如何通过php的curl模拟ajax请求,获取其返回值

Gulp压缩jscssimghtml提高页面打开速度