Adding OkHttp custom interceptor to Feign client

13,183

Solution 1

You should provide an OkHttpClient bean as stated in the doc:

The OkHttpClient and ApacheHttpClient feign clients can be used by setting feign.okhttp.enabled or feign.httpclient.enabled to true, respectively, and having them on the classpath. You can customize the HTTP client used by providing a bean of either ClosableHttpClient when using Apache or OkHttpClient whe using OK HTTP.

https://github.com/OpenFeign/feign/blob/master/okhttp/src/main/java/feign/okhttp/OkHttpClient.java

Solution 2

The solution is to let Spring auto configuration do its job.

In order for that to happen, the following dependency must be removed from the pom.xml file:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.11.0</version>
</dependency>

And the following one must be manually included:

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
</dependency>

Once this is done, everything works as expected with the provided configuration.

Share:
13,183
fps
Author by

fps

I am an expert software developer and architect with 15+ years experience. I also do some software consultancy from time to time.

Updated on June 04, 2022

Comments

  • fps
    fps almost 2 years

    I'm having problems to set up a global OkHttp interceptor for my @FeignClient beans. I'm not experiencing any error, but the interceptor is being ignored.

    My understanding is that Spring Cloud's auto configuration should pick the OkHttpClient.Builder bean that I'm declaring and use it to create the underlying OkHttpClient instances, but I might be wrong about this.

    Here are the relevant parts of my Spring app:

    @SpringBootApplication
    @EnableFeignClients(defaultConfiguration = FeignConfig.class)    
    @EnableCircuitBreaker
    public class MyApp {
    
        public static void main(String[] args) {
            SpringApplication.run(MyApp.class);
        }
    }
    

    @Configuration
    public class FeignConfig {
    
        @Bean
        public MyInterceptor myInterceptor() {
            return new MyInterceptor();
        }
    
        @Bean
        public OkHttpClient.Builder okHttpClientBuilder(MyInterceptor interceptor) {
            return new OkHttpClient.Builder().addInterceptor(interceptor);
        }
    }
    

    public class MyInterceptor implements okhttp3.Interceptor {
    
        @Override
        public Response intercept(Chain chain) throws IOException {
    
            Request request = chain.request();
    
            System.out.println("Hey there, this is my request: " + request);
    
            Response response = chain.proceed(request);
    
            System.out.println("Hey there, this is my response: " + response);
    
            return response;
        }
    
    }
    

    The intercept method above is never called. I need MyInterceptor to be a Spring bean, because I need to inject other dependencies to it.


    @FeignClient(name = "myClient", fallback = MyClientFallback.class)
    public interface MyClient {
    
        // method declarations
    }
    

    @Component
    public class MyClientFallback implements MyClient {
    
        // method fallback implementations
    }
    

    Here's the relevant part of my application.properties file:

    feign.hystrix.enabled = true
    feign.okhttp.enabled = true
    
    ribbon.eureka.enabled = false
    ribbon.eager-load.enabled = true
    ribbon.eager-load.clients = myClient
    
    myClient.ribbon.listOfServers = <IP_LIST>
    myClient.ribbon.ServerListRefreshInterval = 10000
    

    As you see from the properties declared above, I'm not using Eureka and I'm using Ribbon to load balance my rest client. I'm also using Hystrix to enable fallback responses and I have set the feign.okhttp.enabled property to true.


    Below is the info about dependecies config and versions...

    Spring Boot version is 2.0.3.RELEASE and Spring Cloud version is Finchley.SR1, while OkHttp version is 3.11.0.

    In my pom.xml file, I have this spring-cloud-dependencies config:

    <dependencyManagement>
        <dependencies>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
    
            ...
    
        </dependencies>
    </dependencyManagement>
    

    I have also included the following Spring Boot and Spring Cloud dependencies, along with the OkHttp dependency:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
    </parent>
    
    <dependencies>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
    
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.11.0</version>
        </dependency>
    
        ...
    
    </dependencies>
    
  • Mạnh Quyết Nguyễn
    Mạnh Quyết Nguyễn over 5 years
    Did you use Feign OkHttpClient? (not the normal OkHttpClient). Also, try to annotated your OkHttpClient with @Primary
  • fps
    fps over 5 years
    Your solution is correct, I apologize for my previous comments. The wrapper class feign.okhttp.OkHttpClient was not in the classpath, so Spring auto configuration wasn't being triggered. Once I discovered which dependency I had to include, it´s enough to provide a bean of okhttp3.OkHttpClient.Builder class, as I was doing, and Spring will take care of everything. Thank you very much for your help.
  • TheNightsWatch
    TheNightsWatch about 5 years
    Hi Federico, I am facing the same issue. For me request and response to the external service is not printed by following the same code.
  • fps
    fps about 5 years
    @TheNightsWatch Hi! I just included that missing dependency and everything worked fine.
  • TheNightsWatch
    TheNightsWatch about 5 years
    Ok. instead of <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.11.0</version> </dependency> we need to add that dependency? or we need both Okhttp depedencies?
  • fps
    fps about 5 years
    @TheNightsWatch I've double checked my app. You only need the <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> dependency, the <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> one isn't necessary. Thanks for asking about this, I will edit my answer above.
  • min
    min almost 5 years
    Any ways to check if we success "enable" okhttp? it doesn't show okhttp mode on or any obvious info in log
  • fps
    fps almost 5 years
    @user1686407 Sorry, I don't know if there's some logging message that notifies about enabling okhttp. You can always try to change the log level to TRACE or DEBUG and see what's going on...