Many friends may have encountered the following problems when using SpringCloudGateway
How to read Post request body in SpringCloudGateway
private BodyInserter getBodyInserter(ServerWebExchange exchange) {
ServerRequest serverRequest = new DefaultServerRequest(exchange);
Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
.flatMap(body -> {
//这里的body就是Post的请求体
});
BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
return bodyInserter;
}
Post request parameters in SpringCloudGateway can only be read once
This is because the Gateway uses Spring Webflux by default. To solve this problem, it is necessary to reconstruct a request to replace the original request.
HttpHeaders headers=new HttpHeaders();
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
ServerHttpRequestDecorator decorator = this.getServerHttpRequestDecorator(exchange,outputMessage);
ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return outputMessage.getBody();
}
};
When the ServerHttpRequestDecorator is constructed, the following method needs to be used in the interceptor to replace the original request
return chain.filter(exchange.mutate().request(decorator).build());
How to read the return data of the back-end service in SpringCloudGateway
Consistent with the idea of replacing the request above, just replace the response
private ServerHttpResponse getServerHttpResponse(ServerWebExchange exchange) {
ServerHttpResponse originalResponse = exchange.getResponse();
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
Flux<DataBuffer> flux = null;
if (body instanceof Mono) {
Mono<? extends DataBuffer> mono = (Mono<? extends DataBuffer>) body;
body = mono.flux();
}
if (body instanceof Flux) {
flux = (Flux<DataBuffer>) body;
return super.writeWith(flux.buffer().map(dataBuffers -> {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
dataBuffers.forEach(i -> {
byte[] array = new byte[i.readableByteCount()];
i.read(array);
DataBufferUtils.release(i);
outputStream.write(array, 0, array.length);
});
String result = outputStream.toString();
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
log.info("后端返回数据:{}", result);
return bufferFactory.wrap(result.getBytes());
}));
}
log.info("降级处理返回数据:{}" + body);
return super.writeWith(body);
}
};
return decoratedResponse;
}
The above is to get a new response. After getting the new response, it is the same as the previous routine, so do this:
return chain.filter(exchange.mutate().request(decorator).response(decoratedResponse).build());
Some students may encounter that even if the response is rewritten according to the above method, the returned data cannot be read. The reason may be that there is a problem with the priority configuration of the interceptor. It is only necessary to implement the Ordered interface and rewrite the getOrder method. , and then set the priority to less than -1
@Override
public int getOrder() {
return -2;
}