Spring Gateway: gestiona, filtra y redirige Rutas fácilmente

Spring Cloud Gateway es uno de los componentes clave para enrutar y filtrar peticiones dentro de una arquitectura de microservicios. Además de actuar como puerta de entrada a tu ecosistema de servicios, el gateway te permite aplicar lógica de negocio, manipular cabeceras y transformar paths antes de redirigir la solicitud al servicio correspondiente.

 

 

En este post vamos a tratar de explicar cómo configurar rutas manuales, aplicar filtros, redirigir hacia un Load Balancer y reescribir rutas en tiempo real. Todo ello con ejemplos prácticos que puedes aplicar directamente en tu proyecto.

 

¿Qué es Spring Cloud Gateway?

 

En primer lugar, hay que comentar que Spring Cloud Gateway es una solución reactiva que permite construir un API Gateway sobre aplicaciones Spring Boot (a partir de la versión 3) y Spring WebFlux. Actualmente, es el Gateway oficial de Spring. Permite lo siguiente:

  • Enrutamiento inteligente de peticiones HTTP.

  • Filtros pre y post procesamiento.

  • Integración con Eureka para descubrimiento de servicios.

  • Configuración en YAML, .properties o Java.

Una vez tenemos claro en qué consiste Spring Cloud Gateway, vamos a ir viendo las posibilidades que nos ofrece a la hora de gestionar y filtrar las rutas de los microservicios invocados.

 

Configurar rutas manualmente en Spring Gateway

 

Por defecto, Spring Gateway dispone de la posibilidad de activar un enrutamiento automático. Dicho automatismo nos permite trabajar con un mecanismo estándar para capturar las peticiones del cliente y reenrutarlas al microservicio destino. Como ya sabemos, esto se hace con los siguientes parámetros:

# Activacion de API gateway con enrutamiento automatico
spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id=true

  

Sin embargo, si el enrutamiento automático no cubre las necesidades de nuestro proyecto, también disponemos de la posibilidad de definir tratamientos manuales para las rutas en Spring Gateway. Esto se podría hacer mediante parametrización (desde el archivo "application.properties" o desde el archivo "application.yml") o mediante configuración programática en Java.

 

🔎 Aquí te pongo un ejemplo de cómo se podría configurar manualmente una ruta de manera programática, haciendo uso del constructor "RouteLocatorBuilder". 

 

 
@Configuration
public class ApiGatewayConfiguration {

    @Bean
    public RouteLocator gatewayRouter(RouteLocatorBuilder builder) {

        return builder.routes()
            .route(r -> r.path("/get")
                .uri("http://almacen-stock.org:80"))
            .build();
    }
}
 

 

En este código se está definiendo manualmente un único enrutador que captura todas las peticiones con rutas que coincidan con "/get" y las redirige hacia el endpoint "http://almacen-stock.org:80".

 

🔎 Esta misma configuración también puede hacerse, tal y como hemos dicho antes, vía parametrización en el fichero "application.properties":


 
spring.cloud.gateway.routes[0].id=almacen-stock-route
spring.cloud.gateway.routes[0].uri=http://almacen-stock.org:80
spring.cloud.gateway.routes[0].predicates[0]=Path=/get
 
 
 

Filtrar rutas en Spring Gateway

 

Una de las grandes ventajas de Spring Cloud Gateway es su capacidad de aplicar filtros sobre las rutas recibidas del cliente antes de ejecutar el reenrutamiento al microservicio destino. Estos filtros nos permiten capturar los request y añadir cabeceras o parámetros adicionales que deseamos que lleguen hasta los servicios destino.

 

🔎 Por ejemplo, aquí puedes ver un filtro en el que se están realizando las siguientes gestiones antes de ejecutar el reenrutado.

  • Se añade una cabecera a la petición mediante addRequestHeader()
  • Se añade un parámetro a la petición mediante addRequestParameter()

        Function<GatewayFilterSpec, UriSpec> filter1 =
                            f -> f.addRequestHeader("MyHeader", "MyURI")
                                  .addRequestParameter("Param", "MyValue");

 

Posteriormente, una vez están totalmente configuradas todas las modificaciones sobre la petición de entrada, se aplica el filtro a la ruta mediante filters() 

        Function<PredicateSpec, Buildable<Route>> routeFunction =
                p -> p.path("/get").filters(filter1).uri("http://almacen-stock.org:80");

 

👉 El ejemplo completo quedaría así:

 
 
@Bean
    public RouteLocator gatewayRouter(RouteLocatorBuilder builder) {

        // Filtro de ruta --->  
        // Se incorpora un header al request antes de que el gateway haga el enrutado
        // Tambien se añade un parametro
        Function<GatewayFilterSpec, UriSpec> filter1 =
                            f -> f.addRequestHeader("MyHeader", "MyURI")
                                  .addRequestParameter("Param", "MyValue");
       
        // Funcion Lambda que redirige los paths /get a una url especifica
        Function<PredicateSpec, Buildable<Route>> routeFunction =
                p -> p.path("/get").filters(filter1).uri("http://almacen-stock.org:80");
       
        RouteLocator routeLocator = builder.routes()
                .route(routeFunction)
                .build();
       
        return routeLocator;
       
    });
 
 
 

