Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get request body string from ServerHttpRequest / Flux<DataBuffer>

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();

}
like image 688
bhavishya singh Avatar asked Aug 19 '19 19:08

bhavishya singh


2 Answers

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);
    };
}
like image 111
Fabian Avatar answered Sep 22 '22 12:09

Fabian


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");

        };
    }
like image 27
tony.hokan Avatar answered Sep 24 '22 12:09

tony.hokan