Skip to content
Advertisement

is it possible to register route filter in the application.properties config in spring gateway

I define a custom filter in spring gateway project, now I found I have to register the custom filter in the code like this:

@Configuration
public class GatewayConfig {

    private final JwtAuthenticationFilter filter;

    public GatewayConfig(JwtAuthenticationFilter filter) {
        this.filter = filter;
    }

    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("auth", r -> r.path("/auth/**").filters(f -> f.filter(filter)).uri("lb://auth"))
                .route("music", r -> r.path("/music/**").filters(f -> f.filter(filter)).uri("lb://dolphin-music")).build();
    }
}

if I do not register the custom filter, the filter will not make effect and work as expect. But I already config the route in application.properties like this:

# dolphin music
spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id=true
spring.cloud.gateway.routes[0].id=dolphin-music-service
# forward by ip:port way
spring.cloud.gateway.routes[0].uri=http://10.107.64.246:11014
# forward by service name way
# spring.cloud.gateway.routes[0].uri=lb://
spring.cloud.gateway.routes[0].predicates[0]=Path=/music/**

I think we should not define the route config both in code and configuration file, what should I do to only register the filter? is there any better way to handle the situation? should I must define the route in code? I think config in file will more flexible.BTW,this is the JwtAuthenticationFilter:

@Component
public class JwtAuthenticationFilter implements GatewayFilter {

    @Value("${dolphin.gateway.jwt.verify:true}")
    private boolean jwtVerfiy;

    final static List<String> apiEndpoints = List.of("/register", "/login");

    final static Predicate<ServerHttpRequest> isApiSecured = r -> apiEndpoints.stream()
            .noneMatch(uri -> r.getURI().getPath().contains(uri));

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        
        return chain.filter(exchange);
    }
}

I tried to add MyFilterFactory like this:

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

    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;

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

    @Override
    public GatewayFilter apply(Config config) {
        return jwtAuthenticationFilter; 
    }

    public static class Config {
    }

}

and define in route factory in application.properties like this:

spring.cloud.gateway.routes[0].filters[0]=MyFilterFactory

the problem is that the request did not enter the JwtAuthenticationFilter I am defined.

Advertisement

Answer

Yes, it is possible, you need to register a bean that extends the GatewayFilterFactory class.

For example:

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

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

    @Override
    public GatewayFilter apply(Config config) {
        return new MyFilter(); // or MyFilter(config), depending on your needs
    }

    public static class Config {
        // this can be empty if you don't need to pass any filter arguments
    }
}

Then you can use its name in the application.properties file.

spring.cloud.gateway.routes[0].filters[0]=MyFilterFactory

Not that you need to use the factory name in the properties file.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement