🚪 Spring Cloud Gateway Cheatsheet Completo 🚪

Spring Cloud Gateway es un framework API Gateway construido sobre Spring Framework 5, Spring Boot 2 y Project Reactor. Proporciona una forma potente y flexible de enrutar solicitudes HTTP y aplicar filtros a esas solicitudes. Es una alternativa reactiva al Zuul 1 de Netflix.


1. 🌟 Conceptos Clave


2. 🛠️ Configuración Inicial (Spring Boot)

  1. Añadir dependencias en pom.xml (Maven):

    <dependencies>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>3.2.0</version>
            <relativePath/>
        </parent>
    
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        &lt;!-- Spring Cloud BOM (para gestionar versiones de Spring Cloud) -->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>2023.0.0</version> &lt;!-- Usar la versión compatible con tu Spring Boot -->
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
        &lt;!-- Opcional: Para descubrimiento de servicios (ej. Eureka) -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        &lt;!-- Para pruebas -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
  2. Configurar application.yml (o application.properties):

    # src/main/resources/application.yml
    server:
      port: 8080 # Puerto del Gateway
    
    spring:
      application:
        name: api-gateway # Nombre de la aplicación Gateway
      cloud:
        gateway:
          routes: # Definición de rutas
            - id: product_service_route # ID único de la ruta
              uri: http://localhost:8081 # URI del servicio backend
              predicates:
                - Path=/products/** # Coincide con solicitudes a /products/cualquiercosa
              filters:
                - AddRequestHeader=X-Gateway-Request, true # Añade un encabezado a la solicitud
                - StripPrefix=1 # Elimina el prefijo /products de la URL enviada al backend
            - id: user_service_route
              uri: http://localhost:8082
              predicates:
                - Path=/users/{id} # Coincide con /users/123
                - Method=GET # Solo para método GET
              filters:
                - RewritePath=/users/(?<segment>.*), /api/v1/users/${segment} # Reescribe la URL para el backend
          default-filters: # Filtros que se aplican a todas las rutas (opcional)
            - AddResponseHeader=X-Powered-By, SpringCloudGateway

3. 🗺️ Definición de Rutas

Las rutas pueden definirse en la configuración (application.yml) o programáticamente (RouteLocator).

3.1. Rutas Basadas en Configuración (YAML - Recomendado para la mayoría de los casos)

spring:
  cloud:
    gateway:
      routes:
        - id: mi_ruta_id # Identificador único de la ruta
          uri: lb://nombre-servicio-eureka # URI del servicio destino. 'lb://' para balanceo de carga con Eureka
          # uri: http://localhost:8081 # URI directa a un servicio
          predicates: # Condicionales para que la ruta coincida
            - Path=/api/miservicio/** # Coincide con el path
            - Host=*.example.com # Coincide con el host
            - Method=GET,POST # Coincide con el método HTTP
            - Header=X-Custom-Header, myValue # Coincide con un encabezado
            - Query=param, value # Coincide con un parámetro de query string
            - Cookie=mycookie, myvalue # Coincide con una cookie
            - After=2023-01-01T12:00:00+01:00[Europe/Madrid] # Después de una fecha/hora
            - Before=2024-01-01T12:00:00+01:00[Europe/Madrid] # Antes de una fecha/hora
            - Between=2023-01-01T12:00:00+01:00[Europe/Madrid], 2023-12-31T23:59:59+01:00[Europe/Madrid] # Entre dos fechas
            - RemoteAddr=192.168.1.1/24 # Coincide con la IP remota
            - Weight=myGroup, 8 # Para Canary deployments (ver Filters)
          filters: # Filtros a aplicar a esta ruta
            - StripPrefix=1 # Elimina 1 segmento de la ruta (ej. /api/users -&gt; /users)
            - AddRequestHeader=X-Request-ID, {uuid} # Añade un encabezado a la solicitud backend
            - RewritePath=/old/(?<segment>.*), /new/${segment} # Reescribe el path
            - RequestRateLimiter=#{ ... } # Rate limiting
          metadata: # Metadatos opcionales (no afectan el routing, para otros sistemas)
            key: value

3.2. Rutas Basadas en Java (Programáticas)

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GatewayRoutesConfig {

    @Bean
    public RouteLocator myCustomRoutes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route(p -&gt; p
                    .path("/api/legacy/**") // Predicado de Path
                    .filters(f -&gt; f.stripPrefix(1) // Elimina /api
                                   .addRequestHeader("X-Legacy-Route", "true")) // Añade un encabezado
                    .uri("http://localhost:8083")) // URI de destino
                .route(p -&gt; p
                    .host("*.example.com") // Predicado de Host
                    .and() // Conecta predicados con AND
                    .path("/users/{id}")
                    .filters(f -&gt; f.rewritePath("/users/(?<segment>.*)", "/api/v1/users/${segment}"))
                    .uri("lb://user-service")) // Usa el nombre del servicio Eureka
                .build();
    }
}

4. 🧰 Predicados (Built-in Predicate Factories)

Para definir las condiciones de coincidencia de una ruta.


5. ⚙️ Filtros (Built-in GatewayFilter Factories)

Para modificar las solicitudes o respuestas.


6. 🌐 Integración con Eureka (DiscoveryClient)

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true # Habilita el Service Discovery para las rutas
          lower-case-service-id: true # Convierte los IDs de servicio a minúsculas
      routes:
        - id: my_service_discovery_route
          uri: lb://MY-MICROSERVICE # Eureka resolverá 'MY-MICROSERVICE' a instancias registradas
          predicates:
            - Path=/my-app/**
          filters:
            - StripPrefix=1
    # Configuración de Eureka Client
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/

7. 🔒 Seguridad

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class CustomAuthFilterFactory extends AbstractGatewayFilterFactory<CustomAuthFilterFactory.Config> {

    public CustomAuthFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -&gt; {
            // Lógica de autenticación/autorización
            if (!exchange.getRequest().getHeaders().containsKey("Authorization")) {
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            // Validar token, etc.
            // Si es válido, pasar al siguiente filtro
            return chain.filter(exchange);
        };
    }

    public static class Config {
        // Cualquier configuración para tu filtro
    }
}

// Configuración en application.yml:
# filters:
#   - CustomAuth

8. 💡 Buenas Prácticas y Consejos


Este cheatsheet te proporciona una referencia completa de Spring Cloud Gateway, cubriendo sus conceptos esenciales, cómo configurarlo, la definición de rutas con predicados y filtros, las integraciones clave, la seguridad y las mejores prácticas para construir un API Gateway robusto y escalable en arquitecturas de microservicios.