Filtros con WebClient de Spring


En este artículo vamos a ver los filtros con WebClient de Spring, basados en el framework reactivo introducido por Spring WebFlux.

Para refrescar conocimientos de WebClient, podéis echar un ojo pulsando aquí.

Filtro de una petición de cliente

Por lo general un filtro sirve para interceptar y analizar una petición de cliente. Por ejemplo una petición http puede ser interceptada para ver cabeceras, parámetros o puede ser interceptada para añadir una autorización, un log, o cualquier cosa que necesites en una petición.

En Spring podemos interceptar una request por ejemplo con handlerInterceptor. Pero, con programación reactiva, vamos a hacer uso de la interfaz ExchangeFilterFunction.

Veamos un ejemplo sencillo de la utilización de ExchangeFilterFunction:

  private ExchangeFilterFunction logFilter() {
    return (clientRequest, next) -> {
      log.info("External Request to {}", clientRequest.url());
      clientRequest.headers().forEach((name, values) -> {
        log.info("header: " + name + " with value " + values);
      });
      return next.exchange(clientRequest);
    };
  }

En este ejemplo vemos, por un lado, que hacemos log de la request entera, y por otro lado, hacemos log de las cabeceras. Normalmente un filtro se devuelve llamando al siguiente en la cadena de filtros.

¿Cómo usar un filtro en WebClient?

Uno de los campos del builder de WebClient es filter, por lo que una vez creado el WebClient , añadimos el filtro.

    return WebClient.builder()
        .baseUrl(url)
        .filters(exchangeFilterFunctions -> {
          exchangeFilterFunctions.add(logFilter());
          exchangeFilterFunctions.add(authHeader());
        }).defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
        .build();

En el ejemplo anterior, podemos ver como hemos añadido dos diferentes filtros, uno el método que hemos definido en el punto anterior, y otro es añadir una cabecera de autorización.

Creemos un filtro de autorización

Muchas veces es necesario hacer propagación de un token de autorización cuando se llama a otro microservicio, en el siguiente utilizamos la clase ClientRequest.from(), para obtener la url y añadir una cabecera.

  private ExchangeFilterFunction authHeader() {
    return (request, next) -> next.exchange(ClientRequest.from(request).headers((headers) -> {
      headers.set("Authorization", "Bearer " + infoUser.getAuthorizationBearer());
    }).build());
  }

Como podemos ver en ejemplo anterior, obtenemos la petición y le añadimos la cabecera.

Crear un filtro básico

Y ahora vamos con la creación de un filtro básico, que lo podemos meter de manera directa. Así que vamos a añadir en el WebClient un filtro básico de autenticación.

Para añadir el siguiente filtro, utilizaremos el método basicAuthentication que nos ofrece la clase ExchangeFilterFunction.

private ExchangeFilterFunction basicAuthentication(String user, String password) {
WebClient webClient = WebClient.builder()
  .filter(ExchangeFilterFunctions.basicAuthentication(user, password))
  .build();
}

Conclusión

Brevemente hemos visto como añadir filtros con WebClient de Spring, nos permite interceptar y tratar cualquier petición que se realice.


4 pensamientos sobre “Filtros con WebClient de Spring

  1. Hola Chris,

    infoUser sería una Clase de Java que tendría atributos, en este caso el authorization bearer. En lugar de infouser.getAuthorizationBearer(), se podría poner directamente el token que se tiene.

    Actualmente no tengo un ejemplo completo lo desarrollo y lo publico.

    Un saludo.

  2. Hola Noel, luego de estar un par de horas mirando cómo solucionar mi problema este fue el resultado
    @Bean
    WebClient webClient(@Value(«${http.url}») String baseUrl) {
    return WebClient.builder().baseUrl(baseUrl).filter(authHeader()).build();
    }

    private ExchangeFilterFunction authHeader() {
    return (request, next) -> {
    String token = «»;
    final var authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication != null
    && authentication.getDetails() != null
    && authentication.getDetails() instanceof AuthenticationDetails)
    token = ((AuthenticationDetails) authentication.getDetails()).getJwt();
    final String finalToken = token;
    return next.exchange(
    ClientRequest.from(request)
    .headers((headers) -> headers.setBearerAuth(finalToken))
    .build());
    };
    }

    Donde AuthenticationDetails es:
    @Builder
    @Getter
    @Setter
    public class AuthenticationDetails {

    private String jwt;
    private List accessibleFranchises;

    }

    facilmente se puede obviar la parte del parseo y validación y así cambiar la forma en la que la aplicación obtiene el token, la idea principal es que el método setBearerAuth reciba el JWT, para que la momento de hacer cualquier petición con el bean de webClient este tenga el token.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *