How to Log Request and Response Bodies in Spring WebFlux?
Last Updated :
28 May, 2024
To log request and response bodies in Spring WebFlux, we need to use filters or logging mechanisms that can intercept and log the necessary information. In this article, we use WebFilter to filter the request types in the Spring application.
Intercepting the Request Body:
- The getRequest().getBody() method returns a Flux<DataBuffer>.
- Map over this Flux to read the request body bytes and convert them into a string for logging purposes.
- Then continue the filter chain with chain.filter(exchange).
Intercepting the Response Body:
- The doOnSuccess method is used to log the response body after the request has been processed.
- exchange.getResponse().beforeCommit() ensures that we subscribe to the response body before it is committed.
- Similar to the request body, the response body is read from the DataBuffer and logged.
Prerequisites:
You should have knowledge of the below-listed topics to understand this article.
- Spring Framework
- Spring WebFlux
- Publisher and Consumer
- Operators in Spring reactor
- Maven
- Events Flow and Subscription
- Web Filters
- HTTP Request and Response
Tools & Technologies:
- Spring Framework
- Spring Reactive programming
- Spring Tool Suite
- project type : maven
Steps to Implement Log Request and Response Bodies in Spring WebFlux
Here we created one simple spring reactive project Below we provide the in detail explanation with examples for better understanding the concept.
Dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Project folder Structure:
After creating the project, the structure will be like below:

Step 1: Logging Configuration
To enable logs in Spring application, we need configure the logs in the application properties file. Open application properties file which is located in resource folder of project. You can observe this in the above project folder image. Below we provide the code for configure the log functionality in spring application.
spring.application.name=log
# application.properties
logging.level.org.springframework.web=DEBUG
logging.level.com.example.logging=DEBUG
Step 2: LoggingFilter Implementation
Now, we create a Component class in the project package by using @Component spring annotation. We can use @Component throughout the application to mark beans as managed Spring components.
LoggingFilter.java:
Java
package com.app;
import java.nio.charset.StandardCharsets;
import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Component
public class LoggingFilter implements WebFilter {
private static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
return DataBufferUtils.join(request.getBody())
.flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
String body = new String(bytes, StandardCharsets.UTF_8);
logger.info("Request Body: {}", body);
return chain.filter(exchange.mutate().request(request.mutate().build()).build())
.then(Mono.defer(() -> {
ServerHttpResponse response = exchange.getResponse();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(response) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
Flux<? extends DataBuffer> flux = Flux.from(body);
return super.writeWith(flux.map(dataBuffer -> {
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
String responseBody = new String(content, StandardCharsets.UTF_8);
logger.info("Response Body: {}", responseBody);
return dataBuffer;
}));
}
@Override
public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
return writeWith(Flux.from(body).flatMapSequential(p -> p));
}
};
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}));
});
}
}
In the above code, we implemented the user-created class to WebFilter. And override the filter method to log request and response bodies. Ensure that the filter is registered in your Spring Boot application by annotating it with @Component.
After creating the class we define the Logger inside the class.
private static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class);
After this, we write our own logic for overriding the filter method and It can take ServerWebExchange, and WebFilterChain as arguments. In the filter method, we define the ServerHttpRequest object by using the ServerWebExchange object. Then return the Mono object with void type.
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
return DataBufferUtils.join(request.getBody())
.flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
String body = new String(bytes, StandardCharsets.UTF_8);
logger.info("Request Body: {}", body);
return chain.filter(exchange.mutate().request(request.mutate().build()).build())
.then(Mono.defer(() -> {
ServerHttpResponse response = exchange.getResponse();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(response) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
Flux<? extends DataBuffer> flux = Flux.from(body);
return super.writeWith(flux.map(dataBuffer -> {
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
String responseBody = new String(content, StandardCharsets.UTF_8);
logger.info("Response Body: {}", responseBody);
return dataBuffer;
}));
}
@Override
public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
return writeWith(Flux.from(body).flatMapSequential(p -> p));
}
};
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}));
});
}
Step 3: Sample RestController
After this, we create one RestController class in the main package of the project by using @RestController annotation. Inside the class we created a method called sayHello() with @RequestMapping("/hello") and this method returns a String value in the form of Mono publisher.
Java
package com.app;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/hello")
public class HelloController {
@GetMapping
public Mono<String> sayHello() {
return Mono.just("Hello, WebFlux!");
}
}
Step 4: Run the Application
Now, run this project by using maven commends or run as Spring Boot App. This project runs on Netty Server on port number 8080 by default. Here we run this project as a Spring Boot App.

