Golang中能否读取带Transfer-Encoding=identity的HTTP响应?
解决Golang中处理Transfer-Encoding=identity响应的问题
问题原因
Golang官方net/http库的默认Transport会严格校验HTTP响应的Transfer-Encoding头部,仅支持chunked值,而AG服务返回了不符合标准的Transfer-Encoding=identity(HTTP/1.1中identity是默认传输编码,无需显式声明),导致连接中断报错。
直接解决方案:自定义Transport拦截并修改响应头部
通过自定义http.RoundTripper,在响应返回给上层代码前,移除或修改不合法的Transfer-Encoding头部,让net/http库能正常处理响应。
自定义Transport实现
import ( "net/http" ) type IdentityFixTransport struct { http.RoundTripper } func (t *IdentityFixTransport) RoundTrip(req *http.Request) (*http.Response, error) { resp, err := t.RoundTripper.RoundTrip(req) if err != nil { return resp, err } // 移除或替换不合法的Transfer-Encoding头部 if encodings := resp.Header["Transfer-Encoding"]; len(encodings) > 0 { var validEncodings []string for _, enc := range encodings { if enc != "identity" { validEncodings = append(validEncodings, enc) } } if len(validEncodings) == 0 { resp.Header.Del("Transfer-Encoding") } else { resp.Header["Transfer-Encoding"] = validEncodings } } return resp, nil }
使用自定义Transport发送请求
修改原有代码,创建带有自定义Transport的http.Client:
// 初始化自定义Transport,基于默认Transport transport := &IdentityFixTransport{ RoundTripper: http.DefaultTransport, } // 创建使用该Transport的Client client := &http.Client{ Transport: transport, } // 替换原有的http.Post为client.Post resp, err := client.Post(url, "application/json", bytes.NewBuffer(jsonData)) if err != nil { results <- err return } defer resp.Body.Close() // 后续逻辑保持不变 if resp.StatusCode >= 200 && resp.StatusCode < 300 { results <- nil } else { errMsg := fmt.Sprintf("Push profile to agent %s:%s failed, appname=%s, uuid=%s", ip, port, dto.AppName, dto.UUID) results <- fmt.Errorf(errMsg) }
原理说明
identity传输编码表示响应体未经过压缩或分块编码,和不设置Transfer-Encoding头部的效果一致。通过移除这个不合法的头部,net/http库会按照常规的方式读取响应体(根据Content-Length或者直接读取到连接结束),从而避免报错。
内容的提问来源于stack exchange,提问作者haojie zhang
相关产品推荐
相关产品推荐

