当前位置: 首页 > 知识库问答 >
问题:

如何使用spring webflux读取请求体

戚宏浚
2023-03-14

我正在使用Spring5、Netty和Spring webflux开发和API网关。有时,我希望网关停止请求,但我也希望读取请求的主体以记录它,例如,并向客户机返回一个错误。

我尝试在WebFilter中通过订阅body来实现这一点。

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    if (enabled) {
        logger.debug("gateway is enabled. The Request is routed.");
        return chain.filter(exchange);
    } else {
        logger.debug("gateway is disabled. A 404 error is returned.");

        exchange.getRequest().getBody().subscribe();
        exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
        return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().allocateBuffer(0)));
    }
}

当我这样做的时候,它在身体的内容很少的时候起作用。但当我有一个大的身体时,只有第一个元素的通量被读取,所以我不能有整个身体。知道怎么做吗?

共有1个答案

宰父嘉胜
2023-03-14

这里的问题是您在筛选器中手动订阅,这意味着您将请求的读取与管道的其余部分断开。调用subscribe()将为您提供一个disposable,帮助您管理基础的订阅

因此您需要将整个过程转换为单个管道连接起来,有点像:

Flux<DataBuffer> requestBody = exchange.getRequest().getBody();
// decode the request body as a Mono or a Flux
Mono<String> decodedBody = decodeBody(requestBody); 
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
return decodedBody.doOnNext(s -> logger.info(s))
                  .then(exchange.getResponse().setComplete());

请注意,将整个请求主体解码为mono意味着网关必须将整个请求主体缓冲在内存中。

databuffer是一种低级别类型。如果希望将其解码(即实现示例DecodeBody方法)为字符串,则可以使用Spring中的各种Decoder实现之一,如StringDecoder

现在,由于这是一个相当大和复杂的空间,您可以使用和/或看一看Spring Cloud Gateway,它只做了这一点,而且做得更多。

 类似资料:
  • 问题内容: 我正在使用Java 7和。我想读取一个请求(例如),但如果它大于我正在使用的大小,则我正在努力想出一个很好的解决方案来读取完整的请求。例如,如果是4048字节,并且HTTP POST包含大于4kB的图像。 有没有很好的递归解决方案或循环呢? 这是我的阅读请求代码: 在我写过的地方: 它看起来像是代码重用的好地方,但是我无法提出一个好的解决方案。有什么办法可以在这里重用Completio

  • 我正在尝试从HTML中读取post请求参数。我可以使用以下JavaScript代码读取get请求参数。 但对post请求不起作用。有人能告诉我如何使用JavaScript读取HTML中的post请求参数值吗?

  • 问题内容: 我正在尝试从HTML中读取发布请求参数。我可以使用JavaScript中的以下代码读取get请求参数。 但这不适用于发布请求。谁能告诉我如何使用JavaScript读取HTML中的发布请求参数值? 问题答案: POST数据是在服务器端处理的数据 。Javascript位于客户端。因此,您无法使用JavaScript读取帖子数据。

  • 问题内容: 我需要能够 使用 OKHTTP* 来 管理 一些请求,使用来通过输入地址来接收一些预测。该 问题是 ,我插入每次 CHAR 它将使一个新的请求,但在同一时间,我需要取消前一个!例如:纽约市=同时请求13个!因此,我仅使用一个实例来尝试取消已请求但没有成功的任何内容。这就是我所做的! * 我检查对象是否为null并取消请求,但仍然不断! 问题答案: 关于以下内容:

  • 问题内容: 我有两个Python脚本。一种使用Urllib2库,另一种使用Requests库。 我发现请求更容易实现,但是找不到urlib2的等效函数。例如: 建立完发布网址后,请给我内容-我正尝试连接到vcloud Director api实例,并且响应显示了我有权访问的端点。但是,如果我按以下方式使用请求库.... .... the和不返回任何内容,即使请求后调用中的状态代码等于200。 为什

  • 那么,这种情况下有没有变通的办法呢?我是否应该使用简单的rest客户端,比如reverfit,或者在每个新请求上创建新的ApolloClient和OkHttpClient实例,并带有所需的头集?或者也许还有别的变通办法?