Adding OkHttp custom interceptor to Feign client
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.
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, 2022Comments
-
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 underlyingOkHttpClient
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 needMyInterceptor
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 totrue
.
Below is the info about dependecies config and versions...
Spring Boot version is
2.0.3.RELEASE
and Spring Cloud version isFinchley.SR1
, whileOkHttp
version is3.11.0
.In my
pom.xml
file, I have thisspring-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 over 5 yearsDid you use
Feign OkHttpClient
? (not the normal OkHttpClient). Also, try to annotated yourOkHttpClient
with@Primary
-
fps over 5 yearsYour 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 ofokhttp3.OkHttpClient.Builder
class, as I was doing, and Spring will take care of everything. Thank you very much for your help. -
TheNightsWatch about 5 yearsHi 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 about 5 years@TheNightsWatch Hi! I just included that missing dependency and everything worked fine.
-
TheNightsWatch about 5 yearsOk. 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 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 almost 5 yearsAny ways to check if we success "enable" okhttp? it doesn't show
okhttp mode on
or any obvious info in log -
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...