天道酬勤,学无止境

Spring-webflux filter to fetch the request body

I need to fetch the entire request body in filter and convert it into String. Below is my code but nothing is getting printed on console.

@Component
public class WebFilter01 implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange serverWebExchange, 
      WebFilterChain webFilterChain) {    

        Flux<DataBuffer> requestBody = serverWebExchange.getRequest().getBody();        

        Flux<String> decodedRequest = requestBody.map(databuffer -> {
            return decodeDataBuffer(databuffer);
        });     
        decodedRequest.doOnNext(s -> System.out.print(s));
        return webFilterChain.filter(serverWebExchange);
    }


    protected String decodeDataBuffer(DataBuffer dataBuffer) {
        Charset charset = StandardCharsets.UTF_8;       
        CharBuffer charBuffer = charset.decode(dataBuffer.asByteBuffer());      
        DataBufferUtils.release(dataBuffer);        
        String value = charBuffer.toString();
        return value;
    }
}

评论

Nothing is getting printed on console because you did not subscribe to decodedRequest , as we know one of the Reactive aspect:

Nothing happens until you subscribe

But if you do that you will see printed body on console but your code will not work, because the next operators cannot read the body and you will get IllegalStateException(Only one connection receive subscriber allowed.)

So, how to resolve it?

  1. Create your own wrapper for ServerWebExchange (please read about this here: How to log request and response bodies in Spring WebFlux)
  2. Log bodies in HttpMessageDecoder. If you see, for instance, AbstractJackson2Decoder you will found code where Spring decode you buffer to object and can log it:
