Spring Cloud Gateway在有些场景中需要获取request body内容进行参数校验或参数修改,我们通过在GatewayFilter中获取请求内容来获取和修改请求体,下面我们就基于ServerWebExchange来实现:
ServerWebExchange命名为服务网络交换器,存放着重要的请求-响应属性、请求实例和响应实例等等,有点像Context的角色,其中有两个重要的接口方法:
// 获取ServerHttpRequest对象
ServerHttpRequest getRequest();
// 获取ServerHttpResponse对象
ServerHttpResponse getResponse();
创建一个GatewayFilter,必须实现Ordered接口,返回一个小于-1的order值,这是因为NettyWriteResponseFilter的order值为-1,我们需要覆盖返回响应体的逻辑,自定义的GlobalFilter必须比NettyWriteResponseFilter优先执行。
public class RequestGatewayFilter implements GatewayFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
HttpHeaders headers = request.getHeaders();
// 处理参数
MediaType contentType = headers.getContentType();
if (exchange.getRequest().getMethod().equals(HttpMethod.POST)) {
//Content-type为“application/json”
if (MediaType.APPLICATION_JSON.isCompatibleWith(contentType)) {
return readBody(exchange, chain);
}
//Content-type为“application/x-www-form-urlencoded”
else if(MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)){
GatewayContext gatewayContext = new GatewayContext();
gatewayContext.setRequestHeaders(headers);
gatewayContext.getAllRequestData().addAll(request.getQueryParams());
exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT,gatewayContext);
return readFormData(exchange, chain, gatewayContext);
}
//Content-type为“multipart/form-data”
else if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)) {
GatewayContext gatewayContext = new GatewayContext();
gatewayContext.setRequestHeaders(headers);
gatewayContext.getAllRequestData().addAll(request.getQueryParams());
exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT,gatewayContext);
return readMultipartData(exchange, chain, gatewayContext);
}
} else {
return readGetData(exchange, chain);
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -2;
}
}
处理content-type为application/json的方法:
/**
* ReadJsonBody
*
* @param exchange
* @param chain
* @return
*/
private Mono<Void> readBody(ServerWebExchange exchange, GatewayFilterChain chain) {
/**
* join the body
*/
return DataBufferUtils.join(exchange.getRequest().getBody(