Как исключить RequestInterceptor для конкретного клиента Spring Cloud Feign?

У меня есть несколько клиентов, для которых определен «глобальный» RequestInterceptor. Для одного из клиентов мне нужно исключить этот "глобальный" перехватчик. Можно ли переопределить полный набор RequestInterceptors для конкретного FeignClient?

@FeignClient(value = "foo", configuration = FooClientConfig.class)
public interface FooClient {
//operations
}

@Configuration
public class FooClientConfig{

//How do I exclude global interceptors from this client configuration?
}

Используемая версия spring-cloud-netflix - 1.1.0 M5


person Newbie    schedule 15.03.2016    source источник
comment
Это интересный вопрос. Мое первое предположение состоит в том, что вам, возможно, придется расширить Feign.Builder, который игнорирует любой вызов requestInterceptors или игнорирует те, которые вы хотите.   -  person spencergibb    schedule 16.03.2016
comment
@spencergibb Другими словами, для данного клиента я хочу переопределить любые существующие перехватчики, используя настраиваемую конфигурацию клиента. Это на удивление сложно.   -  person Newbie    schedule 16.03.2016
comment
Мне будет сложно вести список перехватчиков, которые я не хочу включать в этот клиент. Поэтому я вообще не собираюсь регистрировать глобальные перехватчики. Вместо этого каждый клиент будет объявлен с привязанной к нему конкретной конфигурацией. В моем случае это означает, что у меня будет 2 пользовательских конфигурации имитации клиента, одна для большинства клиентов, а другая для исключительного / одноразового клиента. :-(   -  person Newbie    schedule 16.03.2016
comment
Это потому, что у вас может быть несколько перехватчиков, а имитируемые контексты приложения наследуются от родительского. Может быть, вариант НЕ наследовать от родителя на @FeignClient?   -  person spencergibb    schedule 16.03.2016
comment
Это хороший обходной путь   -  person spencergibb    schedule 16.03.2016
comment
Да, перехватчики родительского контекста проникают в каждую настраиваемую конфигурацию клиента (при вызове beanNamesForTypeIncludingAncestors).   -  person Newbie    schedule 16.03.2016
comment
Я бы не назвал это утечкой. Это по умолчанию. Все остальные объекты заменяются, кроме перехватчиков, которые добавляют.   -  person spencergibb    schedule 16.03.2016
comment
Может быть, золотая середина могла бы заключаться в поддержке двух элементов ниже: 1) Возможность не наследовать от родительского объекта для имитируемых bean-компонентов (Decoder, Encoder, Contract и т. Д.) 2) Продолжать разрешать внедрение bean-компонентов из родительского контекста в настраиваемом классе конфигурации сам, так что люди могут повторно использовать родительские символьные bean-компоненты, если они выбирают на уровне класса конфигурации (например, половина bean-компонентов повторно используется из родительского ctx, а половина bean-компонентов настраивается без побочных эффектов). Я не уверен, насколько возможно реализовать №2, но это позволило бы выбрать то, что вы хотите использовать, от родителя.   -  person Newbie    schedule 16.03.2016


Ответы (2)


Кажется, нет простого способа переопределить глобальный перехватчик. Думаю, вы могли бы сделать это так:

@Configuration
public class FooClientConfig{

@Bean
RequestInterceptor globalRequestInterceptor() {
    return template -> {
        if (template.url().equals("/your_specific_url")) {
            //don't add global header for the specific url
            return;
        }

        //add header for the rest of requests
        template.header(AUTHORIZATION, String.format("Bearer %s", token));
    };
}
}
person fungbo    schedule 04.05.2018

Улучшенный способ решения этой проблемы - передать вашему запросу настраиваемый заголовок, например:

@PostMapping("post-path")
ResponseEntity<Void> postRequest(@RequestHeader(HEADER_CLIENT_NAME) String feignClientName, @RequestBody RequestBody requestBody);

Я хочу установить заголовок в перехватчике только для этого воображаемого клиента. Перед установкой заголовка сначала перехватчик проверяет заголовок HEADER_CLIENT_NAME, если он существует и имеет желаемое значение:

private boolean criteriaMatches(RequestTemplate requestTemplate) {
    Map<String, Collection<String>> headers = requestTemplate.headers();
    return headers.containsKey(HEADER_CLIENT_NAME)
        && headers.get(HEADER_CLIENT_NAME).contains("feign-client-name");
}

Таким образом, вы можете проверить перед установкой базовой аутентификации. В перехватчике:

@Override
public void apply(RequestTemplate template) {
    if (criteriaMatches(template)) {
        /*apply auth header*/
    }
}

Таким образом, перехватчик не будет обрабатывать запросы других мнимых клиентов.

Наконец, я установил feignClientName в запрос:

feignClient.postRequest("feign-client-name", postBody);
person Bahadir Tasdemir    schedule 03.03.2020