try {
    Object value = reader.readValue(tokenBuffer.asParser(getObjectMapper()));
    if (!Hints.isLoggingSuppressed(hints)) {
        LogFormatUtils.traceDebug(logger, traceOn -> {
            String formatted = LogFormatUtils.formatValue(value, !traceOn);
            return Hints.getLogPrefix(hints) + "Decoded [" + formatted + "]";
        });
    }
    return value;
}

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 在 spring-webflux 中处理错误的正确方法是什么(what is the right way to handle errors in spring-webflux)
    问题 我一直在使用 spring-webflux 进行一些研究,我想了解使用路由器功能处理错误的正确方法应该是什么。 我创建了一个小项目来测试几个场景,我喜欢得到关于它的反馈,看看其他人在做什么。 到目前为止,我所做的是。 给出以下路由功能: @Component public class HelloRouter { @Bean RouterFunction<?> helloRouterFunction() { HelloHandler handler = new HelloHandler(); ErrorHandler error = new ErrorHandler(); return nest(path("/hello"), nest(accept(APPLICATION_JSON), route(GET("/"), handler::defaultHello) .andRoute(POST("/"), handler::postHello) .andRoute(GET("/{name}"), handler::getHello) )).andOther(route(RequestPredicates.all(), error::notFound)); } } 我已经在我的处理程序上这样做了 class HelloHandler { private ErrorHandler
  • what is the right way to handle errors in spring-webflux
    I've been doing some research using spring-webflux and I like to understand what should be the right way to handle errors using Router Functions. I've created an small project to test a couple of scenarios, and I like to get feedback about it, and see what other people is doing. So far what I doing is. Giving the following routing function: @Component public class HelloRouter { @Bean RouterFunction<?> helloRouterFunction() { HelloHandler handler = new HelloHandler(); ErrorHandler error = new ErrorHandler(); return nest(path("/hello"), nest(accept(APPLICATION_JSON), route(GET("/"), handler
  • How can I send POST request with zip body using WebClient reactive web client
    How to POST a request with ZIP (compressed data) body using WebClient reactive web Client. I created a zip in memory (bytearrayoutputstream) and want to send the zip data in a POST request body using WebClient reactive web Client. The REST API is a PdfReactor REST WebService. The Response is a binary data (pdf). When I debug my Code I get the following error: Pooled connection observed an error org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/octet-stream' not supported for bodyType=java.io.ByteArrayInputStream at org.springframework.web
  • spring-webflux如何获取当前请求的上下文(How to get the context of the current request in spring-webflux)
    问题 在经典的 spring-mvc 中,可以在RequestContextHolder上设置请求范围的属性。 在此基础上,我们可以在HandlerInterceptorAdapter解析传入的请求,设置请求参数,例如当前登录的用户、唯一请求 ID(用于日志关联)等。 在请求的生命周期内,可以从任何服务(不仅是控制器)静态检索这些请求属性。 我正在尝试使用 spring-webflux 实现类似的功能。 我可以使用WebFilter来拦截所有传入的请求,获取当前的ServerWebExchange并在其上设置属性。 但是,除了控制器方法之外,我没有看到任何方法可以在其他任何地方获取当前请求的ServerWebExchange 。 我正在寻找比传递ServerWebExchange (或ServerHttpRequest )更好的解决方案。 这似乎在 webflux 中很难实现,因为我们不能依赖于在 ThreadLocal 上保存与特定请求相关的变量(因为非阻塞架构,单个线程可以在请求中切换)。 尽管如此,这是一个重要的要求。 也许有不同的方法? 回答1 您描述的方法是当前支持的方法。 正如您所强调的,对ThreadLocals使用静态方法是不可能的。 Reactor 正在寻找具有新上下文功能的替代方案(请参阅此 PR)。 Spring 可能会选择并使用它,但不一定用于请求属性
  • How to get the context of the current request in spring-webflux
    In the classic spring-mvc it is possible to set request scoped attributes on a RequestContextHolder. Building on that, we can parse an incoming request in a HandlerInterceptorAdapter, set request parameters such as currently logged in user, unique request ID (for log correlation) and so on. These request attributes can be retrieved statically from any service (not only controllers) during the request's lifetime. I am trying to achieve something similar with spring-webflux. I could use a WebFilter to intercept all incoming requests, get the current ServerWebExchange and set attributes on it
  • Spring-Webflux:从 Mono 中提取对象而不使用 block()(Spring-Webflux: Extracting Object from Mono without block())
    问题 我是新的 Spring Webflux。 我正在编写一个简单的 api,它调用另一个 api 并返回响应。 我遇到的问题是我的 api 接受的请求类型与外部 api 不同。我必须将传入的请求转换为发送到外部 api。我正在使用 Mono 来接收对我的 api 的请求,但是在没有的情况下无法转换为另一个对象堵塞()。 输入 路由器 @Configuration @EnableWebFlux public class RouterConfig implements WebFluxConfigurer{ @Bean public RouterFunction<ServerResponse> routes(UserHandler handler){ return RouterFunctions .route(POST("/rest/create"), handler::createUser); } } 处理程序 @Component public class UserHandler { private UserService service; public UserHandler(UserService service) { this.service = service; } public Mono<ServerResponse> saveUser(ServerRequest
  • zuul与spring-cloud-gateway的区别
    zuul与spring-cloud-gateway的区别 在了解zuul与spring-cloud-gateway的却别之前我们先来了解一下API网关。 API网关 API网关的定义:网关的角色是作为一个API架构,用来保护、增强和控制对于API服务的访问。它出于应用程序或服务之前的系统。可以屏蔽对于内部服务的直接调用,是用来管理授权、访问控制和流量限制等。API网关是程序的基础性设施功能。 API网关的职能: ①请求接入:作为所有API接口服务请求的接入点 ②业务整合:是所有后端业务的聚合点 ③中介策略:实现验证、过滤、路由、流量控制和安全等策略 ④统一管理:对所有API和策略进行统一管理 API网关分为流量网关和业务网关。 Spring-cloud-gateway Spring-cloud-gateway是Spring-Cloud生态中的网关,是基于Spring-boot开发的网关。其目的是替代Zuul,它提供了网关的基本功能实现,并且提供了统一的路由管理。 gateway中的基本构建 1、Route(路由):这是网关的基本模块。由ID和目标URL,一组断言(Predicate)和一组过滤器(Filter)定义。如果断言为真,则路由匹配。 2、Predicate(断言/谓言):输入类型是一个ServerWebExchange。可以使用它来匹配来自HTTP请求的任何内容。
  • How to correctly use slf4j MDC in spring-webflux WebFilter
    I referenced with the blog post Contextual Logging with Reactor Context and MDC but I don't know how to access reactor context in WebFilter. @Component public class RequestIdFilter implements WebFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { List<String> myHeader = exchange.getRequest().getHeaders().get("X-My-Header"); if (myHeader != null && !myHeader.isEmpty()) { MDC.put("myHeader", myHeader.get(0)); } return chain.filter(exchange); } }
  • Spring-Webflux: Extracting Object from Mono without block()
    I am new Spring Webflux. I am writing a simple api which call another api and returns response. The problem I have is my api takes diffrent type of request than the external api.I have to convert the incoming request to send to external api.I am using Mono to receive request for my api, but having trouble to convert to another object without block(). Input Router @Configuration @EnableWebFlux public class RouterConfig implements WebFluxConfigurer{ @Bean public RouterFunction<ServerResponse> routes(UserHandler handler){ return RouterFunctions .route(POST("/rest/create"), handler::createUser); }
  • Reactive Spring does not support ServerHttpRequest as parameter in REST endpoint tests?
    The question is very similar to this one. Except the fact that I use: org.springframework.http.server.ServerHttpRequest not HttpServletRequest. The exception is got in test code. Real calls works. Code: @RunWith(SpringRunner.class) @SpringBootTest(classes = SecurityTests.SecurityTestsApplication.class) @TestPropertySource(properties = {""}) @AutoConfigureWebTestClient public class SecurityTests { @Test public void myTest() { //send request to myUrl and got 500 } } @RestController @RequestMapping("/myPath") public class MyController { @PostMapping public Mono<Void> myMethod(ServerHttpRequest
  • Spring WebFlux - Content type 'application/xml' not supported for bodyType=org.springframework.web.multipart.MultipartFile
    I am using spring-webflux and want to upload files .... everything works great with just spring-web but when it comes to webflux i have not a clue what's wrong . Be careful in the difference ... i am using : <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> So let's say we have the below @RestController , for Spring Web it works like charm: @PostMapping(value = "/uploadFile") public Response uploadFile(@RequestParam("file") MultipartFile file) { } Now trying the same with Spring-webflux produces the below error : {
  • Correct way to get response body of XHR requests generated by a page with RStudio Chromote
    I'd like to use Chromote to gather the response body of the XHR calls made by a website, but I find the API a bit complex to master, especially the async pipeline. I guess I need to first enable the Network functionality and then load the page (this can do), but then I need to: list all XHR calls filter them by recognizing patterns in the request URL access the request body of the selected sources Can someone provide any guidance or tutorial material on this regard? UPDATE: Ok, I switched to package crrri and made a general function for the purpose. The only missing part is some logic to
  • Zuul和GateWay区别
    Zuul的作用 过滤请求、对过滤器进行动态的加载、编译、运行 验证与安全:识别面向各类资源的验证要求并拒绝那些与要求不符的请求。 审查与监控:在边缘位置追踪有意义数据及统计结果,从而为我们带来准确的生产状态结论。动态路由:以动态方式根据需要将请求路由至不同后端集群处。 压力测试:逐渐增加指向集群的负载流量,从而计算性能水平。 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求。静态响应处理:在边缘位置直接建立部分响应,从而避免其流入内部集群。 其核心是一系列的filters,定义了四套标准 PRE:路由之前调用,实现身份验证 ROUTING:将请求路由到微服务 POST,微服务以后执行,响应header ERROR,错误时执行 Filter有四个方法,分别为 filterType():过滤器的类型,它决定过滤器在请求的哪个生命周期中执行。 fiterOrder:过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时,需要根据该方法返回的值来依次执行。通过数字指定,数字越大,优先级越低。 shouldFiter:判断该过滤器是否需要被执行。直接返回true,则该过滤器对所有请求都会生效。实际运用中我们可以利用该函数来指定过滤器的有效范围。 r un():过滤器的具体逻辑。 gateway使用了高性能框架Netty,由三部分组成 1、filter过滤器:拦截和修改请求 2
  • Spring boot way to marshall/demarshall XML
    What is the "Boot-iful" way to auto marshall/demarshall XML? My Rest controller: @RestController @Slf4j public class ProvisioningController { @RequestMapping(value = "/provisioning", method = RequestMethod.POST, consumes = MediaType.APPLICATION_XML) public void handleRequest(@RequestBody ProvisioningRequest request) { log.info("Rx request: {}", request); } } The ProvisioningRequest class is generated by Jaxb from a XSD. Posting a sample request to the rest endpoint gives the following error: java.lang.IllegalStateException: Failed to resolve argument 0 of type 'jaxb.generated
  • Spring 启动方式来编组/解组 XML(Spring boot way to marshall/demarshall XML)
    问题 自动编组/解组 XML 的“Boot-iful”方式是什么? 我的休息控制器: @RestController @Slf4j public class ProvisioningController { @RequestMapping(value = "/provisioning", method = RequestMethod.POST, consumes = MediaType.APPLICATION_XML) public void handleRequest(@RequestBody ProvisioningRequest request) { log.info("Rx request: {}", request); } } ProvisioningRequest 类由 Jaxb 从 XSD 生成。 向其余端点发布示例请求会出现以下错误: java.lang.IllegalStateException: Failed to resolve argument 0 of type 'jaxb.generated.ProvisioningRequest' on public void rest.controller.ProvisioningController.handleRequest(jaxb.generated.ProvisioningRequest) 我在类路径中有
  • Spring WebFlux - bodyType=org.springframework.web.multipart.MultipartFile 不支持内容类型“application/xml”(Spring WebFlux - Content type 'application/xml' not supported for bodyType=org.springframework.web.multipart.MultipartFile)
    问题 我正在使用spring-webflux并想上传文件....一切都适用于spring-web但是当涉及到webflux我不知道出了什么问题。 小心区别......我正在使用: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> 所以假设我们有下面的@RestController ,对于Spring Web它就像魅力一样: @PostMapping(value = "/uploadFile") public Response uploadFile(@RequestParam("file") MultipartFile file) { } 现在尝试对Spring-webflux进行相同的操作会产生以下错误: { "timestamp": "2019-04-11T13:31:01.705+0000", "path": "/upload", "status": 400, "error": "Bad Request", "message": "Required MultipartFile parameter 'file' is not present" } 我从一个随机的
  • Webflux websocketclient, How to send multiple requests in same session[design client library]
    TL;DR; We are trying to design a WebSocket server using spring webflux WebSocket implementation. The server has usual HTTP server operations e.g. create/fetch/update/fetchall. Using WebSockets we were trying to expose one endpoint so the clients could leverage a single connection for all sort of operations, given WebSockets are meant for this purpose. Is it a right design with webflux and WebSockets? Long Version We are starting a project which is going to use reactive web sockets from spring-webflux. We need to build a reactive client library which can be used by consumers to connect to the
  • 15.SpringCloud学习笔记--Gateway
    Zuul参考: https://github.com/Netflix/zuul Gateway参考: https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/ https://spring.io/projects/spring-cloud-gateway 什么是 Gateway 网关 概述 Gateway 是在 Spring 生态系统之上构建的 API 网关服务,基于 Spring 5, Spring Boot 2 和 Project Reactor 等技术。 Gateway 旨在提供一 种简单而有效的方式来对 API 进行路由,以吸提供一些强大的过滤器功能,例如: 熔断、限流、重试等。 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。 Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul。在 Spring Cloud2.0 以上版本中,没有对新版本的 Zuul2.0
  • 如何根据凭证号过滤计数 xml 响应?(how to filter tally xml response based on voucher number?)
    问题
  • 返回 fetch .json 内部对象。(Return fetch .json inside object.)
    问题 我有一个 API 调用函数,我想将 response.json() 内容以及 response.status 一起返回到单个对象中。 像这样: const getData = data => { return fetch('/api_endpoint',{ method: 'GET', headers: { 'Content-type': 'application/json' } }) .then(response => { return { body: response.json(), status: response.status } }) } 问题是 response.json() 是一个承诺,所以在它解决之前我无法提取它的价值。 我可以通过这样做来绕过它: const getData = data => { let statusRes = undefined; return fetch('/api_endpoint',{ method: 'GET', headers: { 'Content-type': 'application/json' } }) .then(response => { statusRes = response.status; return response.json() }) .then(data => { return { body: data