Spring Gateway locator automatic routing compatible with context-path

background

Based on the microservice development method combined with Spring Gateway and Eureka,
if automatic routing analysis is used, the eureka service ID on the microservice can be used as the routing key, so that the automatic forwarding of services can be realized according to the gateway address + service ID.
Spring Gateway can be configured like this:

spring:
  application:
    name: gateway
  cloud:
    gateway:
      enabled: true
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true

For example, for a microservice spring.application.name=my-service, there is an interface address of /api/api-test. If passed, http://网关地址:端口/my-service/api/api-testit can be forwarded to this microservice.

However, for some reason, this microservice added server.servlet.context-path=/my-service. In this case, automatic routing cannot be used directly. Instead, the routing policy must be added manually:

spring:
    name: gateway
  cloud:
    gateway:
      enabled: true
      routes:
        - id: my-service
          uri: lb://my-service
          predicates:
            - Path=/my-service/**

The problem with this is that every time you add a service, you have to manually add a route to the configuration file, and you need to restart the gateway to take effect.

Is there a way to automatically configure routing according to eureka and add context-path?

train of thought

The answer is of course yes. First of all, we need to know why the gateway can automatically forward /my-service/api/api-test to the /api/api-test address on the corresponding service, and find a service node through load balancing. Leaving aside the discussion, it is mainly the process of replacing /my-service/api/api-test with /api/api-test, which is actually defined in org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactorythis class:

public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
	ServerHttpRequest req = exchange.getRequest();
	addOriginalRequestUrl(exchange, req.getURI());
	String path = req.getURI().getRawPath();
	String newPath = path.replaceAll(config.regexp, replacement);
	ServerHttpRequest request = req.mutate().path(newPath).build();
	exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI());
	return chain.filter(exchange.mutate().request(request).build());
}

Where is this class initialized?
it's here:org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration

public static List<FilterDefinition> initFilters() {
    
    
	ArrayList<FilterDefinition> definitions = new ArrayList<>();
	// add a filter that removes /serviceId by default
	FilterDefinition filter = new FilterDefinition();
    filter.setName(normalizeFilterFactoryName(RewritePathGatewayFilterFactory.class));
	String regex = "'/' + serviceId + '/?(?<remaining>.*)'";
	String replacement = "'/${remaining}'";
	filter.addArg(REGEXP_KEY, regex);
	filter.addArg(REPLACEMENT_KEY, replacement);
	definitions.add(filter);
	return definitions;
}

So I saw that Spring Cloud Gateway's automatic routing injects a filter that replaces the URL, which is responsible for replacing the serviceId in the address, and the context-path we added happens to be servcieId, so as long as this filter is not enabled, it will not be replaced up.

solve

spring:
  application:
    name: gateway
  cloud:
    gateway:
      enabled: true
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
          filters:

Yes, you just need to add one filter, the default is an empty list, but there is a better option to add some default filters, for example, it can PreserveHostHeaderkeep the header information of the original request, so the final configuration is as follows :

spring:
 application:
   name: gateway
 cloud:
   gateway:
     enabled: true
     discovery:
       locator:
         enabled: true
         lower-case-service-id: true
         filters:
           - PreserveHostHeader

Guess you like

Origin blog.csdn.net/qq_39609993/article/details/129598985