Step 5: Testing API
Now test the API. Here we use the Post Man tool for testing the API.
http://localhost:8080/hello
Output:

After hitting the API, you can observe the logs in the console.
Note:
- The code provided is a simplified version and may need enhancements for production use, such as handling larger request or response bodies and considering performance impacts.
- Ensure proper exception handling and consider using non-blocking approaches if the payload size is significant.
- You might also need to handle different content types and potentially encode/decode binary data accordingly.
Similar Reads
How to Redirect a Request in Spring WebFlux?
The Spring WebFlux is a part Spring Reactive framework. In Spring WebFlux, we can redirect requests by using the ServerResponse. This is one of the classes in Spring WebFlux which provides methods for creating responses. To direct a request in Spring WebFlux, we typically return the ServerResponse w
4 min read
How to Handle Logs and Tracing in Spring WebFlux?
In modern microservices, effective logging and tracing are essential for monitoring, debugging, and maintaining the applications. Spring Webflux is a reactive web framework and it can provide the tools and techniques for handling the logs and tracing efficiently. This article will guide you through
4 min read
How to Solve 403 Error in Spring Boot Post Request?
Spring Boot is one of the frameworks used in developing web applications, and it provides a lot of features to solve real-time problems in software industries. In this article, we will explain how to solve the 403 error in the Spring Boot post request. This error is raised due to security configurat
6 min read
Creating REST APIs Using Spring WebFlux and MongoDB
Spring Boot is the most popular Java framework for building stand-alone Java-based applications quickly and with minimal configuration. WebFlux is a responsive operating system provided by the Spring framework for running non-blocking, asynchronous, and event-driven applications. On the other hand,
10 min read
How to Intercept a Request and Add Headers in WebFlux?
Spring WebFlux is the reactive stack web framework that allows developers to build non-blocking, asynchronous applications that can handle a large number of concurrent with fewer hardware resources. In this article, we will explore how to intercept the HTTP requests in the Spring WebFlux application
4 min read
How to Add @RestController to Spring WebFlux Applications?
Spring WebFlux is fully non-blocking and supports reactive streamback pressure. It works well with non-blocking servers like Netty and Undertow. The reactive model allows handling more connections with fewer threads. It provides reactive support at multiple levels: Web layer, security, WebClient, te
5 min read
How to save Request & Response result as a File in Postman?
In this article, we will see how to save request & response results as a file in Postman. It is a collaborative API development platform used to design, develop, test, document, and manage APIs efficiently. Saving requests and responses as files documents API interactions, making it helpful for
2 min read
Get the Response Body in Spring Boot Filter
In a Spring Boot application, filters can be used to intercept requests and responses, allowing you to manipulate them before reaching the controller or after the response is generated. A common requirement is capturing or logging the response body in the Spring Boot filter, especially for monitorin
5 min read
Basic Introduction to Spring WebFlux
Spring WebFlux is a reactive, non-blocking web framework that uses Project Reactor's reactive streams API to enable highly concurrent and asynchronous processing of web requests in a non-blocking and event-driven way. It is fully asynchronous and non-blocking using reactive streams and callbacks. It
4 min read
Spring REST - Response for Access Denied Request
The Access Denied Request has an error code of 403. This is the error that is generated when the user tries to access certain resources that he is not authorized. The system displays a whitelabel error displaying the status code 403. In this article, let us regenerate this error using spring securit
5 min read