当前位置: 首页 > news >正文

SpringCloud Gateway 网关的请求体body的读取和修改

SpringCloud Gateway 网关的请求体body的读取和修改

getway需要多次对body 进行操作,需要对body 进行缓存

缓存body 动态多次获取

新建顶层filter,对body 进行缓存


import lombok.extern.slf4j.Slf4j;
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.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBuffer;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;import java.util.List;/*** @author: zhoumo* @descriptions:*/
@Component
@Slf4j
public class RequestParamGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {/*** save request path and serviceId into gateway context*/ServerHttpRequest request = exchange.getRequest();HttpHeaders headers = request.getHeaders();// 处理参数MediaType contentType = headers.getContentType();long contentLength = headers.getContentLength();if (contentLength > 0) {return readBody(exchange, chain);}return chain.filter(exchange);}/*** default HttpMessageReader*/private static final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();/*** ReadJsonBody** @param exchange* @param chain* @return*/private Mono<Void> readBody(ServerWebExchange exchange, GatewayFilterChain chain) {/*** join the body*/return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> {byte[] bytes = new byte[dataBuffer.readableByteCount()];dataBuffer.read(bytes);DataBufferUtils.release(dataBuffer);Flux<DataBuffer> cachedFlux = Flux.defer(() -> {DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);DataBufferUtils.retain(buffer);return Mono.just(buffer);});/*** repackage ServerHttpRequest*/ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {@Overridepublic Flux<DataBuffer> getBody() {return cachedFlux;}};/*** mutate exchage with new ServerHttpRequest*/ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build();/*** read body string with default messageReaders*/return ServerRequest.create(mutatedExchange, messageReaders).bodyToMono(String.class).doOnNext(objectValue -> {log.debug("[GatewayContext]Read JsonBody:{}", objectValue);}).then(chain.filter(mutatedExchange));});}@Overridepublic int getOrder() {return HIGHEST_PRECEDENCE;}
}

在子节点层获取body

AtomicReference<String> requestBody = new AtomicReference<>("");RecorderServerHttpRequestDecorator requestDecorator = new RecorderServerHttpRequestDecorator(request);Flux<DataBuffer> body = requestDecorator.getBody();body.subscribe(buffer -> {CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());requestBody.set(charBuffer.toString());});String body= requestBody.get();

重写获取body方法

   public class RecorderServerHttpRequestDecorator  extends ServerHttpRequestDecorator {private final List<DataBuffer> dataBuffers = new ArrayList<>();public RecorderServerHttpRequestDecorator(ServerHttpRequest delegate) {super(delegate);super.getBody().map(dataBuffer -> {dataBuffers.add(dataBuffer);return dataBuffer;}).subscribe();}@Overridepublic Flux<DataBuffer> getBody() {return copy();}private Flux<DataBuffer> copy() {return Flux.fromIterable(dataBuffers).map(buf -> buf.factory().wrap(buf.asByteBuffer()));}}

对body 进行修改重新封装

                String str=""+encodedDecryptedParam;DataBuffer bodyDataBuffer = stringBuffer(str);Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);MediaType contentType = request.getHeaders().getContentType();ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {@Overridepublic HttpHeaders getHeaders() {HttpHeaders httpHeaders = new HttpHeaders();int length = str.getBytes().length;httpHeaders.putAll(super.getHeaders());httpHeaders.remove(HttpHeaders.CONTENT_TYPE);httpHeaders.remove(HttpHeaders.CONTENT_LENGTH);httpHeaders.setContentLength(length);httpHeaders.set(HttpHeaders.CONTENT_TYPE, contentType.toString());// 设置CONTENT_TYPEreturn httpHeaders;}@Overridepublic Flux<DataBuffer> getBody() {return bodyFlux;}};return chain.filter(exchange.mutate().request(mutatedRequest).build());
    protected DataBuffer stringBuffer(String value) {byte[] bytes = value.getBytes(StandardCharsets.UTF_8);NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);buffer.write(bytes);return buffer;}

一定必须加上 public HttpHeaders getHeaders()对header 重新封装,否则接口层会卡死,request 无限大

http://www.lryc.cn/news/216615.html

相关文章:

  • 气膜场馆的降噪方法
  • 探索主题建模:使用LDA分析文本主题
  • 服务器黑洞,如何秒解
  • 【生物信息学】单细胞RNA测序数据分析:计算亲和力矩阵(基于距离、皮尔逊相关系数)及绘制热图(Heatmap)
  • 学习笔记三十一:k8s安全管理:认证、授权、准入控制概述SA介绍
  • 【开发新的】apache common BeanUtils忽略null值
  • coalesce函数(SQL )
  • 一键报警可视对讲管理机10寸触摸屏管理机
  • java左右括号
  • 接口自动化测试 —— 工具、请求与响应
  • 【LeetCode:2103. 环和杆 | 模拟】
  • 微信小程序-授权登录(手机号码)
  • 视觉问答(VQA)12篇顶会精选论文合集,附常用数据集下载
  • 详解--编码(ASCII\Unicode,UTF-8\UTF-16\UTF-32)
  • Linux安装配置awscli命令行接口工具及其从aws上传下载数据
  • 中国联通携手华为助力长城精工启动商用5G-A柔性产线
  • 【自动化测试】Java+Selenium自动化测试环境搭建
  • 若依笔记(四):代码生成器
  • 怎样做好金融投资翻译
  • ubuntu 分区 方案
  • Python自动化测试面试题总结
  • 客户端性能测试基础知识
  • 多模态论文阅读之VLMo
  • 休闲类手游还有机会吗?两大策略收割全球玩家
  • Git复制代码
  • 数据结构笔记——查找、排序(王道408)
  • MySQL---搜索引擎
  • 2022最新版-李宏毅机器学习深度学习课程-P32 Transformer
  • 如何使用商品详情API接口获取商品数据:一篇详尽的论述
  • 华为:手机王者归来,汽车起死回生