diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 18c63fa3c84..8ff05447005 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -390,7 +390,7 @@ bom { ] } } - library("HttpClient5", "5.1.4") { + library("HttpClient5", "5.2.1") { group("org.apache.httpcomponents.client5") { modules = [ "httpclient5", diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/HttpClientTransport.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/HttpClientTransport.java index bf2aa2982bb..c0387e12243 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/HttpClientTransport.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/HttpClientTransport.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * 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. @@ -144,7 +144,7 @@ abstract class HttpClientTransport implements HttpTransport { private Response execute(HttpUriRequest request) { try { - ClassicHttpResponse response = this.client.execute(this.host, request); + ClassicHttpResponse response = this.client.executeOpen(this.host, request, null); int statusCode = response.getCode(); if (statusCode >= 400 && statusCode <= 500) { HttpEntity entity = response.getEntity(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/transport/HttpClientTransportTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/transport/HttpClientTransportTests.java index 2f77941c5dd..dd8472e458b 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/transport/HttpClientTransportTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/transport/HttpClientTransportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * 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. @@ -47,6 +47,7 @@ import org.springframework.util.StreamUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.then; @@ -98,7 +99,7 @@ class HttpClientTransportTests { given(this.entity.getContent()).willReturn(this.content); given(this.response.getCode()).willReturn(200); Response response = this.http.get(this.uri); - then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture()); + then(this.client).should().executeOpen(this.hostCaptor.capture(), this.requestCaptor.capture(), isNull()); HttpUriRequest request = this.requestCaptor.getValue(); assertThat(request).isInstanceOf(HttpGet.class); assertThat(request.getUri()).isEqualTo(this.uri); @@ -112,7 +113,7 @@ class HttpClientTransportTests { given(this.entity.getContent()).willReturn(this.content); given(this.response.getCode()).willReturn(200); Response response = this.http.post(this.uri); - then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture()); + then(this.client).should().executeOpen(this.hostCaptor.capture(), this.requestCaptor.capture(), isNull()); HttpUriRequest request = this.requestCaptor.getValue(); assertThat(request).isInstanceOf(HttpPost.class); assertThat(request.getUri()).isEqualTo(this.uri); @@ -127,7 +128,7 @@ class HttpClientTransportTests { given(this.entity.getContent()).willReturn(this.content); given(this.response.getCode()).willReturn(200); Response response = this.http.post(this.uri, "auth token"); - then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture()); + then(this.client).should().executeOpen(this.hostCaptor.capture(), this.requestCaptor.capture(), isNull()); HttpUriRequest request = this.requestCaptor.getValue(); assertThat(request).isInstanceOf(HttpPost.class); assertThat(request.getUri()).isEqualTo(this.uri); @@ -142,7 +143,7 @@ class HttpClientTransportTests { given(this.entity.getContent()).willReturn(this.content); given(this.response.getCode()).willReturn(200); Response response = this.http.post(this.uri, ""); - then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture()); + then(this.client).should().executeOpen(this.hostCaptor.capture(), this.requestCaptor.capture(), isNull()); HttpUriRequest request = this.requestCaptor.getValue(); assertThat(request).isInstanceOf(HttpPost.class); assertThat(request.getUri()).isEqualTo(this.uri); @@ -159,7 +160,7 @@ class HttpClientTransportTests { given(this.response.getCode()).willReturn(200); Response response = this.http.post(this.uri, APPLICATION_JSON, (out) -> StreamUtils.copy(content, StandardCharsets.UTF_8, out)); - then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture()); + then(this.client).should().executeOpen(this.hostCaptor.capture(), this.requestCaptor.capture(), isNull()); HttpUriRequest request = this.requestCaptor.getValue(); HttpEntity entity = request.getEntity(); assertThat(request).isInstanceOf(HttpPost.class); @@ -181,7 +182,7 @@ class HttpClientTransportTests { given(this.response.getCode()).willReturn(200); Response response = this.http.post(this.uri, APPLICATION_X_TAR, (out) -> StreamUtils.copy(content, StandardCharsets.UTF_8, out)); - then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture()); + then(this.client).should().executeOpen(this.hostCaptor.capture(), this.requestCaptor.capture(), isNull()); HttpUriRequest request = this.requestCaptor.getValue(); HttpEntity entity = request.getEntity(); assertThat(request).isInstanceOf(HttpPost.class); @@ -203,7 +204,7 @@ class HttpClientTransportTests { given(this.response.getCode()).willReturn(200); Response response = this.http.put(this.uri, APPLICATION_JSON, (out) -> StreamUtils.copy(content, StandardCharsets.UTF_8, out)); - then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture()); + then(this.client).should().executeOpen(this.hostCaptor.capture(), this.requestCaptor.capture(), isNull()); HttpUriRequest request = this.requestCaptor.getValue(); HttpEntity entity = request.getEntity(); assertThat(request).isInstanceOf(HttpPut.class); @@ -225,7 +226,7 @@ class HttpClientTransportTests { given(this.response.getCode()).willReturn(200); Response response = this.http.put(this.uri, APPLICATION_X_TAR, (out) -> StreamUtils.copy(content, StandardCharsets.UTF_8, out)); - then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture()); + then(this.client).should().executeOpen(this.hostCaptor.capture(), this.requestCaptor.capture(), isNull()); HttpUriRequest request = this.requestCaptor.getValue(); HttpEntity entity = request.getEntity(); assertThat(request).isInstanceOf(HttpPut.class); @@ -245,7 +246,7 @@ class HttpClientTransportTests { given(this.entity.getContent()).willReturn(this.content); given(this.response.getCode()).willReturn(200); Response response = this.http.delete(this.uri); - then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture()); + then(this.client).should().executeOpen(this.hostCaptor.capture(), this.requestCaptor.capture(), isNull()); HttpUriRequest request = this.requestCaptor.getValue(); assertThat(request).isInstanceOf(HttpDelete.class); assertThat(request.getUri()).isEqualTo(this.uri); @@ -302,7 +303,7 @@ class HttpClientTransportTests { @Test void executeWhenClientThrowsIOExceptionRethrowsAsDockerException() throws IOException { - given(this.client.execute(any(HttpHost.class), any(HttpUriRequest.class))) + given(this.client.executeOpen(any(HttpHost.class), any(HttpUriRequest.class), isNull())) .willThrow(new IOException("test IO exception")); assertThatExceptionOfType(DockerConnectionException.class).isThrownBy(() -> this.http.get(this.uri)) .satisfies((ex) -> assertThat(ex.getMessage()).contains("test IO exception")); @@ -315,7 +316,8 @@ class HttpClientTransportTests { } private void givenClientWillReturnResponse() throws IOException { - given(this.client.execute(any(HttpHost.class), any(HttpUriRequest.class))).willReturn(this.response); + given(this.client.executeOpen(any(HttpHost.class), any(HttpUriRequest.class), isNull())) + .willReturn(this.response); given(this.response.getEntity()).willReturn(this.entity); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/init/InitializrService.java b/spring-boot-project/spring-boot-tools/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/init/InitializrService.java index 0cf0357b3f8..e367ca2c0a0 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/init/InitializrService.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/init/InitializrService.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * 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. @@ -184,7 +184,7 @@ class InitializrService { try { HttpHost host = HttpHost.create(url); request.addHeader("User-Agent", "SpringBootCli/" + getClass().getPackage().getImplementationVersion()); - return getHttp().execute(host, request); + return getHttp().executeOpen(host, request, null); } catch (IOException ex) { throw new ReportableException( diff --git a/spring-boot-project/spring-boot-tools/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/AbstractHttpClientMockTests.java b/spring-boot-project/spring-boot-tools/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/AbstractHttpClientMockTests.java index 390d9fa2b5b..0c489821488 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/AbstractHttpClientMockTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/AbstractHttpClientMockTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * 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. @@ -38,6 +38,7 @@ import org.springframework.util.StreamUtils; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -70,7 +71,7 @@ public abstract class AbstractHttpClientMockTests { byte[] content = readClasspathResource(contentPath); mockHttpEntity(response, content, contentType); mockStatus(response, 200); - given(this.http.execute(any(HttpHost.class), argThat(getForMetadata(serviceCapabilities)))) + given(this.http.executeOpen(any(HttpHost.class), argThat(getForMetadata(serviceCapabilities)), isNull())) .willReturn(response); } @@ -87,7 +88,7 @@ public abstract class AbstractHttpClientMockTests { mockStatus(response, 200); String header = (request.fileName != null) ? contentDispositionValue(request.fileName) : null; mockHttpHeader(response, "Content-Disposition", header); - given(this.http.execute(any(HttpHost.class), argThat(getForNonMetadata()))).willReturn(response); + given(this.http.executeOpen(any(HttpHost.class), argThat(getForNonMetadata()), isNull())).willReturn(response); } protected void mockProjectGenerationError(int status, String message) throws IOException, JSONException { @@ -96,14 +97,14 @@ public abstract class AbstractHttpClientMockTests { ClassicHttpResponse response = mock(ClassicHttpResponse.class); mockHttpEntity(response, createJsonError(status, message).getBytes(), "application/json"); mockStatus(response, status); - given(this.http.execute(any(HttpHost.class), isA(HttpGet.class))).willReturn(response); + given(this.http.executeOpen(any(HttpHost.class), isA(HttpGet.class), isNull())).willReturn(response); } protected void mockMetadataGetError(int status, String message) throws IOException, JSONException { ClassicHttpResponse response = mock(ClassicHttpResponse.class); mockHttpEntity(response, createJsonError(status, message).getBytes(), "application/json"); mockStatus(response, status); - given(this.http.execute(any(HttpHost.class), isA(HttpGet.class))).willReturn(response); + given(this.http.executeOpen(any(HttpHost.class), isA(HttpGet.class), isNull())).willReturn(response); } protected HttpEntity mockHttpEntity(ClassicHttpResponse response, byte[] content, String contentType) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitCommandTests.java b/spring-boot-project/spring-boot-tools/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitCommandTests.java index 9e42577a397..287197e05cc 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitCommandTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitCommandTests.java @@ -40,6 +40,7 @@ import org.springframework.boot.cli.command.status.ExitStatus; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.BDDMockito.then; /** @@ -399,7 +400,7 @@ class InitCommandTests extends AbstractHttpClientMockTests { @Test void userAgent() throws Exception { this.command.run("--list", "--target=https://fake-service"); - then(this.http).should().execute(any(HttpHost.class), this.requestCaptor.capture()); + then(this.http).should().executeOpen(any(HttpHost.class), this.requestCaptor.capture(), isNull()); Header agent = this.requestCaptor.getValue().getHeaders("User-Agent")[0]; assertThat(agent.getValue()).startsWith("SpringBootCli/"); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitializrServiceTests.java b/spring-boot-project/spring-boot-tools/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitializrServiceTests.java index 3a27f459263..2af31c574c8 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitializrServiceTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/init/InitializrServiceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * 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. @@ -25,6 +25,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -95,7 +96,7 @@ class InitializrServiceTests extends AbstractHttpClientMockTests { mockSuccessfulMetadataGet(false); ClassicHttpResponse response = mock(ClassicHttpResponse.class); mockStatus(response, 500); - given(this.http.execute(any(HttpHost.class), isA(HttpGet.class))).willReturn(response); + given(this.http.executeOpen(any(HttpHost.class), isA(HttpGet.class), isNull())).willReturn(response); ProjectGenerationRequest request = new ProjectGenerationRequest(); assertThatExceptionOfType(ReportableException.class).isThrownBy(() -> this.invoker.generate(request)) .withMessageContaining("No content received from server"); @@ -115,7 +116,7 @@ class InitializrServiceTests extends AbstractHttpClientMockTests { ClassicHttpResponse response = mock(ClassicHttpResponse.class); mockHttpEntity(response, "Foo-Bar-Not-JSON".getBytes(), "application/json"); mockStatus(response, 200); - given(this.http.execute(any(HttpHost.class), isA(HttpGet.class))).willReturn(response); + given(this.http.executeOpen(any(HttpHost.class), isA(HttpGet.class), isNull())).willReturn(response); ProjectGenerationRequest request = new ProjectGenerationRequest(); assertThatExceptionOfType(ReportableException.class).isThrownBy(() -> this.invoker.generate(request)) .withMessageContaining("Invalid content received from server"); @@ -125,7 +126,7 @@ class InitializrServiceTests extends AbstractHttpClientMockTests { void loadMetadataNoContent() throws Exception { ClassicHttpResponse response = mock(ClassicHttpResponse.class); mockStatus(response, 500); - given(this.http.execute(any(HttpHost.class), isA(HttpGet.class))).willReturn(response); + given(this.http.executeOpen(any(HttpHost.class), isA(HttpGet.class), isNull())).willReturn(response); ProjectGenerationRequest request = new ProjectGenerationRequest(); assertThatExceptionOfType(ReportableException.class).isThrownBy(() -> this.invoker.generate(request)) .withMessageContaining("No content received from server"); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesHttpComponentsTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesHttpComponentsTests.java index afae5323ac4..319594c298e 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesHttpComponentsTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/ClientHttpRequestFactoriesHttpComponentsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * 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. @@ -16,7 +16,9 @@ package org.springframework.boot.web.client; +import org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.core5.function.Resolver; import org.apache.hc.core5.http.io.SocketConfig; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; @@ -41,11 +43,12 @@ class ClientHttpRequestFactoriesHttpComponentsTests } @Override + @SuppressWarnings("unchecked") protected long readTimeout(HttpComponentsClientHttpRequestFactory requestFactory) { HttpClient httpClient = requestFactory.getHttpClient(); Object connectionManager = ReflectionTestUtils.getField(httpClient, "connManager"); - SocketConfig socketConfig = (SocketConfig) ReflectionTestUtils.getField(connectionManager, - "defaultSocketConfig"); + SocketConfig socketConfig = ((Resolver) ReflectionTestUtils.getField(connectionManager, + "socketConfigResolver")).resolve(null); return socketConfig.getSoTimeout().toMilliseconds(); }