C语言实现HTTP服务器对gzip压缩的支持
最近实现一个Prometheus的exporter需要支持HTTP gzip压缩,起初直接用zlib库,发现Prometheus读到被压缩时的数据时会报错,同时Chrome浏览器直接访问exporter的HTTP端口也无法正常显示页面,而IE浏览器可以。基于这些奇怪的现象不得不对HTTP如何支持gzip进行了一番探索:
在HTTP协议中描述了对数据压缩的支持:
表示采用 Lempel-Ziv coding(LZ77)压缩算法,以及 32 位 CRC 校验的编码方式。这个编码方式最初由 UNIX 平台上的 gzip 程序采用。出于兼容性的考虑,HTTP/1.1 标准提议支持这种编码方式的服务器应该识别作为别名的
x-gzip
指令。采用 Lempel-Ziv-Welch(LZW)压缩算法。这个名称来自 UNIX 系统的 compress 程序,该程序实现了前述算法。与其同名程序已经在大部分 UNIX 发行版中消失一样,这种内容编码方式已经被大部分浏览器弃用,部分因为专利问题(这项专利在 2003 年到期)。
采用 zlib 结构(在 RFC 1950 中规定),和 deflate 压缩算法(在 RFC 1951 中规定)。
表示采用 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);