'spring cloud gateway - Create dynamic java routes

I created my bean like this:

@Bean
public RouteLocator routes(RouteLocatorBuilder builder, LoggingGatewayFilterFactory loggingFactory) {
    return builder.routes()
            .route("configuracionApp",
                    r -> r.path("/configuracion")
                    .and().readBody(String.class, requestBody -> true)
                    .filters(
                            f -> f
                            .filter(loggingFactory.apply(new Config("My Custom Message", true, true)))
                            .modifyResponseBody(String.class, String.class, bodyRewrite)
                            )
                    .uri("lb://msapp")
                    )
            .route("configuracionHorario",
                    r -> r.path("/configuracion/horario")
                    .filters(
                            f -> f
                            .filter(loggingFactory.apply(new Config("My Custom Message", true, true)))
                            .modifyResponseBody(String.class, String.class, bodyRewrite)
                            )
                    .uri("lb://msapp")
                    )
            .build();
}

Everything works perfect, my only doubt is if I can create those routes from a list, and have that list in a yml file for example,

Thanks in advance



Solution 1:[1]

I define a list of routes in :
application.yml

application:
  routes:
    - 
      id: referential
      path: /referential/**
      uri: https://referential.p.rapidapi.com
    - 
      id: muslimsalat
      path: /muslimsalat/**
      uri: https://muslimsalat.p.rapidapi.com

I define a configuration properties class to map properties in
RouteConfigProperties.java

import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import lombok.Data;

@Configuration
@ConfigurationProperties(prefix = "application")
@Data
public class RouteConfigProperties 
{
    private List<CustomRoute> routes;

    @Data
    public static class CustomRoute 
    {
        private String id;
        private String path;
        private String uri;
    }

}

Finally i define my GatewayRouteConfig class in
RouteConfig.java

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;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder.Builder;

@Configuration
public class RouteConfig {
            
    private final RouteConfigProperties routeConfigProperties;

    public RouteConfig(RouteConfigProperties routeConfigProperties) {
        this.routeConfigProperties = routeConfigProperties;
    }

    @Bean
    RouteLocator staticRoutes(RouteLocatorBuilder builder) 
    {       
        Builder build = builder.routes();
    
        routeConfigProperties.getRoutes().forEach(customRoute -> {
        
             build.route(
                  customRoute.getId(), 
                  route -> route.path(customRoute.getPath())
                  .filters(filter -> filter.addRequestHeader("x-rapidapi-host", String.format("%s.p.rapidapi.com", customRoute.getId()))
                                           .addRequestHeader("x-rapidapi-key", "2bb4b6cd95msh13bd91f0c332909p10dc79jsn9e98442d4457")
                                           .rewritePath(String.format("/%s/(?<segment>.*)", customRoute.getId()), "/${segment}"))
                  .uri(customRoute.getUri()));
        
        });
    
        return build.build();
    }

}

Don't forget to enabled configuration properties in :
GatewayServiceApplication.java

import org.sid.gatewayservice.config.RouteConfigProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties({ RouteConfigProperties.class })
public class GatewayServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayServiceApplication.class, args);
    }

}

Solution 2:[2]

If you want routes in a file, why not use the Path Route predicate provided by spring cloud gateway - https://cloud.spring.io/spring-cloud-gateway/reference/html/#the-path-route-predicate-factory

There is are a ton of filters there too that can change requests and responses.

To change requests and responses of routes that are not provided the filters provided by spring, you can create your own custom filters - GlobalFilter or GatewayFilters. For reference on how to implement, you can see their repo (for eg. how did they implement AddRequestHeader filter).

While global filters apply to all routes. GatewayFilters can be mapped to a specific one. For example, if you created a custom Filter called MyCustomFilter and you want it to be applied only in /foo/* requests, you can do somehting like:

spring:
  cloud:
    gateway:
      routes:
      - id: 
        uri: https://example.org # or lb://my-service
        predicates:
        - Path=/foo/**
        filters:
        - MyCustomFilter

To check which filters got applied to which routes you can see in the actuator gateway routes.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2