Маршрутизация нескольких путей к одному и тому же маршруту в YAML

Я пытаюсь перевести обширный набор настроек маршрутизации на Spring Cloud Gateway Yaml DSL.

Одна из проблем, с которой я сталкиваюсь, - это (чрезвычайно распространенный случай), когда несколько путей должны соответствовать одному и тому же маршруту. То есть любой входящий URL-адрес, соответствующий /abc/**, /def/** или /ghi/**, должен быть перенаправлен на некоторый uri http://example.org (и иметь тот же набор фильтров и т. Д.).

В подходе маршрутизации на основе Fluent Java это может быть достигнуто с помощью метода .or()., например: r.path("/abc/**").or().path("/def/**").or().path("/fhi/**")...

Как можно достичь этой же функциональности с помощью конфигурации маршрута на основе YAML?

Изменить: в документации я вижу: https://cloud.spring.io/spring-cloud-gateway/single/spring-cloud-gateway.html#gateway-request-predicates-factories

"Несколько фабрик предикатов маршрутов могут быть объединены и объединены с помощью логического and"

Есть ли другой способ добиться этого ИЛИ предикатов пути через Yaml без объявления нескольких маршрутов? Можно ли что-то изменить, чтобы поддержать это?


person acidnbass    schedule 24.08.2018    source источник


Ответы (2)


Вы, наверное, уже получили ответ. Но для записи я бы сказал, что вы можете добавить несколько путей для предикатов следующим образом:

spring:
  cloud:
    gateway:
      routes:
        - id: instructors_route
          uri: lb://INSTRUCTOR-SERVICE/
          predicates:
            - Path=/api/v1/instructors**,/api/v1/countries**
person Diego Correa    schedule 30.05.2020

Я нашел метод, который обрабатывает комбинацию предикатов:

RouteDefinitionRouteLocator.java: combinePredicates:

private AsyncPredicate<ServerWebExchange> combinePredicates(RouteDefinition routeDefinition) {
    List<PredicateDefinition> predicates = routeDefinition.getPredicates();
    AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition, predicates.get(0));

    for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) {
        AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate);
        predicate = predicate.and(found);
    }

    return predicate;
}

Поскольку это частный метод, чтобы переопределить эту логику с помощью логики объединения предикатов, которая выполняет логическое разделение («ИЛИ») Path предикатов, расширяющийся класс RouteDefinitionRouteLocator должен заново определить все методы, ведущие к возможному вызову combinePredicates (который не является самым гибким из возможных маршрутов). Тем не менее, я смог добиться необходимой мне функциональности, повторно реализовав метод следующим образом:

private AsyncPredicate<ServerWebExchange> combinePredicates(RouteDefinition routeDefinition) {
    //filter out "Path" predicates and place in separate list
    List<PredicateDefinition> predicates = routeDefinition.getPredicates();
    List<PredicateDefinition> pathPredicates = new ArrayList();
    for(PredicateDefinition predicate : predicates){
        if (PATH_PREDICATE_NAME.equals(predicate.getName())) {
            pathPredicates.add(predicate);
        }
    }
    predicates.removeAll(pathPredicates);

    //create an uber predicate out of the "Path" predicates by combining them w/ `or`
    AsyncPredicate<ServerWebExchange> pathPredicate = null;
    if(pathPredicates.size()>0){
        pathPredicate = lookup(routeDefinition, pathPredicates.get(0));
        for (PredicateDefinition andPredicate : pathPredicates.subList(1, pathPredicates.size())) {
            AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate);
            pathPredicate = pathPredicate.or(found);
        }
    }
    //"AND" together the uber path predicate and the rest of the predicates for the route
    AsyncPredicate<ServerWebExchange> predicate;
    List<PredicateDefinition> predicateSubList;
    if(pathPredicate != null) {
        predicate = pathPredicate;
        predicateSubList = predicates;
    } else {
        predicate =  lookup(routeDefinition, predicates.get(0));
        predicateSubList = predicates.subList(1, predicates.size());
    }
    for (PredicateDefinition andPredicate : predicateSubList) {
        AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate);
        predicate = predicate.and(found);
    }
    return predicate;
}

Затем, переопределение объявленной конфигурации routeDefinitionRouteLocator RouteLocator @Bean в GatewayAutoConfiguration.java этим новым классом позволяет использовать новую логику.

person acidnbass    schedule 27.08.2018