Dmitriy L
Dmitriy L

Reputation: 31

Problem with Spring cloud gateway filters

I try use Spring Cloud Gateway Filter for my request. I tried use some variants realisation filters like below:

@Component
@Slf4j
@Order(-10000)
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> {

    public CustomFilter() {
        super(Config.class);
        log.info("Loaded GatewayFilterFactory [Authorize]");
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("enabled");
    }


    @Override
    public ShortcutType shortcutType() {
        return ShortcutType.DEFAULT;
    }

    @Override
    public GatewayFilter apply(CustomFilter.Config config) {
        log.info("Into apply");
        return (exchange, chain)->{
            log.info("Into exchange!");
            System.out.println(exchange.getRequest() + " request");

            return chain.filter(exchange);
        };
    }

    public static class Config {
        private boolean enabled;

        public Config() {}

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }

    }
}

Component
@Slf4j
public class MainFilter implements GatewayFilterFactory<MainFilter.Config> {

    @Override
    public GatewayFilter apply(Config config) {
        log.info("[Apply]");
        return (exchange, chain) -> {
            log.info("[Apply: {}]", exchange);
            System.out.println("gateway filter name " + config.getName());
            return chain.filter(exchange);
        };
    }

    @Override
    public Class<Config> getConfigClass() {
        return Config.class;
    }

    @Override
    public Config newConfig() {
        return new Config("MainFilter");
    }

    public static class Config {

        public Config(String name) {
            this.name = name;
        }

        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

My gateway.yml file below:

server:
  port: 8080

management:
  endpoint:
    gateway:
      enabled: true
  endpoints:
    web:
      exposure:
        include: gateway

spring:
  cloud:
    discovery:
      enabled: true
    gateway:
      discovery:
        locator:
          enabled: true
          lowerCaseServiceId: true
#      default-filters:
#        - name: MainFilter
      routes:
        - id: second_route
          uri: lb://auth-service
          predicates:
          - Path=/api/v1/**
          filters:
          - MainFilter

  application:
    loadbalancer:
      ribbon:
        enabled: false

But when i create request for service localhost:8080/auth-service/api/v1/ Filter not working. I don't see mwssahe log.info() on my console. But when i use conditions default-filter in my gateway.yml my custom filter is working. What problem for use custom filter with my route?

Upvotes: 3

Views: 3241

Answers (1)

Hellaren
Hellaren

Reputation: 467

Most likely your filter doesn't work because the incoming request doesn't match the path predicate from your configuration

The route is configured as

    routes:
    - id: second_route
      uri: lb://auth-service
      predicates:
      - Path=/api/v1/**
      filters:
      - MainFilter

where MainFilter is applied to all requests that match the path predicate /api/v1/**. If we take a closer look at the predicate, the incoming request path should:

  1. Start with /api/v1
  2. Have anything in url after /api/v1 segment (the ** is similar to regex .* expression and will match everything)

Therefore the following request urls should be matched:

  • http://localhost:8080/api/v1/
  • http://localhost:8080/api/v1?key=value
  • http://localhost:8080/api/v1/test
  • http://localhost:8080/api/v1/test/key=value
  • etc

But when i create request for service localhost:8080/auth-service/api/v1/ Filter not working

Based on the path predicate mapping information provided above, your request should not be matched the path predicate you defined. Your request has the following path/auth-service/api/v1 while gateway is looking for path like /api/v1/.

Since no routes are matched, gateway ignores the request and allows it to go further in the pipeline where I assume your auth-service API matches the mapping and corresponding controller returns the response directly without the gateway

In speaking about default filters, they will handle all requests no matter what URL/Header/Query they have.

You should be able to find the path matcher logs using the following configuration

logging:
  level:
    org.springframework.cloud.gateway: TRACE
    reactor.netty.http.client: TRACE

Then look for logs similar to this:

  • Pattern "[/api/v1/**]" does not match against value "/auth-service/api/v1"
  • Pattern "/api/v1/**" matches against value "/api/v1/"

Additional information about path predicates could be found here:

Upvotes: 0

Related Questions