From f26568b4d566df0362ef6f15b074fe20859eaadd Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Tue, 15 Sep 2026 18:31:10 +0200 Subject: [PATCH] fix: [OData] Make CSRF token call opt-in --- .../ApacheHttpClient5FactoryBuilder.java | 25 +++++- .../DefaultApacheHttpClient5Factory.java | 22 +++-- .../ApacheHttpClient5FactoryBuilderTest.java | 66 +++++++++++++++ .../DefaultApacheHttpClient5CacheTest.java | 3 +- .../DefaultApacheHttpClient5FactoryTest.java | 15 ++-- .../odata-client-apache-httpclient5/pom.xml | 9 +- .../ODataApacheHttpClient5Accessor.java | 48 +++++++++++ .../ODataApacheHttpClient5AccessorTest.java | 84 +++++++++++++++++++ .../ODataClientQueryBatchUnitTest.java | 15 ++-- .../request/ODataRequestActionTest.java | 7 +- 10 files changed, 263 insertions(+), 31 deletions(-) create mode 100644 datamodel/odata-client-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/client/ODataApacheHttpClient5Accessor.java create mode 100644 datamodel/odata-client-apache-httpclient5/src/test/java/com/sap/cloud/sdk/datamodel/odata/client/ODataApacheHttpClient5AccessorTest.java diff --git a/cloudplatform/connectivity-apache-httpclient5/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/ApacheHttpClient5FactoryBuilder.java b/cloudplatform/connectivity-apache-httpclient5/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/ApacheHttpClient5FactoryBuilder.java index 527249bb74..9f07e5f671 100644 --- a/cloudplatform/connectivity-apache-httpclient5/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/ApacheHttpClient5FactoryBuilder.java +++ b/cloudplatform/connectivity-apache-httpclient5/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/ApacheHttpClient5FactoryBuilder.java @@ -20,6 +20,7 @@ public class ApacheHttpClient5FactoryBuilder private TlsUpgrade tlsUpgrade = TlsUpgrade.AUTOMATIC; private int maxConnectionsTotal = DefaultApacheHttpClient5Factory.DEFAULT_MAX_CONNECTIONS_TOTAL; private int maxConnectionsPerRoute = DefaultApacheHttpClient5Factory.DEFAULT_MAX_CONNECTIONS_PER_ROUTE; + private boolean csrfTokenInterceptorEnabled = false; /** * Enum to control the automatic TLS upgrade feature for insecure connections. @@ -145,6 +146,27 @@ public ApacheHttpClient5FactoryBuilder maxConnectionsPerRoute( final int maxConn return this; } + /** + * Enables the {@link CsrfTokenInterceptor} on {@link HttpClient} instances created by the to-be-built + * {@link ApacheHttpClient5Factory}. + *

+ * When enabled, the interceptor automatically fetches a CSRF token via a HEAD request before every mutating HTTP + * request (POST, PUT, PATCH, DELETE) that does not already carry an {@code x-csrf-token} header. This is required + * when communicating with OData services that enforce CSRF protection. + *

+ * By default, the CSRF token interceptor is disabled. Enable it when the built client will be used to call + * OData services. For general-purpose HTTP clients or REST/OpenAPI services that do not require CSRF protection, + * leave this disabled to avoid unnecessary HEAD requests. + * + * @return This builder. + */ + @Nonnull + public ApacheHttpClient5FactoryBuilder withCsrfTokenInterceptor() + { + this.csrfTokenInterceptorEnabled = true; + return this; + } + /** * Builds a new {@link ApacheHttpClient5Factory} instance with the previously configured parameters. * @@ -158,6 +180,7 @@ public ApacheHttpClient5Factory build() maxConnectionsTotal, maxConnectionsPerRoute, null, - tlsUpgrade); + tlsUpgrade, + csrfTokenInterceptorEnabled); } } diff --git a/cloudplatform/connectivity-apache-httpclient5/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5Factory.java b/cloudplatform/connectivity-apache-httpclient5/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5Factory.java index 7b7c0350e3..6c976f4f86 100644 --- a/cloudplatform/connectivity-apache-httpclient5/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5Factory.java +++ b/cloudplatform/connectivity-apache-httpclient5/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5Factory.java @@ -59,18 +59,22 @@ class DefaultApacheHttpClient5Factory implements ApacheHttpClient5Factory @Nonnull private final ApacheHttpClient5FactoryBuilder.TlsUpgrade tlsUpgrade; + private final boolean csrfTokenInterceptorEnabled; + DefaultApacheHttpClient5Factory( @Nonnull final Duration timeout, final int maxConnectionsTotal, final int maxConnectionsPerRoute, @Nullable final HttpRequestInterceptor requestInterceptor, - @Nonnull final ApacheHttpClient5FactoryBuilder.TlsUpgrade tlsUpgrade ) + @Nonnull final ApacheHttpClient5FactoryBuilder.TlsUpgrade tlsUpgrade, + final boolean csrfTokenInterceptorEnabled ) { this.timeout = toTimeout(timeout); this.maxConnectionsTotal = maxConnectionsTotal; this.maxConnectionsPerRoute = maxConnectionsPerRoute; this.requestInterceptor = requestInterceptor; this.tlsUpgrade = tlsUpgrade; + this.csrfTokenInterceptorEnabled = csrfTokenInterceptorEnabled; } @Nonnull @@ -105,12 +109,16 @@ private CloseableHttpClient buildHttpClient( builder.addRequestInterceptorFirst(requestInterceptor); } - final AtomicReference holder = new AtomicReference<>(); - builder - .addRequestInterceptorLast( - ( req, entity, ctx ) -> new CsrfTokenInterceptor(holder.get()).process(req, entity, ctx)); - holder.set(builder.build()); - return holder.get(); + if( csrfTokenInterceptorEnabled ) { + final AtomicReference holder = new AtomicReference<>(); + builder + .addRequestInterceptorLast( + ( req, entity, ctx ) -> new CsrfTokenInterceptor(holder.get()).process(req, entity, ctx)); + holder.set(builder.build()); + return holder.get(); + } + + return builder.build(); } @Nonnull diff --git a/cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/ApacheHttpClient5FactoryBuilderTest.java b/cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/ApacheHttpClient5FactoryBuilderTest.java index de5f6a7523..3bc7e04957 100644 --- a/cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/ApacheHttpClient5FactoryBuilderTest.java +++ b/cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/ApacheHttpClient5FactoryBuilderTest.java @@ -1,11 +1,31 @@ package com.sap.cloud.sdk.cloudplatform.connectivity; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.head; +import static com.github.tomakehurst.wiremock.client.WireMock.headRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.noContent; +import static com.github.tomakehurst.wiremock.client.WireMock.ok; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; import static org.assertj.core.api.Assertions.assertThatNoException; +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.classic.methods.HttpPost; import org.junit.jupiter.api.Test; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; + +import lombok.SneakyThrows; + +@WireMockTest class ApacheHttpClient5FactoryBuilderTest { + private static final String SERVICE_PATH = "/service/"; + private static final String RESOURCE_PATH = SERVICE_PATH + "Entity"; + private static final String CSRF_TOKEN = "test-token"; @Test void testBuilderContainsOptionalParametersOnly() @@ -13,4 +33,50 @@ void testBuilderContainsOptionalParametersOnly() // make sure we can build a new factory instance without supplying any parameters assertThatNoException().isThrownBy(() -> new ApacheHttpClient5FactoryBuilder().build()); } + + @Test + @SneakyThrows + void csrfInterceptorIsDisabledByDefault( final WireMockRuntimeInfo wm ) + { + wm.getWireMock().register(post(urlEqualTo(RESOURCE_PATH)).willReturn(noContent())); + + final DefaultHttpDestination destination = DefaultHttpDestination.builder(wm.getHttpBaseUrl()).build(); + final HttpClient client = new ApacheHttpClient5FactoryBuilder().build().createHttpClient(destination); + + client.execute(new HttpPost(RESOURCE_PATH), r -> null); + + wm.getWireMock().verifyThat(1, postRequestedFor(urlEqualTo(RESOURCE_PATH))); + wm.getWireMock().verifyThat(0, headRequestedFor(anyUrl())); + } + + @Test + @SneakyThrows + void csrfInterceptorIsEnabledWhenOptedIn( final WireMockRuntimeInfo wm ) + { + wm + .getWireMock() + .register( + head(urlEqualTo(SERVICE_PATH)) + .willReturn(ok().withHeader(CsrfTokenInterceptor.X_CSRF_TOKEN_HEADER_KEY, CSRF_TOKEN))); + wm.getWireMock().register(post(urlEqualTo(RESOURCE_PATH)).willReturn(noContent())); + + final DefaultHttpDestination destination = DefaultHttpDestination.builder(wm.getHttpBaseUrl()).build(); + final HttpClient client = + new ApacheHttpClient5FactoryBuilder().withCsrfTokenInterceptor().build().createHttpClient(destination); + + client.execute(new HttpPost(RESOURCE_PATH), r -> null); + + wm + .getWireMock() + .verifyThat( + 1, + headRequestedFor(urlEqualTo(SERVICE_PATH)) + .withHeader(CsrfTokenInterceptor.X_CSRF_TOKEN_HEADER_KEY, equalTo("fetch"))); + wm + .getWireMock() + .verifyThat( + 1, + postRequestedFor(urlEqualTo(RESOURCE_PATH)) + .withHeader(CsrfTokenInterceptor.X_CSRF_TOKEN_HEADER_KEY, equalTo(CSRF_TOKEN))); + } } diff --git a/cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5CacheTest.java b/cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5CacheTest.java index 64acf6973e..a1757e9033 100644 --- a/cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5CacheTest.java +++ b/cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5CacheTest.java @@ -62,7 +62,8 @@ class DefaultApacheHttpClient5CacheTest DefaultApacheHttpClient5Factory.DEFAULT_MAX_CONNECTIONS_TOTAL, DefaultApacheHttpClient5Factory.DEFAULT_MAX_CONNECTIONS_PER_ROUTE, null, - ApacheHttpClient5FactoryBuilder.TlsUpgrade.AUTOMATIC); + ApacheHttpClient5FactoryBuilder.TlsUpgrade.AUTOMATIC, + false); private static final long NANOSECONDS_IN_MINUTE = 60_000_000_000L; private static final Duration TEN_MINUTES = Duration.ofMinutes(10L); diff --git a/cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5FactoryTest.java b/cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5FactoryTest.java index 80a9e6e01c..408ad06699 100644 --- a/cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5FactoryTest.java +++ b/cloudplatform/connectivity-apache-httpclient5/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DefaultApacheHttpClient5FactoryTest.java @@ -86,7 +86,8 @@ void setup() MAX_CONNECTIONS, MAX_CONNECTIONS_PER_ROUTE, requestInterceptor, - AUTOMATIC); + AUTOMATIC, + false); } @Test @@ -101,7 +102,8 @@ void testHttpClientUsesTimeout() MAX_CONNECTIONS, MAX_CONNECTIONS_PER_ROUTE, requestInterceptor, - AUTOMATIC); + AUTOMATIC, + false); final ApacheHttpClient5Factory factoryWithEnoughTimeout = new DefaultApacheHttpClient5Factory( @@ -109,7 +111,8 @@ void testHttpClientUsesTimeout() MAX_CONNECTIONS, MAX_CONNECTIONS_PER_ROUTE, requestInterceptor, - AUTOMATIC); + AUTOMATIC, + false); final ClassicHttpRequest request = new HttpGet(WIRE_MOCK_SERVER.url("/timeout")); @@ -138,7 +141,8 @@ void testHttpClientUsesMaxConnections() 1, MAX_CONNECTIONS_PER_ROUTE, requestInterceptor, - AUTOMATIC); + AUTOMATIC, + false); final HttpClient client = sut.createHttpClient(); final ClassicHttpRequest firstRequest = new HttpGet(WIRE_MOCK_SERVER.url("/max-connections-1")); @@ -161,7 +165,8 @@ void testHttpClientUsesMaxConnectionsPerRoute() MAX_CONNECTIONS, 1, requestInterceptor, - AUTOMATIC); + AUTOMATIC, + false); final ClassicHttpRequest firstRequest = new HttpGet(WIRE_MOCK_SERVER.url("/max-connections-per-route")); final ClassicHttpRequest secondRequest = new HttpGet(SECOND_WIRE_MOCK_SERVER.url("/max-connections-per-route")); diff --git a/datamodel/odata-client-apache-httpclient5/pom.xml b/datamodel/odata-client-apache-httpclient5/pom.xml index 1f38f558e4..d0ab2a931e 100644 --- a/datamodel/odata-client-apache-httpclient5/pom.xml +++ b/datamodel/odata-client-apache-httpclient5/pom.xml @@ -39,6 +39,10 @@ com.sap.cloud.sdk.cloudplatform connectivity-apache-httpclient5 + + com.sap.cloud.sdk.cloudplatform + cloudplatform-connectivity + io.vavr vavr @@ -79,11 +83,6 @@ cloudplatform-core test - - com.sap.cloud.sdk.cloudplatform - cloudplatform-connectivity - test - org.junit.jupiter junit-jupiter-api diff --git a/datamodel/odata-client-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/client/ODataApacheHttpClient5Accessor.java b/datamodel/odata-client-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/client/ODataApacheHttpClient5Accessor.java new file mode 100644 index 0000000000..a1c92aff0c --- /dev/null +++ b/datamodel/odata-client-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/client/ODataApacheHttpClient5Accessor.java @@ -0,0 +1,48 @@ +package com.sap.cloud.sdk.datamodel.odata.client; + +import javax.annotation.Nonnull; + +import org.apache.hc.client5.http.classic.HttpClient; + +import com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5Factory; +import com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5FactoryBuilder; +import com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestinationProperties; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +/** + * Accessor for {@link HttpClient} instances suitable for OData requests. + *

+ * Unlike the general-purpose {@link com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5Accessor}, clients + * created here have a CSRF token interceptor enabled (see + * {@link com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5FactoryBuilder#withCsrfTokenInterceptor()}). + * The interceptor automatically fetches a CSRF token via a HEAD request before every mutating HTTP request (POST, PUT, + * PATCH, DELETE) that does not already carry an {@code x-csrf-token} header, which is required for OData services that + * enforce CSRF protection. + *

+ * For non-OData use cases (REST, OpenAPI) use + * {@link com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5Accessor} instead to avoid unnecessary CSRF HEAD + * requests. + * + * @since 5.35.0 + */ +@NoArgsConstructor( access = AccessLevel.PRIVATE ) +public final class ODataApacheHttpClient5Accessor +{ + private static final ApacheHttpClient5Factory FACTORY = + new ApacheHttpClient5FactoryBuilder().withCsrfTokenInterceptor().build(); + + /** + * Returns an {@link HttpClient} for the given destination with the CSRF token interceptor enabled. + * + * @param destination + * The destination to get the {@link HttpClient} for. + * @return An {@link HttpClient} configured for OData communication with the given destination. + */ + @Nonnull + public static HttpClient getHttpClient( @Nonnull final HttpDestinationProperties destination ) + { + return FACTORY.createHttpClient(destination); + } +} diff --git a/datamodel/odata-client-apache-httpclient5/src/test/java/com/sap/cloud/sdk/datamodel/odata/client/ODataApacheHttpClient5AccessorTest.java b/datamodel/odata-client-apache-httpclient5/src/test/java/com/sap/cloud/sdk/datamodel/odata/client/ODataApacheHttpClient5AccessorTest.java new file mode 100644 index 0000000000..0319d1adfa --- /dev/null +++ b/datamodel/odata-client-apache-httpclient5/src/test/java/com/sap/cloud/sdk/datamodel/odata/client/ODataApacheHttpClient5AccessorTest.java @@ -0,0 +1,84 @@ +package com.sap.cloud.sdk.datamodel.odata.client; + +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.head; +import static com.github.tomakehurst.wiremock.client.WireMock.headRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.noContent; +import static com.github.tomakehurst.wiremock.client.WireMock.ok; +import static com.github.tomakehurst.wiremock.client.WireMock.okJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.hc.client5.http.classic.HttpClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination; +import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestAction; +import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestRead; +import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestResult; +import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestResultGeneric; + +@WireMockTest +class ODataApacheHttpClient5AccessorTest +{ + private static final String SERVICE_PATH = "/service/"; + private static final String ENTITY_SET = "Entities"; + private static final String ACTION_NAME = "TestAction"; + private static final String CSRF_TOKEN = "test-csrf-token"; + private static final String X_CSRF_TOKEN = "x-csrf-token"; + + private HttpClient client; + + @BeforeEach + void setup( final WireMockRuntimeInfo wm ) + { + final DefaultHttpDestination destination = DefaultHttpDestination.builder(wm.getHttpBaseUrl()).build(); + client = ODataApacheHttpClient5Accessor.getHttpClient(destination); + } + + @Test + void csrfTokenIsFetchedForMutatingODataRequests( final WireMockRuntimeInfo wm ) + { + wm + .getWireMock() + .register(head(urlPathEqualTo(SERVICE_PATH)).willReturn(ok().withHeader(X_CSRF_TOKEN, CSRF_TOKEN))); + wm.getWireMock().register(post(urlPathEqualTo(SERVICE_PATH + ACTION_NAME)).willReturn(noContent())); + + final ODataRequestAction request = new ODataRequestAction(SERVICE_PATH, ACTION_NAME, null, ODataProtocol.V4); + final ODataRequestResult result = request.execute(client); + + assertThat(result).isNotNull(); + + wm + .getWireMock() + .verifyThat(1, headRequestedFor(urlPathEqualTo(SERVICE_PATH)).withHeader(X_CSRF_TOKEN, equalTo("fetch"))); + wm + .getWireMock() + .verifyThat( + 1, + postRequestedFor(urlPathEqualTo(SERVICE_PATH + ACTION_NAME)) + .withHeader(X_CSRF_TOKEN, equalTo(CSRF_TOKEN))); + } + + @Test + void noHeadRequestForReadRequests( final WireMockRuntimeInfo wm ) + { + wm.getWireMock().register(get(urlPathEqualTo(SERVICE_PATH + ENTITY_SET)).willReturn(okJson("{\"value\":[]}"))); + + final ODataRequestRead request = new ODataRequestRead(SERVICE_PATH, ENTITY_SET, "", ODataProtocol.V4); + final ODataRequestResultGeneric result = request.execute(client); + + assertThat(result).isNotNull(); + + wm.getWireMock().verifyThat(0, headRequestedFor(anyUrl())); + wm.getWireMock().verifyThat(1, getRequestedFor(urlPathEqualTo(SERVICE_PATH + ENTITY_SET))); + } +} diff --git a/datamodel/odata-client-apache-httpclient5/src/test/java/com/sap/cloud/sdk/datamodel/odata/client/request/ODataClientQueryBatchUnitTest.java b/datamodel/odata-client-apache-httpclient5/src/test/java/com/sap/cloud/sdk/datamodel/odata/client/request/ODataClientQueryBatchUnitTest.java index d7f6bbd34b..143a207291 100644 --- a/datamodel/odata-client-apache-httpclient5/src/test/java/com/sap/cloud/sdk/datamodel/odata/client/request/ODataClientQueryBatchUnitTest.java +++ b/datamodel/odata-client-apache-httpclient5/src/test/java/com/sap/cloud/sdk/datamodel/odata/client/request/ODataClientQueryBatchUnitTest.java @@ -33,9 +33,8 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import com.google.common.io.Resources; -import com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5Accessor; import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination; -import com.sap.cloud.sdk.cloudplatform.connectivity.Destination; +import com.sap.cloud.sdk.datamodel.odata.client.ODataApacheHttpClient5Accessor; import com.sap.cloud.sdk.datamodel.odata.client.ODataProtocol; import com.sap.cloud.sdk.datamodel.odata.client.exception.ODataConnectionException; import com.sap.cloud.sdk.datamodel.odata.client.exception.ODataRequestException; @@ -56,7 +55,7 @@ class ODataClientQueryBatchUnitTest private static ODataRequestUpdate SAMPLE_REQUEST_UPDATE; private WireMockServer wireMockServer; - private Destination destination; + private DefaultHttpDestination destination; private final AtomicInteger uuidCounter = new AtomicInteger(0); private final Supplier uuidProvider = () -> new UUID(0, uuidCounter.incrementAndGet()); @@ -117,7 +116,7 @@ void testEmptyBatch() assertThat(request.getBatchRequestBody()).isEqualTo(requestBody); // check request execution - final HttpClient client = ApacheHttpClient5Accessor.getHttpClient(destination); + final HttpClient client = ODataApacheHttpClient5Accessor.getHttpClient(destination); wireMockServer.stubFor(post(urlPathEqualTo(SERVICE_PATH_BATCH)).willReturn(okJson("{}"))); final ODataRequestResult result = request.execute(client); @@ -146,7 +145,7 @@ void testEmptyChangesetBatch() assertThat(request.getBatchRequestBody()).isEqualTo(requestBody); // check request execution - final HttpClient client = ApacheHttpClient5Accessor.getHttpClient(destination); + final HttpClient client = ODataApacheHttpClient5Accessor.getHttpClient(destination); wireMockServer.stubFor(post(urlPathEqualTo(SERVICE_PATH_BATCH)).willReturn(okJson("{}"))); final ODataRequestResult result = request.execute(client); @@ -175,7 +174,7 @@ void testReadOnlyBatch() assertThat(request.getBatchRequestBody()).isEqualTo(requestBody); // check request execution - final HttpClient client = ApacheHttpClient5Accessor.getHttpClient(destination); + final HttpClient client = ODataApacheHttpClient5Accessor.getHttpClient(destination); wireMockServer.stubFor(post(urlPathEqualTo(SERVICE_PATH_BATCH)).willReturn(okJson("{}"))); final ODataRequestResult result = request.execute(client); @@ -205,7 +204,7 @@ void testReadOnlyBatchForceConnectionLeaks() assertThat(request.getBatchRequestBody()).isEqualTo(requestBody); // check request execution - final HttpClient client = ApacheHttpClient5Accessor.getHttpClient(destination); + final HttpClient client = ODataApacheHttpClient5Accessor.getHttpClient(destination); wireMockServer.stubFor(post(urlPathEqualTo(SERVICE_PATH_BATCH)).willReturn(okJson("{}"))); try { @@ -243,7 +242,7 @@ void testCombinedBatch() assertThat(request.getBatchRequestBody()).isEqualTo(requestBody); // check request execution - final HttpClient client = ApacheHttpClient5Accessor.getHttpClient(destination); + final HttpClient client = ODataApacheHttpClient5Accessor.getHttpClient(destination); wireMockServer.stubFor(post(urlPathEqualTo(SERVICE_PATH_BATCH)).willReturn(okJson("{}"))); final ODataRequestResult result = request.execute(client); diff --git a/datamodel/odata-client-apache-httpclient5/src/test/java/com/sap/cloud/sdk/datamodel/odata/client/request/ODataRequestActionTest.java b/datamodel/odata-client-apache-httpclient5/src/test/java/com/sap/cloud/sdk/datamodel/odata/client/request/ODataRequestActionTest.java index c366e38b71..c99189a622 100644 --- a/datamodel/odata-client-apache-httpclient5/src/test/java/com/sap/cloud/sdk/datamodel/odata/client/request/ODataRequestActionTest.java +++ b/datamodel/odata-client-apache-httpclient5/src/test/java/com/sap/cloud/sdk/datamodel/odata/client/request/ODataRequestActionTest.java @@ -22,9 +22,8 @@ import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import com.github.tomakehurst.wiremock.junit5.WireMockExtension; import com.google.gson.GsonBuilder; -import com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5Accessor; import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination; -import com.sap.cloud.sdk.cloudplatform.connectivity.Destination; +import com.sap.cloud.sdk.datamodel.odata.client.ODataApacheHttpClient5Accessor; import com.sap.cloud.sdk.datamodel.odata.client.ODataProtocol; import com.sap.cloud.sdk.datamodel.odata.client.expression.ODataResourcePath; @@ -44,8 +43,8 @@ class ODataRequestActionTest @BeforeEach void setup() { - final Destination destination = DefaultHttpDestination.builder(wireMockServer.baseUrl()).build(); - client = ApacheHttpClient5Accessor.getHttpClient(destination); + final DefaultHttpDestination destination = DefaultHttpDestination.builder(wireMockServer.baseUrl()).build(); + client = ODataApacheHttpClient5Accessor.getHttpClient(destination); } @Test