使用Lazarus解压gzip
背景 使用fphttpclient调用一个http接口,但接口返回的响应体是经gzip压缩过的。这本是一个很常用,也很基础的功能,不想却如历劫般充满磨难。 历劫 初劫 场景很常用,也很基础,本着能偷懒就偷懒的原则,向AI进行提问。 AI给出的答案是使用ZStream单元的Tdecompressionstream。但是,AI给的示例第二个传参的数据类型怎么和方法声明不一样?继续问AI,AI就道歉,再给示例。 本以为几轮勾通下来问题就解决了,不曾想,恶梦才刚刚开始。AI每次都先道歉,然后信誓旦旦的说这次肯定可以,结果每次都不行。到后来,AI一会说是版本问题,一会说是数据问题……其实那些问题一开始就是排除掉的,但AI就是死鸭子嘴硬,真是气得令人口吐芬芳。结果。到最后,这货果然开始摆烂、甩锅,说什么它只是个模型,反正它尽力了,它不知道,问他不如你自己去网上查靠谱……浪费一上午时间,结果就来个让自己去网上查,那要你AI有个卵用! 再劫 午饭后,换个方式,先让AI去官方的gitlab查下有没有相关bug,结果果然有!然后顺藤摸瓜再查下解决方案,但是没有查到明确的解决方式,反倒是AI又开始一本正经胡说八道了,一不小心,半下午又没了! 罢了,一直被这货瞎忽悠,还不如自己静下心来深入了解下。一番了解加测试后,发现是Tdecompressionstream并不能识别gzip的格式。 复劫 既然问题出在gzip的格式上,那就先简单了解下gzip格式吧,懒得自己去搜,又问了AI,这次倒是说得有模有样,而且和测试的数据也都对得上,于是就追问了下如何解决。结果,又不知不觉被这货一本正经胡说八道忽悠瘸了,等发觉时已经深夜了。 劫中劫 官方的不能直接用,那就自己写个能用的。Tdecompressionstream是基于zlib的,而且有现成的底层功能可调用,那就仿一个支持gzip的,思路也很简单:把gzip的特征剥离后,剩下的就是原始的deflate,这个zlib肯定是支持的。 历经磨难,终于还是没写出能用的,看来一知半解就去搞还是行不通的,总不能像当初搞sm3、sm4那样对着规范研究几天再说吧! 劫散 对啊!虽说当初确实研究了好几天规范,但最终的实现还是参考了现成的c代码,fpc是小众中的小众,但c却是软件世界的基石啊,写pascal的话AI会一本正经胡说八道,那写c应该就只是代码搬运了吧。 让AI给了基于zlib的解压gzip的示例,自己对照着翻译成pascal,结果果然成功了! 仅是解压http的响应,够用了: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 uses ZBase, PasZLib; function GZipDecompression(Input, Output: TStream): boolean; var z: z_stream; ret: integer; inBuf, outBuf: TBytes; n: uint64; offset: integer; xlen: uint16; begin Result := False; //数据太短 if Input....