[英]How to get Original response body in Spring cloud gateway (Webflux) Post filter
I've implemented a Post filter in the spring cloud gateway.我已经在 spring 云网关中实现了一个 Post 过滤器。 But I need the readable format (JSON Format of response body) before sending it to UI.但在将其发送到 UI 之前,我需要可读格式(响应正文的 JSON 格式)。 I'm getting exchange.getResponse().我得到了 exchange.getResponse()。 (when i printed in console: org.springframework.http.server.reactive.ReactorServerHttpResponse@3891d61a
) But it is in the reactive object. (当我在控制台中打印时: org.springframework.http.server.reactive.ReactorServerHttpResponse@3891d61a
)但它在反应对象中。 I can't able to see the actual original response which is coming from API to post filter.我无法看到来自 API 到后过滤器的实际原始响应。 I've searched numerous stackoverflow topics but couldn't get an actual solution.我搜索了许多 stackoverflow 主题,但找不到实际的解决方案。 Please assist...请协助...
you can extract/read/modify/manipulate the request and response and their headers with the help of ServerHttpRequestDecorator
& ServerHttpResponseDecorator
see below您可以在ServerHttpRequestDecorator
和ServerHttpResponseDecorator
的帮助下提取/读取/修改/操作请求和响应及其标头,见下文
Note: i implemented GatewayFilter because i have this logic in gateway service level, if you want to modify at micro service level you can use WebFilter注意:我实现了 GatewayFilter因为我在网关服务级别有这个逻辑,如果你想在微服务级别进行修改,你可以使用WebFilter
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.IOUtils;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DefaultDataBuffer;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import java.io.ByteArrayOutputStream;
import java.nio.channels.Channels;
import java.nio.charset.StandardCharsets;
@Configuration
@Log4j2
public class RequestResponseModifyFilter implements GatewayFilter/WebFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path = exchange.getRequest().getPath().toString();
ServerHttpResponse response = exchange.getResponse();
ServerHttpRequest request = exchange.getRequest();
DataBufferFactory dataBufferFactory = response.bufferFactory();
// log the request body
ServerHttpRequest decoratedRequest = getDecoratedRequest(request);
// log the response body
ServerHttpResponseDecorator decoratedResponse = getDecoratedResponse(path, response, request, dataBufferFactory);
return chain.filter(exchange.mutate().request(decoratedRequest).response(decoratedResponse).build());
}
private ServerHttpResponseDecorator getDecoratedResponse(String path, ServerHttpResponse response, ServerHttpRequest request, DataBufferFactory dataBufferFactory) {
return new ServerHttpResponseDecorator(response) {
@Override
public Mono<Void> writeWith(final Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
DefaultDataBuffer joinedBuffers = new DefaultDataBufferFactory().join(dataBuffers);
byte[] content = new byte[joinedBuffers.readableByteCount()];
joinedBuffers.read(content);
String responseBody = new String(content, StandardCharsets.UTF_8);//MODIFY RESPONSE and Return the Modified response
log.debug("requestId: {}, method: {}, url: {}, \nresponse body :{}", request.getId(), request.getMethodValue(), request.getURI(), responseBody);
return dataBufferFactory.wrap(responseBody.getBytes());
})).onErrorResume(err -> {
log.error("error while decorating Response: {}",err.getMessage());
return Mono.empty();
});
}
return super.writeWith(body);
}
};
}
private ServerHttpRequest getDecoratedRequest(ServerHttpRequest request) {
return new ServerHttpRequestDecorator(request) {
@Override
public Flux<DataBuffer> getBody() {
log.debug("requestId: {}, method: {} , url: {}", request.getId(), request.getMethodValue(), request.getURI());
return super.getBody().publishOn(Schedulers.boundedElastic()).doOnNext(dataBuffer -> {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
Channels.newChannel(byteArrayOutputStream).write(dataBuffer.asByteBuffer().asReadOnlyBuffer());
String requestBody = IOUtils.toString(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8.toString());//MODIFY REQUEST and Return the Modified request
log.debug("for requestId: {}, request body :{}", request.getId(), requestBody);
} catch (Exception e) {
log.error(e.getMessage());
}
});
}
};
}
@Override
public int getOrder() { return -2;}
}
https://github.com/einsteinarbert/spring-webfux-response-logging注意安全链,也许那个过滤器会覆盖你的过滤器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.