La implementación anterior también podría llevarse a cabo mediante parametrización. Lo equivalente al ejemplo indicado se pondría así en el fichero .properties:


 
# Api Gateway - Enrutamiento manual
spring.cloud.gateway.routes[0].id=almacen-stock-route
spring.cloud.gateway.routes[0].uri=lb://almacen-stock
spring.cloud.gateway.routes[0].predicates[0]=Path=/almacen-stock/status
spring.cloud.gateway.routes[0].predicates[1]=Method=GET,POST
spring.cloud.gateway.routes[0].filters[0]=AddRequestHeader=MyHeader,MyURI
spring.cloud.gateway.routes[0].filters[1]=AddRequestParameter=Param,MyValue
  

     

Este tipo de parametrización puede resultar útil, por ejemplo, para pruebas, logging o para añadir autenticaciones internas.

 

Redirigir peticiones a un Load Balancer

 

Si utilizas Eureka como Service Discovery, otra de las funcionalidades relevantes de Spring Gateway es que nos permite enrutar directamente las peticiones a los balanceadores de los servicios registrados usando el prefijo "lb://".

 

👉 Aquí te dejo un ejemplo de cómo se haría esto: 

 
@Bean
public RouteLocator gatewayRouter(RouteLocatorBuilder builder) {
    return builder.routes()
        .route(r -> r.path("/users/status/check")
            .and().method(HttpMethod.GET, HttpMethod.POST)
            .uri("lb://users-ws"))
        .build();
}
 

En este método el gateway redirige la petición hacia cualquier instancia del microservicio "users-ws" que esté registrada en el servidor Eureka, aplicando balanceo de carga automático.

 

👉 Como siempre, si no nos gusta la configuración programática, podríamos hacer lo mismo mediante esta configuración parametrizada equivalente en el fichero .properties:


spring.cloud.gateway.routes[0].id=users-status-check
spring.cloud.gateway.routes[0].uri=lb://users-ws
spring.cloud.gateway.routes[0].predicates[0]=Path=/users/status/check
spring.cloud.gateway.routes[0].predicates[1]=Method=GET,POST

Este tipo de parametrización es ideal para mantener la alta disponibilidad del sistema sin especificar direcciones IP concretas.

 

Cambiar paths en Spring Gateway

 

En muchos proyectos, en ocasiones necesitas reescribir la URL recibida del cliente antes de reenviar la petición al microservicio destino. Para ello se utiliza la función rewritePath().

 

👉 Aquí tienes un ejemplo de uso:

 
        // Rewrite
        // Cambiamos el path "stock-market-new" por el path "stock-market/feign" 
// antes de reenrutar al servicio
        Function<GatewayFilterSpec, UriSpec> filter2 =
                    f -> f.rewritePath("/stock-market-new/(?<segment>.*)",
                                        "/stock-market/feign/${segment}");
        Function<PredicateSpec, Buildable<Route>> routeFunction4 =
                                p -> p.path("/stock-market-new/**")
                                        .filters(filter2)
                                        .uri("lb://stock-market");
       
        RouteLocator routeLocator = builder.routes()
                .route(routeFunction4)
                .build();
       
        return routeLocator;
 

 

Esta ruta intercepta cualquier petición que comience por "/stock-market-new/" y la transforma internamente a "/stock-market/feign/" antes de enviarla.

 

👉 Aquí te dejo la configuracion parametrizada equivalente en el application.properties:

 
 
spring.cloud.gateway.routes[0].id=stock-market-rewrite
spring.cloud.gateway.routes[0].uri=lb://stock-market
spring.cloud.gateway.routes[0].predicates[0]=Path=/stock-market-new/**
spring.cloud.gateway.routes[0].filters[0]=RewritePath=/stock-market-new/(?<segment>.*), \
/stock-market/feign/${segment}

 

Si eres de los que visualiza de forma más clara las parametrizaciones en formato YAML, así quedaría la configuración en el fichero application.yml: 

 
spring:
  cloud:
    gateway:
      routes:
        - id: stock-market-rewrite
          uri: lb://stock-market
          predicates:
            - Path=/stock-market-new/**
          filters:
            - RewritePath=/stock-market-new/(?<segment>.*), /stock-market/feign/${segment}
 

 

Lo importante es tener en cuenta que este mecanismo es ideal para refactorizar rutas sin romper compatibilidad con versiones anteriores.

 

 

Conclusión: Gateway como punto de control inteligente

 

Como has podido comprobar, Spring Cloud Gateway no sirve únicamente para enrutar tráfico, sino que ofrece mecanismos para manipular, filtrar y transformar las peticiones. Gestionar rutas manualmente te da control total sobre tu arquitectura, y funciones como "rewritePath", "filters" o la integración con Eureka hacen que tu gateway sea tan flexible como potente.

 

Además, toda esta lógica se puede extender con filtros personalizados en Java para gestionar autenticación, logging distribuido, cacheo y más.

 

¡Nos vemos en el siguiente post!

Saludos.

 

Comentarios

Entradas populares de este blog

Componentes y Ventanas de Java Swing

Creación de Webservice SOAP mediante Anotaciones

Configurar Apache Tomcat en Eclipse