Predicados do Gateway Spring Cloud

spring:
  cloud:
    gateway:
      routes:
        - id: rota_provedor
          uri: http://localhost:8081
          predicates:
            - Path=/api/**
        - id: rota_consumidor
          uri: http://localhost:8082
          predicates:
            - Path=/cliente/**


No exemplo anterior, os endereços IP e porta estão fixos na configuração de URI, o que significa que as solicitações serão direcionadas para um nó específico. Em cenários com múltiplas instâncias, esta abordagem apresenta limitações, pois não permite balanceamento de carga automático.

Conexão com Múltiplas Instâncias

Para resolver este problema, podemos substituir o endereço fixo pelo nome do serviço registrado no service discovery. Considere que a porta 8081 corresponde ao serviço denominado servico-teste-provedor, enquanto a porta 8082 representa servico-teste-consumidor. A modificação necessária é a seguinte:

- id: rota_provedor
  uri: lb://servico-teste-provedor
  predicates:
    - Path=/api/**
- id: rota_consumidor
  uri: lb://servico-teste-consumidor
  predicates:
    - Path=/cliente/**


O prefixo lb:// indica que o gateway deve utilizar balanceamento de carga para resolver dinamicamente as instâncias disponíveis do serviço.

Predicados Disponíveis

Os predicados permitem adicionar condições adicionais às rotas. Mesmo que a URL corresponda ao padrão definido, a requisição só será processada se todas as condições forem satisfeitas. O Spring Cloud Gateway oferece diversas implementações nativas.

Predicados Temporais

Os predicados baseados em tempo verificam o momento em que a requisição é recebida:

  • Before: aceita requisições antes de um horário específico
  • After: aceita requisições após um horário específico
  • Between: aceita requisições dentro de um intervalo de tempo

O formato utiliza ZonedDateTime, que inclui informações de fuso horário:

public static void main(String[] args) {
    System.out.println(ZonedDateTime.now());
}
// Saída: 2024-11-20T15:30:45.123456789-03:00[America/Sao_Paulo]


Para um sistema de e-commerce com promoção relâmpago válida durante o dia 13 de julho de 2024:

- id: promocao_relampago
  uri: lb://servico-teste-provedor
  predicates:
    - Path=/oferta/**
    - Between=2024-07-13T00:00:00-03:00[America/Sao_Paulo],2024-07-14T00:00:00-03:00[America/Sao_Paulo]


Predicado de Cookie

Este predicado verifica a presença e valor de cookies na requisição:

- id: promocao_usuario_vip
  uri: lb://servico-teste-provedor
  predicates:
    - Path=/oferta/**
    - Between=2024-07-13T00:00:00-03:00[America/Sao_Paulo],2024-07-14T00:00:00-03:00[America/Sao_Paulo]
    - Cookie=identificacao,joao.silva


A expressão joao.silva representa uma expressão regular que deve corresponder ao valor do cookie identificacao.

Predicado de Cabeçalho HTTP

Valida a existência e formato de headers específicos:

- id: promocao_usuario_vip
  uri: lb://servico-teste-provedor
  predicates:
    - Path=/oferta/**
    - Between=2024-07-13T00:00:00-03:00[America/Sao_Paulo],2024-07-14T00:00:00-03:00[America/Sao_Paulo]
    - Cookie=identificacao,joao.silva
    - Header=idade,[0-9]{2}


Predicados Adicionais

  • Path: verifica se o caminho da URL coresponde ao padrão especificado
  • Query: exige a presença de parâmetros de consulta na URL
  • RemoteAddr: aplica restrições baseadas em endereço IP
  • Method: limita o acesso a métodos HTTP específicos como GET, POST, PUT, DELETE

Criando Predicados Personalizados

Para requisitos específicos, podemos implementar predicados customizados estendendo AbstractRoutePredicateFactory:

@Component
public class ValidacaoNivelFactory extends AbstractRoutePredicateFactory<ValidacaoNivelFactory.Configuracao> {

    public ValidacaoNivelFactory() {
        super(ValidacaoNivelFactory.Configuracao.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("nivelRequerido");
    }

    @Override
    public Predicate<ServerWebExchange> apply(Configuracao config) {
        return solicitacao -> {
            MultiValueMap<String, String> parametros = solicitacao.getRequest().getQueryParams();
            String nivel = parametros.getFirst("nivel");

            if (!StringUtils.hasText(nivel)) {
                return false;
            }

            return nivel.equals(config.getNivelRequerido());
        };
    }

    @Validated
    public static class Configuracao {
        private String nivelRequerido;

        public String getNivelRequerido() {
            return nivelRequerido;
        }

        public void setNivelRequerido(@NotNull String nivelRequerido) {
            this.nivelRequerido = nivelRequerido;
        }
    }
}


A convenção de nomenclatura exige que a classe termine com RoutePredicateFactory, sendo que a parte anterior define o nome curto utilizado nas configurações YAML.

Configuração da Rota Personalizada

routes:
- id: rota_provedor
  uri: http://localhost:8081
  predicates:
    - Path=/api/**
    - ValidacaoNivel=5


O valor 5 representa o nível mínimo necessário para que a requisição seja processada. A correspondência é feita com base na propriedade nivelRequerido definida na classe de configuração.

Validação

Para testar o predicado personalizado, basta incluir o parâmetro nivel=5 na URL de requisição. Caso o valor seja diferente ou ausente, a rota não será ativada.

Tags: spring-cloud-gateway predicates routes load-balancing java

Publicado em 8-5 14:26