1

I'm updating old jHipster gateway to 7.5.0 version. New version uses Spring Cloud Gateway (with Eureka), while the old one used Zuul. In previous version working with Service Discovery having service named 'foo' and path 'bar' would register it without any prefix on the gateway so it could be accessed as:

GATEWAY_URL/foo/bar

right now all services register with 'services/' prefix which results requires to call following url:

GATEWAY_URL/services/foo/bar

I can't find configuration responsible for that. I found a property spring.webservices.path, but changing this to other value does not make any change and in Spring Boot 2.6.3 its value cannot be empty or '/' (but Im not sure if this is a property I should be checking). I also experimented with spring.cloud.gateway.routes in form:

spring:
webservices:
    path: /test
main:
    allow-bean-definition-overriding: true
cloud:
    gateway:
        discovery:
            locator:
                enabled: true
        routes:
            - id: user-service-route
              uri: lb://user
              predicates:
                  - Path=/user/**

but without any luck. Also Im not sure if this is jHipster issue or SCG

I need to change that so that other systems using my API won't need to update their paths, I know I can always add nginx before so that it will rewrite te path but that feels not correct.

marekk
  • 237
  • 2
  • 11
  • As far as I know, this change was done also in JHipster Zuul before moving to spring cloud gateway. – Gaël Marziou Jan 28 '22 at 09:51
  • This might be true, I was using very old version - from files i see it was generated using 4.6.2 generator, so a lot was changed for sure, but this would mean that maybe its something that jHipster is responsible for – marekk Jan 28 '22 at 10:46
  • I don't think so, personally I'd try to run under debugger with a breakpoint in DiscoveryClientRouteDefinitionLocator class – Gaël Marziou Jan 29 '22 at 12:15
  • 1
    Yes, this is exactly what I did, and I found out that this is the case of autoconfiguration done by GatewayDiscoveryClientAutoConfiguration, which is part of SCG. Its defining DiscoveryLocatorProperties bean with default predicate: PredicateDefinition{name='Path', args={pattern='/'+serviceId+'/**'}} so in the end I created custom WebFilter that is mapping my old services paths to new and over the time I will update clients to use new route paths :) – marekk Jan 29 '22 at 20:24

1 Answers1

1

This behavior is done by SCG autoconfiguration - GatewayDiscoveryClientAutoConfiguration, it registers DiscoveryLocatorProperties bean with predicate:

PredicateDefinition{name='Path', args={pattern='/'+serviceId+'/**'}}

I didnt want to change autoconfigration, so I did WebFilter that is executed as first one and mutates request path

public class ServicesFilter implements WebFilter {

private final ServicesMappingConfigration mapping;

public ServicesFilter(ServicesMappingConfigration mapping) {
    this.mapping = mapping;
}

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    RequestPath path = exchange.getRequest().getPath();
    if (path.elements().size() > 1) {
        PathContainer pathContainer = path.subPath(1, 2);
        if (mapping.getServices().contains(pathContainer.value())) {
            ServerHttpRequest mutatedRequest = exchange
                .getRequest()
                .mutate()
                .path("/services" + exchange.getRequest().getPath())
                .build();
            ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build();
            return chain.filter(mutatedExchange);
        }
    }

    return chain.filter(exchange);
}}
marekk
  • 237
  • 2
  • 11