Only one connection receive subscriber allowed.
这个filter 中报Only one connection receive subscriber allowed.
主要是body体为null的情况
@Component
public class DecryptionFilter implements GlobalFilter, Ordered {
@SneakyThrows
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
解决办法:
参考:https://blog.csdn.net/weixin_37644979/article/details/115264027
完全代码:
package com.riocento.filter;import com.alibaba.fastjson.JSONObject;
import io.netty.buffer.ByteBufAllocator;import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.CoreSubscriber;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Iterator;/*** 解密过滤器* 对请求的request进行解密*/
@Slf4j
@Component
public class DecryptionFilter implements GlobalFilter, Ordered {@SneakyThrows@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("request解密处理");//源request对象ServerHttpRequest request = exchange.getRequest();//获取请求方式HttpMethod method = request.getMethod();URI uri = request.getURI();log.info("请求方式:"+method);log.info("请求地址:"+uri);MultiValueMap<String, String> queryParams = request.getQueryParams();log.info("所有参数:"+queryParams);//是否为加密参数Boolean isEncrypt = false;// GET请求解密if(HttpMethod.GET == method){if(queryParams.containsKey("isEncrypt")){isEncrypt = Boolean.valueOf(queryParams.get("isEncrypt").get(0));}if(isEncrypt){//加密参数String enParams = queryParams.get("enParams").get(0);//将参数解密String paramsStr = AESUtil.decrypt(enParams);//格式化参数String urlParams = formatUrlParams(paramsStr);//重新创建requestURI plaintUrl = new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), urlParams, uri.getFragment());ServerHttpRequest newRequest = request.mutate().uri(plaintUrl).build();return chain.filter(exchange.mutate().request(newRequest).build());}}//POST和PUT请求解密else if(HttpMethod.POST == method|| HttpMethod.PUT == method) {if(queryParams.containsKey("isEncrypt")){isEncrypt = Boolean.valueOf(queryParams.get("isEncrypt").get(0));}if(isEncrypt){URI plaintUrl = null;//处理url参数if(queryParams.size() > 0 && queryParams.containsKey("enParams")){//加密参数String urlEnParams = queryParams.get("enParams").get(0);//将参数解密String urlParamsStr = AESUtil.decrypt(urlEnParams);//格式化参数String urlParams = formatUrlParams(urlParamsStr);//重新创建uriplaintUrl = new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), urlParams, uri.getFragment());}else{plaintUrl = uri;}//处理表单参数//获取表单信息Flux<DataBuffer> dataBufferFlux = request.getBody();//获取body中的数据String strBody = FilterRequestResponseUtil.resolveBodyFromRequest(dataBufferFlux);//获取加密参数String enParams = getEnParams(strBody);//将参数解密String paramsStr = AESUtil.decrypt(enParams);ServerHttpRequest newRequest = request.mutate().uri(plaintUrl).build();DataBuffer bodyDataBuffer = stringBuffer(paramsStr);if(paramsStr == null) {newRequest = new ServerHttpRequestDecorator(newRequest) {@Overridepublic Flux<DataBuffer> getBody() {return Flux.just(bodyDataBuffer);}};// 构建新的请求头HttpHeaders headers = new HttpHeaders();headers.putAll(exchange.getRequest().getHeaders());// 重新设置CONTENT_LENGTHint length = 0;headers.remove(HttpHeaders.CONTENT_LENGTH);headers.setContentLength(length);newRequest = new ServerHttpRequestDecorator(newRequest) {@Overridepublic HttpHeaders getHeaders() {return headers;}};return chain.filter(exchange.mutate().request(newRequest).build());}Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);newRequest = new ServerHttpRequestDecorator(newRequest) {@Overridepublic Flux<DataBuffer> getBody() {return bodyFlux;}};// 构建新的请求头HttpHeaders headers = new HttpHeaders();headers.putAll(exchange.getRequest().getHeaders());// 重新设置CONTENT_LENGTHint length = paramsStr.getBytes().length;headers.remove(HttpHeaders.CONTENT_LENGTH);headers.setContentLength(length);newRequest = new ServerHttpRequestDecorator(newRequest) {@Overridepublic HttpHeaders getHeaders() {return headers;}};return chain.filter(exchange.mutate().request(newRequest).build());}}//DELETE等请求方式不做处理return chain.filter(exchange);}@Overridepublic int getOrder() {return 0;}/*** 格式化url参数* @param paramsStr 字符串参数*/private String formatUrlParams(String paramsStr){StringBuilder stbResult = new StringBuilder();if(Strings.isNotEmpty(paramsStr)){if(paramsStr.startsWith("{")){JSONObject paramsJSON = JSONObject.parseObject(paramsStr);Iterator<String> iterator = paramsJSON.keySet().iterator();while (iterator.hasNext()) {String key = iterator.next();String value = paramsJSON.getString(key);if(stbResult.length() > 0){stbResult.append("&");}stbResult.append(key).append("=").append(value);}}else{stbResult.append(paramsStr);}}return stbResult.toString();}/*** 获取加密字符串参数* @return*/private String getEnParams(String paramsStr){String result = null;if(Strings.isNotEmpty(paramsStr)){if(paramsStr.startsWith("{")){//将字符串转换为JSON格式JSONObject jsonBody = JSONObject.parseObject(paramsStr);result = jsonBody.getString("enParams");}else if(paramsStr.indexOf("=") > 0){String[] paramsArr = paramsStr.split("=");result = paramsArr[1];}}return result;}private DataBuffer stringBuffer(String value) {if(value == null) {NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(0);return buffer;}byte[] bytes = value.getBytes(StandardCharsets.UTF_8);NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);buffer.write(bytes);return buffer;}
}
Only one connection receive subscriber allowed.相关推荐
- spring cloud gateway Unhandled failure: Only one connection receive subscriber allowed.
https://gist.github.com/WeirdBob/b25569d461f0f54444d2c0eab51f3c48 ToUppercaseGlobalFilter.java https ...
- Spring Cloud Gateway 之获取请求体的几种方式
一.直接在全局拦截器中获取 伪代码如下 private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest){Flux& ...
- spring cloud gateway - 日志
spring cloud gateway - 日志 实现日志 前提:spring cloud gateway是基于webflux的项目,所以不能像使用spring mvc一样直接获取request b ...
- SpringCloud Gateway获取post请求体(request body)
获取spring cloud gateway POST请求体的时候,会有很多坑,网上大多数解决方案是 /** 这种方法在spring-boot-starter-parent 2.0.6.RELEASE ...
- quartz异常:Couldn't rollback jdbc connection
为什么80%的码农都做不了架构师?>>> 最近工作发现,有个项目偶尔会报Couldn't rollback jdbc connection. No operations all ...
- python2.0_s12_day10_rabbitMQ使用介绍
RabbitMQ RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列(M ...
- Python-day-9- RabbitMQ队列
RabbitMQ队列 安装 http://www.rabbitmq.com/install-standalone-mac.html 安装python rabbitMQ module pip insta ...
- Day10-Python3基础-协程、异步IO、redis缓存、rabbitMQ队列
内容目录: Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko S ...
- Python学习笔记day10
Twsited异步网络框架 twisted是一个用python语言写的事件驱动的网络框架,他支持很多种协议,包括UDP,TCP,TLS和其他应用层协议,比如HTTP,SMTP,NNTM,IRC,XMP ...
- java disconnect_Java BlockingConnection.disconnect方法代碼示例
本文整理匯總了Java中org.fusesource.mqtt.client.BlockingConnection.disconnect方法的典型用法代碼示例.如果您正苦於以下問題:Java Bloc ...
最新文章
- C语言解析pcap文件得到HTTP信息实例(原创,附源码)
- 深入浅出计算机组成原理学习笔记:高速缓存(下)-你确定你的数据更新了么?(第38讲)...
- python 字符串split 正则分割 换行符_python数据分析实战-JOINamp;SPLIT分割与合并
- matlab用dft对连续信号做谱分析,用 DFT 对连续信号进行谱分析的误差问题有哪些?...
- 聚类算法分析及其性能比较
- 华为荣耀手机指令代码大全_2020.10月《各价位华为、荣耀手机推荐》
- Webshell实现与隐藏探究
- 微信小程序云函数 -- 腾讯云通用印刷体识别应用
- 电商产品经理:如何搭建会员管理体系(多图干货)
- godspeed机器人_cs1.6kz地图包下载
- Python】Scrapy抓取多玩Gif图片
- (转)男人的梦想之野性篇 什么是真正的越野车
- 使用SINet进行伪装目标检测
- HQChart--uniApp v3 中使用 render.js
- 软路由-Hi-Spider Router-海蜘蛛
- Teams认证话机系列(2)--AudioCodes C450HD
- 在美面试红宝书:美国MBA毕业生就业面经
- CSS3蒙版 Mask
- SSM项目实战-新闻发布系统
- 爬虫入门------从数据看奥斯卡陪跑健将到底是谁?学院派评委都热衷于哪类电影?
热门文章
- Python中的f字符串的用法
- VMware vCenter vShield配置vxlan时候vib未安装
- 联盟链系列 - 中间CA颁发证书
- wamp5数据库密码修改
- LC.1175. Prime Arrangements
- 【定制项目】【M13】【数据监控 + 数据分析 + 可视化大屏】- 关键技术 python flask + pandas + echarts + excel
- 利用FME(myfme)将MAPGIS格式的土地处用现状图完美转换为CAD
- 1487C - Minimum Ties
- 在linux系统下ping不通windows主机问题
- 公众号内测算法推荐引争议,却有小号因此阅读增长20倍