公司做免费网站建设,大型网站制作小程序,怎么把图片做成链接形式,沧州网站建设专业定制基于公司的业务需求#xff0c;在SpringCloud Gateway组件的基础上#xff0c;写了一个转发服务#xff0c;测试开发阶段运行正常#xff0c;并实现初步使用。但三个月后#xff0c;PostMan请求接口#xff0c;返回异常#xff0c;经排查#xff0c;从日志中获取到转发… 基于公司的业务需求在SpringCloud Gateway组件的基础上写了一个转发服务测试开发阶段运行正常并实现初步使用。但三个月后PostMan请求接口返回异常经排查从日志中获取到转发响应的结果为乱码 跟踪日志 转发到目标接口响应结果已乱码。一般排查的思路是查看请求方和响应方的编码格式是否一致打印请求方的编码格式为UTF-8,响应服务的编码格式也是UTF-8。 以上说明编码格式没有问题。上网去找“gateway响应结果乱码”的相关文章大多数会提供解决方案
DataBufferFactory dataBufferFactory new DefaultDataBufferFactory();
DataBuffer join dataBufferFactory.join(dataBuffers);
byte[] content new byte[join.readableByteCount()];
join.read(content);
// 释放掉内存
DataBufferUtils.release(join);
String str new String(content, Charset.forName(UTF-8));
originalResponse.getHeaders().setContentLength(str.getBytes().length);
System.out.println(str);
return bufferFactory.wrap(str.getBytes());这段关键代码在我的响应结果包装过滤器是有的如下 /*** 获取到解码方的response,验签---重新封装---加签* 通过 DataBufferFactory 解决响应体分段传输问题。*/private ServerHttpResponseDecorator verifyRePackageSignatureResponse(ServerWebExchange exchange, String jmf_decode_url, String route_privateKey, String jmf_publicKey) {ServerHttpResponse response exchange.getResponse();log.debug(R:给响应结果response设置编码格式----START----);response.getHeaders().add(Content-Type,application/json;charsetUTF-8);log.debug(R:给响应结果response设置编码格式-----END-----);DataBufferFactory bufferFactory response.bufferFactory();return new ServerHttpResponseDecorator(response) {Overridepublic MonoVoid writeWith(Publisher? extends DataBuffer body) {if (body instanceof Flux) {// 获取响应类型如果是 json 就打印String originalResponseContentType exchange.getAttribute(ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);log.debug(响应类型为originalResponseContentType:{},originalResponseContentType);if (RequestResponseUtil.isJson(originalResponseContentType)) {Flux? extends DataBuffer fluxBody Flux.from(body);return super.writeWith(fluxBody.buffer().map(dataBuffers - {// 合并多个流集合解决返回体分段传输DataBufferFactory dataBufferFactory new DefaultDataBufferFactory();DataBuffer join dataBufferFactory.join(dataBuffers);byte[] content new byte[join.readableByteCount()];join.read(content);// 释放掉内存DataBufferUtils.release(join);// 正常返回的数据String rootData new String(content, StandardCharsets.UTF_8);log.debug(R:正常返回的数据rootData为:{}, rootData);//使用枚举 工厂 策略模式第二版String newQqtBodyJson null;try {newQqtBodyJson DecoderSignStrategyContext.zwmVerifySignResponse(rootData, jmf_decode_url, route_privateKey, jmf_publicKey);log.debug(R:【码路由服务】经具体策略处理得到结果newQqtBodyJson为:{}, newQqtBodyJson);} catch (Exception e) {log.error(R:【码路由服务】解码方返回结果验签异常:{}, e);throw new VerifySignException(StaticVar.FAIL_10020015, R:【码路由服务】解码方返回结果验签异常);}byte[] respData newQqtBodyJson.getBytes();//byte[] respData newQqtBodyJson.getBytes(StandardCharsets.UTF_8);byte[] uppedContent new String(respData, Charset.forName(UTF-8)).getBytes();return bufferFactory.wrap(uppedContent);}));} else {log.error(响应结果异常);throw new ProcessHandleException(StaticVar.FAIL_10020015, R:【码路由服务】解码方返回结果异常,非法JSON);}}// if body is not a flux. never got there.return super.writeWith(body);}};}
因此不是代码的问题。又找到了一篇文章解决了PostMan请求的问题。
https://bbs.csdn.net/topics/399102026/close 如上所述在PostMan请求的headers中去掉Accept-Encoding,请求成功 至此PostMan请求乱码的问题已解决。但事情似乎没有那么简单接下来使用手机模拟扫码请求码路由服务又出现了乱码扫码结果页面返回结果: 查看日志乱码如下 排查问题进入瓶颈期有些烦躁了必须冷静下来重新捋一下代码同时也在想既然和PostMan请求存在同样的问题是不是在请求头中默认会有一个Accept-Encoding属性从而导致了乱码根据这个思路在自定义的请求转发过滤器中发现了以下代码 由于在请求转发的逻辑中重新构建了一个request请求的同时重新创建了一个请求头headers,它在重新构建的时候默认会有一个accept-encoding属性看到这一行代码时正印证了以上我的猜想问题已经找到了将其置为空字符串即可注意不能使其为null,也不能remove这个属性会报错。 将headers的accept-encoding属性置为空字符串并添加注释如下
// 定义新的消息头HttpHeaders headers new HttpHeaders();//System.out.println(headers headers); //查看重新定义消息头的内容headers.putAll(exchange.getRequest().getHeaders());// 由于修改了传递参数需要重新设置CONTENT_LENGTH长度是字节长度不是字符串长度int length bodyStr.getBytes().length;log.debug(bodyStr长度为:{},length);headers.remove(HttpHeaders.CONTENT_LENGTH);// 设置CONTENT_TYPEif (StringUtils.isNotBlank(contentType)) {headers.set(HttpHeaders.CONTENT_TYPE, contentType);}String jmf_decode_url request.getURI().toString();String qqtBodyJsonStr JSONUtils.toString(bizPackage);//request.mutate().header(HttpHeaders.CONTENT_LENGTH, Integer.toString(bodyStr.length())); //报错JSON parse error JsonEOFException长度必须为字节的长度request.mutate().header(HttpHeaders.CONTENT_LENGTH, Integer.toString(length));//成功解决JSON parse error JsonEOFException/*** 乱码现象请求响应结果乱码* 解决过程分为PostMan请求和手机端App扫码请求* 1、PostMan请求响应乱码解决* PostMan请求的headers中默认会有Accept-Encoding属性值为gzip, deflate, br,导致响应结果乱码* 去掉Accept-Encoding后请求正常。** 2、手机端App扫码请求乱码解决* 在HttpRequestSignForwardGatewayFilter中定义新的消息头headers中默认会有accept-encoding属性* 值为gzip, deflate, br, 添加代码request.mutate().header(accept-encoding,); 解决乱码** 注意: 创建headers对象默认会生成“accept-encoding‘gzip, deflate, br‘ ”属性此处必须将accept-encoding* 置为空字符串置为null会报错否则使用默认值会导致响应结果乱码。* 说明: 测试开发阶段未发生此问题第三方检测时演示出现此问题这个可能是gateway内部的问题尚未可知。** 经测试这种方式已解决了手机端APP扫码和PostMan响应结果乱码的问题PostMan请求时可以不用刻意去掉Accept-Encoding* 也可请求成功**/request.mutate().header(accept-encoding,);
重启后部署后问题得到解决。这个问题在测试开发阶段没有暴露出来按理说应该早暴露了但现实情况就是这么诡异这可能是Gateway内部的bug尚未可知。 希望此文对遇到同样问题的小伙伴有所帮助和启发望了解gateway内部原理机制的大神参与讨论。 乱码问题已排查并处理结束完结撒花
参考文章
RestTemplate请求头accept-encoding导致乱码_resttemplate 乱码_AE86Jag的博客-CSDN博客
https://bbs.csdn.net/topics/399102026/close
在此感谢文章作者