从 ServerHttpRequest / Flux<DataBuffer> 获取请求正文字符串

bha*_*ngh 8 java spring-cloud spring-cloud-gateway

我使用的是 spring boot 版本 - 2.0.6.RELEASE 和 spring cloud 版本 - Finchley.SR2

我已经创建了我的自定义网关过滤器来修改请求正文。

但是在使用 Flux 将请求正文转换为字符串时,我得到了一个空字符串。我需要一种方法来获取与我的请求正文对应的字符串。

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

}
Run Code Online (Sandbox Code Playgroud)

Fab*_*ian 6

您可以使用ModifyRequestBodyGatewayFilterFactory我相信它包含在 Spring Cloud Gateway 2.0.2 中,它是Finchley 的一部分。

例如:

@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);
    };
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这是Spring Cloud Gateway 2.2.5中的另一种方法,我们将使用ReadBodyPredicateFactory,因为这将使用属性键cachedRequestBodyObject将requestBody缓存到ServerWebExchange

创建始终为真的谓词

@Component
public class TestRequestBody implements Predicate
{
    @Override
    public boolean test(Object o)
    {
        return true;
    }
}

Run Code Online (Sandbox Code Playgroud)

在application.yml中,添加谓词

spring:
  cloud:
    gateway:
      routes:
       ....
          predicates:
            .....
            - name: ReadBodyPredicateFactory
              args:
                inClass: "#{T(String)}" 
                predicate: "#{@testRequestBody}"
Run Code Online (Sandbox Code Playgroud)

在您自己的过滤器中,获取 requestBody,如下所示:

    @Override
    public GatewayFilter apply(Object config)
    {
        return (exchange, chain) -> {

            String requestBody = exchange.getAttribute("cachedRequestBodyObject");

        };
    }
Run Code Online (Sandbox Code Playgroud)


jba*_*m17 3

一旦您读取(通过读取记录)请求正文,请求就会自行删除。spring cloud gateway需要记录请求体的内容,但是请求体只能读取一次。如果读取请求体后没有进行封装,后面的服务将无法读取到请求体数据。按照这个