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());
}));
}
如有问题欢迎指正,已试验成功了。