Open In App

Spring WebFlux Filters

Last Updated : 05 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In Spring WebFlux, the filters are used to do modifications like it modifies the requests and responses going through the server. This Filter allows us to do basic tasks like modifying headers, logging, authentication etc. In Spring WebFlux Filters, filters are created using WebFilter interface and @WebFilter annotation.

Implementation of WebFlux Filters

public interface WebFilter {
Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain);
}

Step-by-Step Implementation of Spring WebFlux Filters

Below are the steps to implement Spring Webflux Filters.

Step 1: Add Maven Dependency

First, let us define the Maven dependency for WebFlux:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

Step 2: Create an Endpoint

We need to construct a few endpoints. Annotation-based and functional-based methods, one for each. The annotation-based controller will be discussed first:

// Define a Spring WebFlux controller endpoint for handling GET requests with a path variable
@GetMapping(path = "/authors/{name}")
// Method to retrieve and return a Mono<String> representing the provided path variable "name"
public Mono<String> getName(@PathVariable String name) {
// Return a Mono<String> containing the value of the provided path variable "name"
return Mono.just(name);
}

Step 3: Create functional Endpoint

We must construct a handler for the functional endpoint:

Java




// Spring component class representing a handler for author-related operations
@Component
public class AuthorHandler {
  
    // Method to handle retrieving and returning a author name based on the provided ServerRequest
    public Mono<ServerResponse> getName(ServerRequest request) {
        // Extract the "name" path variable from the ServerRequest and wrap it in a Mono
        Mono<String> name = Mono.just(request.pathVariable("name"));
          
        // Return a ServerResponse with an OK status and the author name in the response body
        return ServerResponse.ok().body(name, String.class);
    }
}


Step 4: WebFlux Routing Function

To achieve the same endpoint, using the Functional Web Framework, we can build a Functional Router. The Routing Function that we are developing here has a Handler Function attached to it.

Java




// Define a RouterFunction bean for handling GET requests to "/authors/{id}"
@Bean
public RouterFunction<ServerResponse> getAuthorRoute() {
    return route(GET("/authors/{id}"),
        // Lambda expression handling the request and returning a ServerResponse
        request -> ok().body(service
            .getAuthor(request.pathVariable("id")), Author.class)
    );
}


Step 5: Add a new header to the response

Apply a WebFilter to the response in order to append a new header. This means that every response behaves like this:

Java




// Spring component class implementing the WebFilter interface for filtering web requests and responses
@Component
public class SecondWebFilter implements WebFilter {
  
    // Method to perform filtering on the ServerWebExchange and WebFilterChain
    @Override
    public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
        // Add a custom header to the response indicating the use of this web filter
        serverWebExchange.getResponse().getHeaders().add("web-filter", "web-filter-test");
          
        // Continue the filter chain, allowing the request to proceed to the next filters or handlers
        return webFilterChain.filter(serverWebExchange);
    }
}


Step 6: Create HandlerFilterFunction

Create a logic that, in the event that the “name” argument equals “article” sets the HTTP status to OK.

Java




// Class implementing HandlerFilterFunction for filtering handler functions in a reactive web application
public class SecondHandlerFilterFunction 
  implements HandlerFilterFunction<ServerResponse, ServerResponse> {
  
    // Method to perform filtering on the ServerRequest and HandlerFunction
    @Override
    public Mono<ServerResponse> filter(ServerRequest serverRequest,
      HandlerFunction<ServerResponse> handlerFunction) {
        // Check if the "name" path variable is "article"; if true, return a OK response
        if (serverRequest.pathVariable("name").equalsIgnoreCase("article")) {
            return ServerResponse.status(HttpStatus.OK).build();
        }
        // Continue with the original handler function if the condition is not met
        return handlerFunction.handle(serverRequest);
    }
}


  • In this case, we built up a mechanism to set the HTTP status to OK if the value of the “name” field is “article”.
  • It is possible to filter handler functions in a reactive web application by using the ExampleHandlerFilterFunction class, which implements HandlerFilterFunction.
  • If “article” is present in the “name” path variable, the filter method verifies it and provides a 200 status code along with a Ok response.
  • The purpose of this filter is to intercept and alter the response prior to it reaching the handler function, based on predetermined criteria.

Step 7: Test the WebTestClient

The WebTestClient in the WebFlux Framework provides a simple method for testing our filters. We can test HTTP requests to our endpoints with it.

Annotation-based endpoint:

Java




// Test case to verify that the web filter is applied when the username is "geeksforgeeks"
@Test
public void whenUserNameIsGeeksforgeeks_thenWebFilterIsApplied() {
    // Perform a GET request to "/users/geeksforgeeks" using the WebTestClient
    EntityExchangeResult<String> result = webTestClient.get()
      .uri("/users/geeksforgeeks")
      .exchange()
      // Expect a successful response with status code 200 (OK)
      .expectStatus().isOk()
      // Expect the response body to be of type String
      .expectBody(String.class)
      .returnResult();
  
    // Assert that the response body matches the expected username "geeksforgeeks"
    assertEquals(result.getResponseBody(), "geeksforgeeks");
    // Assert that the "web-filter" header is present in the response and has the expected value
    assertEquals(result.getResponseHeaders().getFirst("web-filter"), "web-filter-test");
}
  
// Test case to verify that the HandlerFilterFunction is not applied when the username is "article"
@Test
public void whenUserNameIsTest_thenHandlerFilterFunctionIsNotApplied() {
    // Perform a GET request to "/users/article" using the WebTestClient
    webTestClient.get().uri("/users/article")
      .exchange()
      // Expect a successful response with status code 200 (OK)
      .expectStatus().isOk();
}


Functional endpoint:

Java




// Test case to verify that the web filter is applied when the author name is "geeksforgeeks"
@Test
public void whenAuthorNameIsGeeksforgeeks_thenWebFilterIsApplied() {
    // Perform a GET request to "/authors/geeksforgeeks" using the WebTestClient
    EntityExchangeResult<String> result = webTestClient.get()
      .uri("/authors/geeksforgeeks")
      .exchange()
      // Expect a successful response with status code 200 (OK)
      .expectStatus().isOk()
      // Expect the response body to be of type String
      .expectBody(String.class)
      .returnResult();
  
    // Assert that the response body matches the expected author name "geeksforgeeks"
    assertEquals(result.getResponseBody(), "geeksforgeeks");
    // Assert that the "web-filter" header is present in the response and has the expected value
    assertEquals(result.getResponseHeaders().getFirst("web-filter"), "web-filter-test");
}
  
// Test case to verify that the HandlerFilterFunction is applied when the author name is "article"
@Test
public void whenAuthorNameIsTest_thenHandlerFilterFunctionIsApplied() {
    // Perform a GET request to "/authors/article" using the WebTestClient
    webTestClient.get().uri("/authors/article")
      .exchange()
      // Expect a Ok response status code (200)
      .expectStatus().isOk();
}


Spring WebFlux Filters helps guarantee that response material is always consumed and offers a mechanism for encoding to and from higher level objects. The filter method allows us to interface with web requests and perform operations via a ServerWebExchange.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads