分享一个以前CDN遇到的问题,有个客户自己写了个golang程序,下载CDN域名的文件出现问题,具体就是下载到本地的文件用不了,MD5也不正常。

问题排查了很久都没发现什么问题,查看CDN的日志也没发现啥异常,然后找到我这边,让我协助一起排查,然而我根本不懂开发,golang程序看不懂。

我向客户要了那个文件的URL,使用curl命令进行测试,令人惊喜的是curl下载的文件是正常的,到这里我从初步判断是golang程序有问题。

随后我咨询客户能不能提供golang程序,我主要是想在自己的Linux服务器上尝试看看,客户很配合把程序给了我,郁闷的是在我的服务器上测试也有问题。

非常疑惑,为什么golang程序下载的文件有问题,而curl下载的文件却正常的?

临时抱佛脚,使用tcpdump抓包试试能不能找到蛛丝马迹,没想到的是,还真被我找到了问题所在,最终完美解决。

具体原因:cdn 域名启用了智能压缩功能,指定 Content-Type 的文件会被压缩再响应给客户端,恰好 golang 的 "net/http" 包,在发起 http 请求时,默认就会构建一个 Accept-Encoding: gzip 头部,这样客户端拿到的文件就是压缩后的,文件有问题也正常。

最后让客户重新改代码,将 Accept-Encoding 头部去掉或者改为 Accept-Encoding: identity。

golang net/http
curl

第一张图片是golang net/http包发起的http请求,默认就有Accept-Encoding: gzip。

第二张图片是curl命令发起的http请求,没有Accept-Encoding头部。

服务器传过来的文件如果是被压缩了,响应头部中是没有Content-Length头部的,而是变成了Transfer-Encoding,这是因为压缩后的文件不好统计字节数。

关于这点,希望程序员在码字的时候要注意下,有的时候是不能用Content-Length来判断文件长度的。

如果不抓包真的很难发现这些问题。