网关请求拦截器
@Component
@Slf4j
public class MyFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("进入request拦截器**********");
ServerHttpRequest request = exchange.getRequest();
if (request.getMethod() != HttpMethod.POST) {
return chain.filter(exchange);
}
return operationExchange(exchange, chain);
}
private Mono<Void> operationExchange(ServerWebExchange exchange, GatewayFilterChain chain) {
// mediaType
MediaType mediaType = exchange.getRequest().getHeaders().getContentType();
// read & modify body
ServerRequest serverRequest = new DefaultServerRequest(exchange);
Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
.flatMap(body -> {
if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType)) {
log.info("********* request拦截器加密[前]的requsetBody "+body);
// 对原先的body进行修改操作
String newBody = Base64Utils.encode(body);
log.info("********* request拦截器加密[后]的requsetBody " +newBody);
return Mono.just(newBody);
}
return Mono.empty();
});
BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
HttpHeaders headers = new HttpHeaders();
headers.putAll(exchange.getRequest().getHeaders());
headers.remove(HttpHeaders.CONTENT_LENGTH);
MyCachedBodyOutputMessage outputMessage = new MyCachedBodyOutputMessage(exchange, headers);
return bodyInserter.insert(outputMessage, new BodyInserterContext())
.then(Mono.defer(() -> {
ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
exchange.getRequest()) {
@Override
public HttpHeaders getHeaders() {
long contentLength = headers.getContentLength();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(super.getHeaders());
if (contentLength > 0) {
httpHeaders.setContentLength(contentLength);
} else {
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
}
return httpHeaders;
}
@Override
public Flux<DataBuffer> getBody() {
return outputMessage.getBody();
}
};
return chain.filter(exchange.mutate().request(decorator).build());
}));
}
@Override
public int getOrder() {
return 1;
}
}
由于spring中的CachedBodyOutputMessage权限已改为private,因此需模仿写一个相似功能的MyCachedBodyOutputMessage类
public class MyCachedBodyOutputMessage implements ReactiveHttpOutputMessage {
private final DataBufferFactory bufferFactory;
private final HttpHeaders httpHeaders;
private Flux<DataBuffer> body = Flux.error(new IllegalStateException(
"The body is not set. " + "Did handling complete with success?"));
public MyCachedBodyOutputMessage(ServerWebExchange exchange, HttpHeaders httpHeaders) {
this.bufferFactory = exchange.getResponse().bufferFactory();
this.httpHeaders = httpHeaders;
}
@Override
public void beforeCommit(Supplier<? extends Mono<Void>> action) {
}
@Override
public boolean isCommitted() {
return false;
}
@Override
public HttpHeaders getHeaders() {
return this.httpHeaders;
}
@Override
public DataBufferFactory bufferFactory() {
return this.bufferFactory;
}
/**
* Return the request body, or an error stream if the body was never set or when.
* @return body as {@link Flux}
*/
public Flux<DataBuffer> getBody() {
return this.body;
}
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
this.body = Flux.from(body);
return Mono.empty();
}
@Override
public Mono<Void> writeAndFlushWith(
Publisher<? extends Publisher<? extends DataBuffer>> body) {
return writeWith(Flux.from(body).flatMap(p -> p));
}
@Override
public Mono<Void> setComplete() {
return writeWith(Flux.empty());
}
}
网关响应拦截器
public interface BodyHandlerFunction extends
BiFunction<ServerHttpResponse, Publisher<? extends DataBuffer>, Mono<Void>> {
}
public class BodyHandlerServerHttpResponseDecorator
extends ServerHttpResponseDecorator {
/**
* body 处理拦截器
*/
private BodyHandlerFunction bodyHandler = initDefaultBodyHandler();
/**
* 构造函数
*
* @param bodyHandler
* @param delegate
*/
public BodyHandlerServerHttpResponseDecorator(
BodyHandlerFunction bodyHandler, ServerHttpResponse delegate) {
super(delegate);
if (bodyHandler != null) {
this.bodyHandler = bodyHandler;
}
}
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
//body 拦截处理器处理响应
return bodyHandler.apply(getDelegate(), body);
}
@Override
public Mono<Void> writeAndFlushWith(
Publisher<? extends Publisher<? extends DataBuffer>> body) {
return writeWith(Flux.from(body).flatMapSequential(p -> p));
}
/**
* 默认body拦截处理器
*
* @return
*/
private BodyHandlerFunction initDefaultBodyHandler() {
return (resp, body) -> resp.writeWith(body);
}
}
@Configuration
@Slf4j
public class ResponseGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange,
GatewayFilterChain chain) {
log.info("进入response拦截器******");
ServerHttpRequest request = exchange.getRequest();
if (request.getMethod() != HttpMethod.POST) {
return chain.filter(exchange);
}
//构建响应拦截处理器
BodyHandlerFunction bodyHandler = (resp, body) -> Flux.from(body)
.map(dataBuffer -> {
//响应信息转换为字符串
String reqBody = null;
try {
//dataBuffer 转换为String
reqBody = IOUtils
.inputStreamAsString(dataBuffer.asInputStream(), "UTF-8")
.replaceAll(">\\s{1,}<", "><");
} catch (IOException e) {
e.printStackTrace();
}
return reqBody;
})
.flatMap(orgBody -> {
//根据原有的响应信息构建新响应信息并写入到resp中
//此处可以根据业务进行组装新的响应信息,
// 例如:登录后创建会话
//- 拿到登录请求的响应信息,判断登录是否成功
//- 登录成功调用创建会话接口,根据创建会话接口返回组装登录的真实响应
log.info("********* response拦截器解密[前]的responseBody "+orgBody);
String rbody = Base64Utils.decode(orgBody);
log.info("********* response拦截器解密[后]的responseBody "+rbody);
HttpHeaders headers = resp.getHeaders();
return resp.writeWith(Flux.just(rbody)
.map(bx -> resp.bufferFactory()
.wrap(bx.getBytes())));
}).then();
//构建响应包装类
BodyHandlerServerHttpResponseDecorator responseDecorator = new BodyHandlerServerHttpResponseDecorator(
bodyHandler, exchange.getResponse());
return chain
.filter(exchange.mutate().response(responseDecorator).build());
}
@Override
public int getOrder() {
//WRITE_RESPONSE_FILTER 之前执行
return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1;
}
}