Envoy External Processing Filter修改请求体时Content-Length Header丢失问题求助
问题分析
你遇到的这个情况其实是Envoy的默认行为:当你通过External Processing Filter修改请求体后,Envoy会自动将请求切换为分块传输编码(Chunked Transfer Encoding)。在这种编码方式下,HTTP协议本身就不需要Content-Length头——因为数据是分块发送的,每块都会携带自己的长度标识。所以即使你在HeaderMutation里手动设置了Content-Length,Envoy也会直接忽略并移除它。
解决方案
要解决这个问题,核心是让Envoy在修改请求体后仍然使用Content-Length而不是分块编码,你可以从以下几个方向入手:
1. Envoy配置层面:强制禁用分块编码
在Envoy的http_connection_manager配置中,添加强制设置Content-Length的参数,同时确保上游集群配置不允许分块编码:
# http_connection_manager 部分配置 http_connection_manager: codec_type: HTTP1 always_set_content_length: true override_stream_error_on_invalid_http_message: true # 其他已有配置... # 上游集群部分配置 clusters: - name: your_upstream_cluster http_protocol_options: allow_chunked_length: false # 其他已有配置...
always_set_content_length: true会让Envoy尽可能使用Content-Length头替代分块编码,而allow_chunked_length: false则限制上游集群不接受分块编码的请求。
2. 代码层面:同步处理请求头与请求体
修改请求体的同时,除了设置Content-Length,还要主动移除Transfer-Encoding: chunked头(HTTP规范中这两个头不能同时存在),确保上游服务只收到Content-Length:
bytesToSend := b.RequestBody.Body resp = &pb.ProcessingResponse{ Response: &pb.ProcessingResponse_RequestBody{ RequestBody: &pb.BodyResponse{ Response: &pb.CommonResponse{ HeaderMutation: &pb.HeaderMutation{ SetHeaders: []*core.HeaderValueOption{ { Header: &core.HeaderValue{ Key: "Content-Length", Value: strconv.Itoa(len(bytesToSend)), }, }, }, // 移除分块编码头 RemoveHeaders: []string{"Transfer-Encoding"}, }, BodyMutation: &pb.BodyMutation{ Mutation: &pb.BodyMutation_Body{ Body: bytesToSend, }, }, }, }, }, ModeOverride: &v3.ProcessingMode{ ResponseHeaderMode: v3.ProcessingMode_SEND, ResponseBodyMode: v3.ProcessingMode_NONE, }, }
3. 额外检查:上游服务兼容性
如果上述调整后仍有问题,建议确认上游服务是否严格遵循HTTP规范:有些老旧服务可能对Content-Length的大小写(比如要求全小写content-length)、数值格式有特殊要求,不过Envoy默认会标准化头名,这个概率较低。也可以开启Envoy的trace级别日志,查看请求头的具体处理流程,定位是否有其他配置覆盖了你的头修改操作。
备注:内容来源于stack exchange,提问作者Gabriele Cerfoglio

