.Net5 API网关中间件无法正确读取Response.Body内容问题咨询
问题原因
- 核心诱因:你的请求头携带
Accept-Encoding: gzip标识,下游服务返回的响应体为gzip压缩后的二进制数据,直接读取压缩流转换为字符串会出现乱码。 - 其他可能:若响应采用非UTF-8编码,StreamReader默认使用UTF-8解码也会出现乱码,你的场景优先排查压缩问题。
解决方案
方案1:移除压缩请求头(推荐,性能损耗最小)
在中间件调用后续管道前,移除请求的Accept-Encoding头,让下游服务返回未压缩的明文响应:
// 放在 await _next.Invoke(context); 之前执行 context.Request.Headers.Remove("Accept-Encoding");
如果需要给客户端返回压缩响应,可在网关的日志中间件之后,单独注册全局压缩中间件即可,不影响日志读取。
方案2:保留压缩逻辑,读取后解压
若必须透传压缩请求头给下游,需在读取响应时先根据Content-Encoding头判断压缩格式,解压后再转字符串:
using System.IO.Compression; using System.Text; // ... 其他原有逻辑 string responseBody = string.Empty; var originalBodyStream = context.Response.Body; using (var responseStream = new MemoryStream()) { context.Response.Body = responseStream; await _next.Invoke(context); context.Response.Body.Seek(0, SeekOrigin.Begin); if (context.Response.Headers.TryGetValue("Content-Encoding", out var encodingVal) && encodingVal.Contains("gzip")) { // 处理gzip压缩响应 using var decompressStream = new GZipStream(context.Response.Body, CompressionMode.Decompress); using var reader = new StreamReader(decompressStream, Encoding.UTF8); responseBody = await reader.ReadToEndAsync(); } else { // 未压缩响应直接读取 using var reader = new StreamReader(context.Response.Body, Encoding.UTF8); responseBody = await reader.ReadToEndAsync(); } context.Response.Body.Seek(0, SeekOrigin.Begin); await responseStream.CopyToAsync(originalBodyStream); }
若存在br等其他压缩格式,对应增加BrotliStream解压逻辑即可,处理逻辑与gzip一致。
内容的提问来源于stack exchange,提问作者Aristopher S
相关产品推荐
相关产品推荐

