curl / libcurl 中的 CURLOPT_ACCEPT_ENCODING:HTTP 压缩响应自动解压完全指南
发布时间:2026/9/10 16:44:25来源:尧图网络
curl / libcurl 中的 CURLOPT_ACCEPT_ENCODINGHTTP 压缩响应自动解压完全指南【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl导读CURLOPT_ACCEPT_ENCODING是 libcurl 提供的 HTTP 内容协商选项它既能控制请求中Accept-Encoding:头的内容又能在收到带Content-Encoding:的压缩响应时自动解压。本文以 docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.md 为主体结合本仓库lib/setopt.c、lib/http.c、lib/content_encoding.c等源码讲解该选项的取值规则、各编码支持范围、与CURLOPT_HTTPHEADER的差异、编译期依赖以及解压带来的安全与资源注意事项帮助你在自己的程序中安全、高效地启用 HTTP 压缩传输。选项概览功能、原型与适用协议选项名称CURLOPT_ACCEPT_ENCODING所属函数curl_easy_setopt(3)详见 libcurl 选项手册适用协议HTTP含 HTTPS加入版本7.21.6此前名为CURLOPT_ENCODING默认值NULL即默认不发送Accept-Encoding:头也不自动解压标准调用原型#include curl/curl.h CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ACCEPT_ENCODING, char *enc);传入的是一个指向字符串的char *其作用体现在两个方向请求方向设置 HTTP 请求中Accept-Encoding:头的内容响应方向当收到带Content-Encoding:头的响应时自动对下载内容进行解压。也就是说该选项同时完成了声明我支持什么编码和收到的压缩内容我自己解两件事。取值规则NULL、空串与编码列表NULL显式关闭将CURLOPT_ACCEPT_ENCODING设为NULL会显式关闭该功能libcurl 不发送Accept-Encoding:头同时忽略响应中收到的Content-Encoding:头不自动解压。这是选项的默认状态DEFAULT为NULL。在源码 lib/setopt.c 中可以看到该分支的实现逻辑当传入非空字符串时走Curl_setstropt(data, STRING_ENCODING, ptr)将字符串存入 easy handle 的STRING_ENCODING槽位传入NULL时该槽位被清空。空字符串 : 启用全部内建编码libcurl 允许传入零长度字符串此时会自动生成一个包含当前构建所有内建支持编码的Accept-Encoding:头。这样应用无需关心某个特定 libcurl 构建到底支持哪些算法直接全要。/* 启用当前构建支持的所有压缩编码 */ curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, );其内部实现位于 lib/setopt.c当ptr非空但*ptr \0时调用Curl_get_content_encodings()动态生成编码列表再存入选项槽。Curl_get_content_encodings()的实现位于 lib/content_encoding.c它遍历general_unencoders[]数组见 lib/content_encoding.c把每个已编译进去的编码器名字用, 连接成逗号分隔列表。general_unencoders[]的内容受编译宏控制static const struct Curl_cwtype * const general_unencoders[] { identity_encoding, #ifdef HAVE_LIBZ deflate_encoding, gzip_encoding, #endif #ifdef HAVE_BROTLI brotli_encoding, #endif #ifdef HAVE_ZSTD zstd_encoding, #endif NULL };从源码结构可以推断若一个构建只启用了 zlib则空串展开后的头会是类似Accept-Encoding: deflate, gzip的内容若同时启用了 brotli 与 zstd则会追加br、zstd。显式编码列表精确控制也可以明确指定想要的编码多个编码用逗号分隔/* 只接受这几种编码 */ curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, br, gzip, deflate);文档列出的受支持编码及其含义编码名称含义引入版本identity不压缩原样传输一直支持deflate服务器用 zlib 算法压缩对应 HTTP 的 deflate一直支持需 zlibgzip服务器用 gzip 算法压缩一直支持需 zlibbrBrotli 压缩curl 7.57.0 起需 brotli 库zstdZstandard 压缩curl 7.72.0 起需 zstd 库注意deflate、gzip、br、zstd是否真正可用取决于构建时是否链接了对应压缩库详见下文编译期依赖。重复设置后者覆盖前者对同一 handle 多次设置该选项时最后一次设置的字符串覆盖之前的设置传入NULL即回到关闭状态。应用不需要在设置之后保留这个字符串libcurl 会自行拷贝管理。请求方向Accept-Encoding:头如何生成当选项被设置后libcurl 在构造 HTTP/1.x 请求头时会生成对应的头行。相关代码位于 lib/http.ccase H1_HD_ACCEPT_ENCODING: { const char *enc CURL_EASY_STR(data, STRING_ENCODING); if(enc !Curl_checkheaders(data, STRCONST(Accept-Encoding))) result curlx_dyn_addf(req, Accept-Encoding: %s\r\n, enc); break; }这里有两点值得注意头冲突保护Curl_checkheaders()会先检查应用是否已经通过CURLOPT_HTTPHEADER手动设置过Accept-Encoding:头若已手动设置则这里不会重复生成避免出现两个同名头。这是请求而非命令文档明确强调该选项是向服务器请求压缩服务器可能不压缩也可能使用与请求不同的编码还可能根本没收到Accept-Encoding:头就自行压缩响应。响应方向Content-Encoding:的自动解压机制收到响应时libcurl 根据Content-Encoding:头解析编码列表并构建一个解压写入链cwriter stack。核心实现在 lib/content_encoding.c 的Curl_build_unencoding_stack()按逗号分隔解析Content-Encoding:中的每个编码名通过find_unencode_writer()在general_unencoders[]中查找匹配的解码器identity是原样透传见 lib/content_encoding.c每个编码对应一个Curl_cwriter写入器按顺序压栈数据经过各层解码器后才交给应用的回调若某个编码在当前构建中不支持cwt NULL会挂上一个error_writer延迟报错——也就是说服务器返回了未构建支持的编码时请求会以错误告终栈深度受MAX_ENCODE_STACK限制超过上限会返回CURLE_BAD_CONTENT_ENCODING防止恶意构造的多重编码攻击相关宏定义可查 lib/content_encoding.h。与命令行动态--compressed参见 docs/cmdline-opts/compressed.md一致若服务器返回了本构建不支持的编码libcurl 会报告错误。与 CURLOPT_HTTPHEADER 的差异手动设头不自动解压文档特别指出也可以用CURLOPT_HTTPHEADER自行加入Accept-Encoding:头但此时不会自动解压收到的压缩内容。两种方式的区别总结设置方式发送Accept-Encoding:自动解压响应CURLOPT_ACCEPT_ENCODING任意非 NULL 值是除非已手动设头是CURLOPT_HTTPHEADER手动设Accept-Encoding:是需自行维护否两者都不设置默认NULL否否因此若你手动设置了Accept-Encoding:头、又希望自动解压需要让两者配合使用只手动设头而不设置本选项收到的将是压缩后的原始字节流。相关选项可参考 CURLOPT_HTTPHEADER、CURLOPT_HTTP_CONTENT_DECODING 与 CURLOPT_TRANSFER_ENCODING。编译期依赖哪些编码真正可用自动解压并非无条件的具体取决于 libcurl 构建时链接的压缩库参见 DEPENDENCIES 文档 与构建脚本中的探测模块如 CMake/FindBrotli.cmake、CMake/FindZstd.cmakegzip / deflate必须启用 zlib源码中以HAVE_LIBZ宏控制见 lib/content_encoding.cbrBrotli必须链接 brotli 库HAVE_BROTLI见 lib/content_encoding.czstd必须链接 zstd 库HAVE_ZSTD见 lib/content_encoding.c。若构建缺少对应库而服务器恰好返回了该编码libcurl 会按上文所述以错误终止本次传输。这也是空串全要的便捷之处libcurl 只会声明构建内真正支持的编码。注意点与安全警告Content-Length 可能不匹配对于压缩响应服务器发送的Content-Length:应当表示压缩后内容的长度开启自动解压后应用通过写回调write callback收到的字节数是解压后的字节数二者通常不一致不少服务器还会错误地发送未压缩内容的长度。因此在计算下载进度或做校验时不能假设两者相等。解压膨胀decompression blowup风险WARNING解压数据时即使很小的传输也可能被膨胀为巨大的字节流源码中 brotli、zstd 等解码器都带有CURL_CW_FLAG_BLOWUP标记如 lib/content_encoding.c 的zstd_encoding。文档建议只对已知且可信的站点、通过安全协议如 HTTPS启用自动解压配合 CURLOPT_MAXFILESIZE_LARGE 设置最大文件大小限制防止解压炸弹导致的内存/磁盘消耗失控。完整示例#include stdio.h #include curl/curl.h /* 将下载内容写入 stdout 的简单回调 */ static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) { (void)userdata; return fwrite(ptr, size, nmemb, stdout); } int main(void) { CURL *curl curl_easy_init(); if(curl) { CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, https://example.com); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* 启用当前构建支持的所有内建压缩编码并自动解压 */ curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ); /* 可选限制最大下载大小缓解解压膨胀风险 */ curl_off_t maxsize 100 * 1024 * 1024; /* 100 MiB */ curl_easy_setopt(curl, CURLOPT_MAXFILESIZE_LARGE, maxsize); result curl_easy_perform(curl); if(result ! CURLE_OK) fprintf(stderr, curl_easy_perform() failed: %s\n, curl_easy_strerror(result)); curl_easy_cleanup(curl); } return 0; }对应的命令行等价物是curl --compressed URL其完整语义可查阅 docs/cmdline-opts/compressed.md。返回值与错误处理curl_easy_setopt()返回CURLcodeCURLE_OK (0)表示设置成功非零表示出错具体错误码见 libcurl-errors。若内存不足例如空串展开编码列表失败可能返回CURLE_OUT_OF_MEMORY参见 lib/setopt.c传输阶段若遇到无法解码的编码或编码栈超限则可能返回CURLE_BAD_CONTENT_ENCODING。版本历史7.21.6引入CURLOPT_ACCEPT_ENCODING此前名为CURLOPT_ENCODING7.57.0支持brBrotli7.72.0支持zstd。小结CURLOPT_ACCEPT_ENCODING让 libcurl 应用用一行代码同时完成请求压缩与自动解压两件事。使用时注意三点空串自动启用全部内建编码、NULL完全关闭、显式列表精确控制若需要服务器压缩但希望自行处理原始字节流则改用CURLOPT_HTTPHEADER手动设置Accept-Encoding:头此时无自动解压同时在面向不可信来源时务必配合CURLOPT_MAXFILESIZE_LARGE限制解压膨胀。【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网