Skip to content

Commit

Permalink
Add RestClient support
Browse files Browse the repository at this point in the history
  • Loading branch information
larsgrefer committed Jul 26, 2023
1 parent c4260e7 commit d3ef710
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.freefair.spring.okhttp;

import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;

/**
* {@link SpringBootCondition} that applies only when running in a non-reactive web
* application.
*
* @author Phillip Webb
*/
class NotReactiveWebApplicationCondition extends NoneNestedConditions {

NotReactiveWebApplicationCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}

@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
private static class ReactiveWebApplication {

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.freefair.spring.okhttp;

import okhttp3.OkHttpClient;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
import org.springframework.boot.web.client.RestClientCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestClient;

/**
* @author Lars Grefer
* @see RestClientAutoConfiguration
*/
@AutoConfiguration
@ConditionalOnClass({RestClientCustomizer.class, RestClient.class})
@Conditional(NotReactiveWebApplicationCondition.class)
public class OkHttpRestClientAutoConfiguration {

@Bean
public RestClientCustomizer okHttpRestClientCustomizer(OkHttpClient okHttpClient) {
return restClientBuilder -> restClientBuilder.requestFactory(new OkHttp3ClientHttpRequestFactory(okHttpClient));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.web.client.RestTemplateBuilderConfigurer;
Expand All @@ -23,7 +21,7 @@
*/
@AutoConfiguration(before = RestTemplateAutoConfiguration.class, after = HttpMessageConvertersAutoConfiguration.class)
@ConditionalOnClass({RestTemplateCustomizer.class, RestTemplate.class})
@Conditional(OkHttpRestTemplateAutoConfiguration.NotReactiveWebApplicationCondition.class)
@Conditional(NotReactiveWebApplicationCondition.class)
public class OkHttpRestTemplateAutoConfiguration {

@Bean
Expand All @@ -36,17 +34,4 @@ public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer res
return restTemplateBuilderConfigurer.configure(builder);
}

static class NotReactiveWebApplicationCondition extends NoneNestedConditions {

NotReactiveWebApplicationCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}

@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
private static class ReactiveWebApplication {

}

}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
io.freefair.spring.okhttp.OkHttp3AutoConfiguration
io.freefair.spring.okhttp.OkHttpRestClientAutoConfiguration
io.freefair.spring.okhttp.OkHttpRestTemplateAutoConfiguration
io.freefair.spring.okhttp.metrics.OkHttpMetricsAutoConfiguration
io.freefair.spring.okhttp.logging.OkHttp3LoggingInterceptorAutoConfiguration
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.freefair.spring.okhttp;

import okhttp3.OkHttpClient;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.client.AbstractClientHttpRequestFactoryWrapper;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestClient;

import java.lang.reflect.Field;
import java.time.Duration;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE,
properties = {
"okhttp.read-timeout=21s",
"okhttp.connect-timeout=21s",
"okhttp.write-timeout=21s"
})
class OkHttpRestClientAutoConfigurationTest {

@Autowired
private RestClient.Builder restClientBuilder;

@Test
void testTimeouts() throws NoSuchFieldException, IllegalAccessException {
RestClient restTemplate = restClientBuilder.build();

OkHttpClient client = extractClient(restTemplate);

assertThat(client.connectTimeoutMillis()).isEqualTo(Duration.ofSeconds(21).toMillis());
assertThat(client.readTimeoutMillis()).isEqualTo(Duration.ofSeconds(21).toMillis());
assertThat(client.writeTimeoutMillis()).isEqualTo(Duration.ofSeconds(21).toMillis());
}

private OkHttpClient extractClient(RestClient restClient) throws NoSuchFieldException, IllegalAccessException {

Field clientRequestFactoryField = restClient.getClass().getDeclaredField("clientRequestFactory");
clientRequestFactoryField.setAccessible(true);
ClientHttpRequestFactory requestFactory = (ClientHttpRequestFactory) clientRequestFactoryField.get(restClient);

while (requestFactory instanceof AbstractClientHttpRequestFactoryWrapper) {
Field field = AbstractClientHttpRequestFactoryWrapper.class.getDeclaredField("requestFactory");
field.setAccessible(true);
requestFactory = (ClientHttpRequestFactory) field.get(requestFactory);
}

assertThat(requestFactory).isInstanceOf(OkHttp3ClientHttpRequestFactory.class);

Field field = OkHttp3ClientHttpRequestFactory.class.getDeclaredField("client");
field.setAccessible(true);
return (OkHttpClient) field.get(requestFactory);
}


@SpringBootConfiguration
@EnableAutoConfiguration
public static class TestConfiguration {

}
}

0 comments on commit d3ef710

Please sign in to comment.