C语言实现HTTP服务器对gzip压缩的支持

发布时间 2023-11-06 07:56:59作者: shijianyujingshen

最近实现一个Prometheus的exporter需要支持HTTP gzip压缩,起初直接用zlib库,发现Prometheus读到被压缩时的数据时会报错,同时Chrome浏览器直接访问exporter的HTTP端口也无法正常显示页面,而IE浏览器可以。基于这些奇怪的现象不得不对HTTP如何支持gzip进行了一番探索:

在HTTP协议中描述了对数据压缩的支持:

gzip

表示采用 Lempel-Ziv coding(LZ77)压缩算法,以及 32 位 CRC 校验的编码方式。这个编码方式最初由 UNIX 平台上的 gzip 程序采用。出于兼容性的考虑,HTTP/1.1 标准提议支持这种编码方式的服务器应该识别作为别名的 x-gzip 指令。

compress

采用 Lempel-Ziv-Welch(LZW)压缩算法。这个名称来自 UNIX 系统的 compress 程序,该程序实现了前述算法。与其同名程序已经在大部分 UNIX 发行版中消失一样,这种内容编码方式已经被大部分浏览器弃用,部分因为专利问题(这项专利在 2003 年到期)。

deflate

采用 zlib 结构(在 RFC 1950 中规定),和 deflate 压缩算法(在 RFC 1951 中规定)。

br

表示采用 Brotli 算法的编码方式。

可见zlib实现的是deflate算法,严格来说与gzip的LZ77是不同的。

LZ77算法在wiki中有详细的描述:LZ77 and LZ78

github上有很多对LZ77算法和其变种(改进版本)的实现。显然Prometheus能支持的gzip并不是各种改进版本。这里有一个Prometheus可以支持的gzip实现:https://github.com/ebiggers/libdeflate

libdeflate编译默认会生成.so和.a,非常方便作为第三方库集成。

最后,在HTTP中调用libdeflate库接口来支持gzip压缩的伪代码如下:

comp = libdeflate_alloc_compressor(level)//1 = fastest, 6 = medium/default, 9 = slow, 12 = slowest

len = libdeflate_gzip_compress(comp, in_data, in_len, out_buf, buf_len);

libdeflate_free_compressor(comp);