Skip to content

Commit de1949a

Browse files
Fix: TLS Upgrade config propagates to RestTemplate (#662)
1 parent 67ecf24 commit de1949a

File tree

5 files changed

+79
-9
lines changed

5 files changed

+79
-9
lines changed

cloudplatform/connectivity-apache-httpclient5/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/ApacheHttpClient5Wrapper.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import java.net.URI;
99
import java.net.URISyntaxException;
1010

11+
import org.apache.hc.client5.http.config.Configurable;
12+
import org.apache.hc.client5.http.config.RequestConfig;
1113
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
1214
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
1315
import org.apache.hc.core5.http.ClassicHttpRequest;
@@ -30,11 +32,12 @@
3032
* and it will append the url configured in the destination.
3133
*/
3234
@Slf4j
33-
class ApacheHttpClient5Wrapper extends CloseableHttpClient
35+
class ApacheHttpClient5Wrapper extends CloseableHttpClient implements Configurable
3436
{
3537
private final CloseableHttpClient httpClient;
3638
@Getter( AccessLevel.PACKAGE )
3739
private final HttpDestinationProperties destination;
40+
private final RequestConfig requestConfig;
3841

3942
@Override
4043
public void close()
@@ -49,7 +52,10 @@ public void close( final CloseMode closeMode )
4952
httpClient.close(closeMode);
5053
}
5154

52-
ApacheHttpClient5Wrapper( final CloseableHttpClient httpClient, final HttpDestinationProperties destination )
55+
ApacheHttpClient5Wrapper(
56+
final CloseableHttpClient httpClient,
57+
final HttpDestinationProperties destination,
58+
final RequestConfig requestConfig )
5359
{
5460
this.httpClient = httpClient;
5561

@@ -62,6 +68,7 @@ public void close( final CloseMode closeMode )
6268
""");
6369
}
6470
this.destination = destination;
71+
this.requestConfig = requestConfig;
6572
}
6673

6774
@Override
@@ -86,7 +93,7 @@ ApacheHttpClient5Wrapper withDestination( final HttpDestinationProperties destin
8693
if( destination == this.destination ) {
8794
return this;
8895
}
89-
return new ApacheHttpClient5Wrapper(httpClient, destination);
96+
return new ApacheHttpClient5Wrapper(httpClient, destination, requestConfig);
9097
}
9198

9299
ClassicHttpRequest wrapRequest( final ClassicHttpRequest request )
@@ -119,4 +126,10 @@ ClassicHttpRequest wrapRequest( final ClassicHttpRequest request )
119126

120127
return requestBuilder.build();
121128
}
129+
130+
@Override
131+
public RequestConfig getConfig()
132+
{
133+
return requestConfig;
134+
}
122135
}

cloudplatform/connectivity-apache-httpclient5/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5Factory.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,25 @@ public HttpClient createHttpClient( @Nullable final HttpDestinationProperties de
7777
throws DestinationAccessException,
7878
HttpClientInstantiationException
7979
{
80-
final CloseableHttpClient httpClient = buildHttpClient(destination);
80+
final var requestConfig = getRequestConfig(destination);
81+
final CloseableHttpClient httpClient = buildHttpClient(destination, requestConfig);
8182
if( destination == null ) {
8283
return httpClient;
8384
}
8485

85-
return new ApacheHttpClient5Wrapper(httpClient, destination);
86+
return new ApacheHttpClient5Wrapper(httpClient, destination, requestConfig);
8687
}
8788

8889
@Nonnull
89-
private CloseableHttpClient buildHttpClient( @Nullable final HttpDestinationProperties destination )
90+
private CloseableHttpClient buildHttpClient(
91+
@Nullable final HttpDestinationProperties destination,
92+
@Nonnull final RequestConfig requestConfig )
9093
{
9194
final HttpClientBuilder builder =
9295
HttpClients
9396
.custom()
9497
.setConnectionManager(getConnectionManager(destination))
95-
.setDefaultRequestConfig(getRequestConfig(destination))
98+
.setDefaultRequestConfig(requestConfig)
9699
.setProxy(getProxy(destination));
97100

98101
if( requestInterceptor != null ) {

cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/HttpClientWrapperTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import java.util.List;
88

9+
import org.apache.hc.client5.http.config.RequestConfig;
910
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
1011
import org.junit.jupiter.api.Test;
1112

@@ -21,7 +22,7 @@ void testDestinationWrapping()
2122
DefaultHttpDestination.builder("http://foo.com").headerProviders(c -> List.of()).build();
2223
final DefaultHttpDestination thirdDestination = DefaultHttpDestination.builder("http://bar.com").build();
2324
final ApacheHttpClient5Wrapper sut =
24-
new ApacheHttpClient5Wrapper(mock(CloseableHttpClient.class), firstDestination);
25+
new ApacheHttpClient5Wrapper(mock(CloseableHttpClient.class), firstDestination, mock(RequestConfig.class));
2526

2627
assertThat(sut.withDestination(firstDestination)).isSameAs(sut);
2728
assertThat(sut.withDestination(firstDestination)).isNotSameAs(sut.withDestination(secondDestination));

datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientViaConstructorTest.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
package com.sap.cloud.sdk.services.openapi.apiclient;
66

7+
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
8+
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
9+
import static com.github.tomakehurst.wiremock.client.WireMock.get;
10+
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
11+
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
12+
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
13+
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
714
import static org.assertj.core.api.Assertions.assertThat;
815
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
916

@@ -18,6 +25,7 @@
1825
import org.springframework.http.HttpHeaders;
1926
import org.springframework.http.HttpMethod;
2027
import org.springframework.http.MediaType;
28+
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
2129
import org.springframework.test.web.client.ExpectedCount;
2230
import org.springframework.test.web.client.MockRestServiceServer;
2331
import org.springframework.test.web.client.response.MockRestResponseCreators;
@@ -27,8 +35,14 @@
2735
import org.springframework.web.util.UriComponentsBuilder;
2836

2937
import com.fasterxml.jackson.annotation.JsonProperty;
38+
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
39+
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
40+
import com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5FactoryBuilder;
41+
import com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5FactoryBuilder.TlsUpgrade;
42+
import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination;
3043
import com.sap.cloud.sdk.services.openapi.core.AbstractOpenApiService;
3144

45+
@WireMockTest
3246
class ApiClientViaConstructorTest
3347
{
3448
private static final String RELATIVE_PATH = "/apiEndpoint";
@@ -121,6 +135,45 @@ void testApiClientWithQueryParams()
121135
server.verify();
122136
}
123137

138+
@Test
139+
void testHttpRequestConfigIsTransmitted( WireMockRuntimeInfo wm )
140+
{
141+
httpRequest(TlsUpgrade.DISABLED, wm.getHttpBaseUrl());
142+
verify(getRequestedFor(anyUrl()).withoutHeader("Upgrade"));
143+
144+
httpRequest(TlsUpgrade.ENABLED, wm.getHttpBaseUrl());
145+
verify(getRequestedFor(anyUrl()).withHeader("Upgrade", equalTo("TLS/1.2")));
146+
}
147+
148+
private static void httpRequest( TlsUpgrade toggle, String url )
149+
{
150+
var sut = new ApacheHttpClient5FactoryBuilder().tlsUpgrade(toggle).build();
151+
var httpClient = sut.createHttpClient(DefaultHttpDestination.builder(url).build());
152+
var clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
153+
var restTemplate = new RestTemplate(clientHttpRequestFactory);
154+
var apiClient = new ApiClient(restTemplate);
155+
apiClient.setBasePath(url);
156+
157+
stubFor(get(anyUrl()).willReturn(ok("success")));
158+
159+
assertThat(
160+
apiClient
161+
.invokeAPI(
162+
"/apiEndpoint",
163+
HttpMethod.GET,
164+
null,
165+
null,
166+
new HttpHeaders(),
167+
null,
168+
null,
169+
null,
170+
null,
171+
new ParameterizedTypeReference<String>()
172+
{
173+
}))
174+
.isEqualTo("success");
175+
}
176+
124177
private static class MyDto
125178
{
126179
@JsonProperty( "Return" )

release_notes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@
2424

2525
### 🐛 Fixed Issues
2626

27-
-
27+
- Fix ApacheHttpClient5Wrapper to propagate the configuration to Spring RestTemplate.

0 commit comments

Comments
 (0)