spring-cloud-gateway修改request param与body

2022-07-03 12:45:38

spring-cloud-gateway修改request param与body

前言:最近遇到一个新需求,就是需要给全局的请求做一个参数解密,包括request param与body中的参数。

分解下来可以分为三步:实现全局拦截请求、修改request param、修改request body。

一、Global Filter

在spring-cloud-gateway中我们要实现全局拦截,可以实现GlobalFilter,通过实现Order来控制filter的执行顺序,代码如下:

    @Component
    @Slf4j
    public class ModificationGatewayFilter implements GlobalFilter, Ordered {
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            //修改 request param
            ServerWebExchange newExchange = modificationRequestParam(exchange);
    
            MediaType mediaType = newExchange.getRequest().getHeaders().getContentType();
            //仅解密 json body,如果要修改类型body传参,可以不作限制
            if (mediaType != null && mediaType.includes(MediaType.APPLICATION_JSON)) {
                //修改reuest body
                return getModificationBodyMono(chain, newExchange);
            }
    
    
            return chain.filter(newExchange);
        }
        
         @Override
         public int getOrder() {
                return -99;
         }

二、修改reuqest param

通过ServerWebExchange modificationRequestParam(ServerWebExchange exchange)修改request param。

private ServerWebExchange modificationRequestParam(ServerWebExchange exchange) {
        //获取uri对象
        URI uri = exchange.getRequest().getURI();
        StringBuilder query = new StringBuilder();
        //获取 url上的参数
        String originalQuery = uri.getRawQuery();
        //如果有参数才进行修改
        if (StringUtils.isNotBlank(originalQuery)) {
            //修改 url上的参数。这里可以自定义修改
            originalQuery = modificationStr(originalQuery);
            //todo 拿到新构建的参数创建一个新的URI对象
            URI newUri = UriComponentsBuilder.fromUri(uri).replaceQuery(query.toString()).build(true).toUri();
            //用新的URI 创建新的 ServerHttpRequest
            ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri).build();
            //返回新构建的 exchange
            return exchange.mutate().request(request).build();
            
        }
        return exchange;
    }

三、修改request body

通过Mono getModificationBodyMono(GatewayFilterChain chain, ServerWebExchange newExchange)修改body

 private Mono getModificationBodyMono(GatewayFilterChain chain, ServerWebExchange newExchange) {
        ServerRequest serverRequest = ServerRequest.create(newExchange, HandlerStrategies.withDefaults().messageReaders());
        //修改body
        Mono modifiedBody = serverRequest.bodyToMono(String.class).flatMap(oldBody -> {
            String newBody;
       
            //todo 这里做修改body的操作
            newBody = modificationBody(oldBody);
            return Mono.just(newBody);
        });
        BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
        
        HttpHeaders headers = new HttpHeaders();
        headers.putAll(newExchange.getRequest().getHeaders());
        //如果body长度有变化,那么就需要修改Content-Length,否则可能会报错
        //这里为了省事直接删除
        headers.remove("Content-Length");
        //MyCachedBodyOutputMessage 这个类完全就是CachedBodyOutputMessage,只不过CachedBodyOutputMessage不是公共的
        CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(newExchange, headers);
        
        return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> {
            ServerHttpRequest decorator = this.decorate(newExchange, headers, outputMessage);
            return returnMono(chain, newExchange.mutate().request(decorator).build());
        }));
    }

如有问题欢迎指正,已试验成功了。

  • 作者:初心常驻
  • 原文链接:https://blog.csdn.net/qq_40778639/article/details/123640651
    更新时间:2022-07-03 12:45:38