问题
I am using spring boot version - 2.0.6.RELEASE and spring cloud version - Finchley.SR2
and i have created my custom gateway filter to modify the request body.
but while converting the request body to string using Flux i am getting a empty string. i need a method to get the string corresponding to my request body.
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = (ServerHttpRequest) exchange.getRequest();
String s = resolveBodyFromRequest(request);
/* s comes out to be "" */
return chain.filter(newExchange);
}
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest){
//Get the request body
Flux<DataBuffer> body = serverHttpRequest.getBody();
StringBuilder sb = new StringBuilder();
body.subscribe(buffer -> {
byte[] bytes = new byte[buffer.readableByteCount()];
buffer.read(bytes);
DataBufferUtils.release(buffer);
String bodyString = new String(bytes, StandardCharsets.UTF_8);
sb.append(bodyString);
});
return sb.toString();
}
回答1:
You could use the ModifyRequestBodyGatewayFilterFactory which I believe is included in Spring Cloud Gateway 2.0.2 which is part of Finchley.
For Ex:
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ModifyRequestBodyGatewayFilterFactory.Config modifyRequestConfig = new ModifyRequestBodyGatewayFilterFactory.Config()
.setContentType(ContentType.APPLICATION_JSON.getMimeType())
.setRewriteFunction(String.class, String.class, (exchange1, originalRequestBody) -> {
String modifiedRequestBody = yourMethodToModifyRequestBody(originalRequestBody);
return Mono.just(modifiedRequestBody);
});
return new ModifyRequestBodyGatewayFilterFactory().apply(modifyRequestConfig).filter(exchange, chain);
};
}
回答2:
This is another approach work in spring cloud gateway 2.2.5, we will use ReadBodyPredicateFactory, as this will cache requestBody to ServerWebExchange with attribute key cachedRequestBodyObject
create always true Predicate
@Component
public class TestRequestBody implements Predicate
{
@Override
public boolean test(Object o)
{
return true;
}
}
in application.yml, add Predicate
spring:
cloud:
gateway:
routes:
....
predicates:
.....
- name: ReadBodyPredicateFactory
args:
inClass: "#{T(String)}"
predicate: "#{@testRequestBody}"
in your own filter, get requestBody like below:
@Override
public GatewayFilter apply(Object config)
{
return (exchange, chain) -> {
String requestBody = exchange.getAttribute("cachedRequestBodyObject");
};
}
回答3:
once you read(log by reading) the request body, request drops there itself. spring cloud gateway needs to record the contents of the request body, but the request body can only be read once. If the request body is not encapsulated after reading it , the latter service will not be able to read the body data. follow this
回答4:
Refinement of @tony.hokan answer https://stackoverflow.com/a/64080867/1484823 using spring cloud gateway rewrite body request to save the request body (and possibly response body) as an attribute of the org.springframework.web.server.ServerWebExchange
@Bean
public RouteLocator myRouteSavingRequestBody(RouteLocatorBuilder builder) {
return builder.routes()
.route("my-route-id",
p -> p
.path("/v2/**") //your own path filter
.filters(f -> f
.modifyResponseBody(String.class, String.class,
(webExchange, originalBody) -> {
if (originalBody != null) {
webExchange.getAttributes().put("cachedResponseBodyObject", originalBody);
return Mono.just(originalBody);
} else {
return Mono.empty();
}
})
.modifyRequestBody(String.class, String.class,
(webExchange, originalBody) -> {
if (originalBody != null) {
webExchange.getAttributes().put("cachedRequestBodyObject", originalBody);
return Mono.just(originalBody);
} else {
return Mono.empty();
}
})
)
.uri("https://myuri.org")
)
.build();
}
in your own filter, get requestBody like below:
@Override
public GatewayFilter apply(Object config)
{
return (exchange, chain) -> {
String requestBody = exchange.getAttribute("cachedRequestBodyObject");
};
}
来源:https://stackoverflow.com/questions/57562873/get-request-body-string-from-serverhttprequest-fluxdatabuffer