Migrate buildpack-platform to Apache HttpClient 5

Closes gh-33533
This commit is contained in:
Scott Frederick 2022-12-14 14:25:31 -06:00
parent 7f09636ad2
commit 1588f9d881
8 changed files with 143 additions and 121 deletions

View File

@ -11,9 +11,7 @@ dependencies {
api("com.fasterxml.jackson.module:jackson-module-parameter-names")
api("net.java.dev.jna:jna-platform")
api("org.apache.commons:commons-compress:1.19")
api("org.apache.httpcomponents:httpclient") {
exclude(group: "commons-logging", module: "commons-logging")
}
api("org.apache.httpcomponents.client5:httpclient5")
api("org.springframework:spring-core")
api("org.tomlj:tomlj:1.0.0")

View File

@ -26,7 +26,7 @@ import java.util.List;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.http.client.utils.URIBuilder;
import org.apache.hc.core5.net.URIBuilder;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerHost;
import org.springframework.boot.buildpack.platform.docker.transport.HttpTransport;

View File

@ -21,20 +21,20 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.AbstractHttpEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.classic.methods.HttpDelete;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpPut;
import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.io.entity.AbstractHttpEntity;
import org.apache.hc.core5.http.message.StatusLine;
import org.springframework.boot.buildpack.platform.io.Content;
import org.springframework.boot.buildpack.platform.io.IOConsumer;
@ -54,11 +54,11 @@ abstract class HttpClientTransport implements HttpTransport {
static final String REGISTRY_AUTH_HEADER = "X-Registry-Auth";
private final CloseableHttpClient client;
private final HttpClient client;
private final HttpHost host;
protected HttpClientTransport(CloseableHttpClient client, HttpHost host) {
protected HttpClientTransport(HttpClient client, HttpHost host) {
Assert.notNull(client, "Client must not be null");
Assert.notNull(host, "Host must not be null");
this.client = client;
@ -130,13 +130,12 @@ abstract class HttpClientTransport implements HttpTransport {
return execute(new HttpDelete(uri));
}
private Response execute(HttpEntityEnclosingRequestBase request, String contentType,
IOConsumer<OutputStream> writer) {
private Response execute(HttpUriRequestBase request, String contentType, IOConsumer<OutputStream> writer) {
request.setEntity(new WritableHttpEntity(contentType, writer));
return execute(request);
}
private Response execute(HttpEntityEnclosingRequestBase request, String registryAuth) {
private Response execute(HttpUriRequestBase request, String registryAuth) {
if (StringUtils.hasText(registryAuth)) {
request.setHeader(REGISTRY_AUTH_HEADER, registryAuth);
}
@ -145,19 +144,19 @@ abstract class HttpClientTransport implements HttpTransport {
private Response execute(HttpUriRequest request) {
try {
CloseableHttpResponse response = this.client.execute(this.host, request);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
HttpEntity entity = response.getEntity();
ClassicHttpResponse response = this.client.execute(this.host, request);
int statusCode = response.getCode();
if (statusCode >= 400 && statusCode <= 500) {
HttpEntity entity = response.getEntity();
Errors errors = (statusCode != 500) ? getErrorsFromResponse(entity) : null;
Message message = getMessageFromResponse(entity);
throw new DockerEngineException(this.host.toHostString(), request.getURI(), statusCode,
StatusLine statusLine = new StatusLine(response);
throw new DockerEngineException(this.host.toHostString(), request.getUri(), statusCode,
statusLine.getReasonPhrase(), errors, message);
}
return new HttpClientResponse(response);
}
catch (IOException ex) {
catch (IOException | URISyntaxException ex) {
throw new DockerConnectionException(this.host.toHostString(), ex);
}
}
@ -193,7 +192,7 @@ abstract class HttpClientTransport implements HttpTransport {
private final IOConsumer<OutputStream> writer;
WritableHttpEntity(String contentType, IOConsumer<OutputStream> writer) {
setContentType(contentType);
super(contentType, "UTF-8");
this.writer = writer;
}
@ -204,7 +203,7 @@ abstract class HttpClientTransport implements HttpTransport {
@Override
public long getContentLength() {
if (this.contentType != null && this.contentType.getValue().equals("application/json")) {
if (this.getContentType() != null && this.getContentType().equals("application/json")) {
return calculateStringContentLength();
}
return -1;
@ -236,6 +235,10 @@ abstract class HttpClientTransport implements HttpTransport {
}
}
@Override
public void close() throws IOException {
}
}
/**
@ -243,9 +246,9 @@ abstract class HttpClientTransport implements HttpTransport {
*/
private static class HttpClientResponse implements Response {
private final CloseableHttpResponse response;
private final ClassicHttpResponse response;
HttpClientResponse(CloseableHttpResponse response) {
HttpClientResponse(ClassicHttpResponse response) {
this.response = response;
}

View File

@ -20,23 +20,24 @@ import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import com.sun.jna.Platform;
import org.apache.http.HttpHost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.SchemePortResolver;
import org.apache.http.conn.UnsupportedSchemeException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.Args;
import org.apache.hc.client5.http.DnsResolver;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.config.Registry;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.util.Args;
import org.apache.hc.core5.util.TimeValue;
import org.springframework.boot.buildpack.platform.docker.configuration.ResolvedDockerHost;
import org.springframework.boot.buildpack.platform.socket.DomainSocket;
@ -50,9 +51,18 @@ import org.springframework.boot.buildpack.platform.socket.NamedPipeSocket;
*/
final class LocalHttpClientTransport extends HttpClientTransport {
private static final HttpHost LOCAL_DOCKER_HOST = HttpHost.create("docker://localhost");
private static final HttpHost LOCAL_DOCKER_HOST;
private LocalHttpClientTransport(CloseableHttpClient client) {
static {
try {
LOCAL_DOCKER_HOST = HttpHost.create("docker://localhost");
}
catch (URISyntaxException ex) {
throw new RuntimeException("Error creating local Docker host address", ex);
}
}
private LocalHttpClientTransport(HttpClient client) {
super(client, LOCAL_DOCKER_HOST);
}
@ -85,11 +95,16 @@ final class LocalHttpClientTransport extends HttpClientTransport {
*/
private static class LocalDnsResolver implements DnsResolver {
private static final InetAddress[] LOOPBACK = new InetAddress[] { InetAddress.getLoopbackAddress() };
private static final InetAddress LOOPBACK = InetAddress.getLoopbackAddress();
@Override
public InetAddress[] resolve(String host) throws UnknownHostException {
return LOOPBACK;
return new InetAddress[] { LOOPBACK };
}
@Override
public String resolveCanonicalHostname(String host) throws UnknownHostException {
return LOOPBACK.getCanonicalHostName();
}
}
@ -115,9 +130,10 @@ final class LocalHttpClientTransport extends HttpClientTransport {
}
@Override
public Socket connectSocket(int connectTimeout, Socket sock, HttpHost host, InetSocketAddress remoteAddress,
InetSocketAddress localAddress, HttpContext context) throws IOException {
return sock;
public Socket connectSocket(TimeValue connectTimeout, Socket socket, HttpHost host,
InetSocketAddress remoteAddress, InetSocketAddress localAddress, HttpContext context)
throws IOException {
return socket;
}
}
@ -130,13 +146,13 @@ final class LocalHttpClientTransport extends HttpClientTransport {
private static final int DEFAULT_DOCKER_PORT = 2376;
@Override
public int resolve(HttpHost host) throws UnsupportedSchemeException {
public int resolve(HttpHost host) {
Args.notNull(host, "HTTP host");
String name = host.getSchemeName();
if ("docker".equals(name)) {
return DEFAULT_DOCKER_PORT;
}
throw new UnsupportedSchemeException(name + " protocol is not supported");
return -1;
}
}

View File

@ -16,14 +16,18 @@
package org.springframework.boot.buildpack.platform.docker.transport;
import java.net.URISyntaxException;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpHost;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.http.HttpHost;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerHost;
import org.springframework.boot.buildpack.platform.docker.configuration.ResolvedDockerHost;
@ -38,7 +42,7 @@ import org.springframework.util.Assert;
*/
final class RemoteHttpClientTransport extends HttpClientTransport {
private RemoteHttpClientTransport(CloseableHttpClient client, HttpHost host) {
private RemoteHttpClientTransport(HttpClient client, HttpHost host) {
super(client, host);
}
@ -51,17 +55,24 @@ final class RemoteHttpClientTransport extends HttpClientTransport {
if (!dockerHost.isRemote()) {
return null;
}
return create(dockerHost, sslContextFactory, HttpHost.create(dockerHost.getAddress()));
try {
return create(dockerHost, sslContextFactory, HttpHost.create(dockerHost.getAddress()));
}
catch (URISyntaxException ex) {
return null;
}
}
private static RemoteHttpClientTransport create(DockerHost host, SslContextFactory sslContextFactory,
HttpHost tcpHost) {
HttpClientBuilder builder = HttpClients.custom();
if (host.isSecure()) {
builder.setSSLSocketFactory(getSecureConnectionSocketFactory(host, sslContextFactory));
PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
.setSSLSocketFactory(getSecureConnectionSocketFactory(host, sslContextFactory)).build();
builder.setConnectionManager(connectionManager);
}
String scheme = host.isSecure() ? "https" : "http";
HttpHost httpHost = new HttpHost(tcpHost.getHostName(), tcpHost.getPort(), scheme);
HttpHost httpHost = new HttpHost(scheme, tcpHost.getHostName(), tcpHost.getPort());
return new RemoteHttpClientTransport(builder.build(), httpHost);
}

View File

@ -20,21 +20,19 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.classic.methods.HttpDelete;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpPut;
import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpHost;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ -67,13 +65,10 @@ class HttpClientTransportTests {
private static final String APPLICATION_X_TAR = "application/x-tar";
@Mock
private CloseableHttpClient client;
private HttpClient client;
@Mock
private CloseableHttpResponse response;
@Mock
private StatusLine statusLine;
private ClassicHttpResponse response;
@Mock
private HttpEntity entity;
@ -101,12 +96,12 @@ class HttpClientTransportTests {
void getShouldExecuteHttpGet() throws Exception {
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(this.content);
given(this.statusLine.getStatusCode()).willReturn(200);
given(this.response.getCode()).willReturn(200);
Response response = this.http.get(this.uri);
then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture());
HttpUriRequest request = this.requestCaptor.getValue();
assertThat(request).isInstanceOf(HttpGet.class);
assertThat(request.getURI()).isEqualTo(this.uri);
assertThat(request.getUri()).isEqualTo(this.uri);
assertThat(request.getFirstHeader(HttpHeaders.CONTENT_TYPE)).isNull();
assertThat(response.getContent()).isSameAs(this.content);
}
@ -115,12 +110,12 @@ class HttpClientTransportTests {
void postShouldExecuteHttpPost() throws Exception {
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(this.content);
given(this.statusLine.getStatusCode()).willReturn(200);
given(this.response.getCode()).willReturn(200);
Response response = this.http.post(this.uri);
then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture());
HttpUriRequest request = this.requestCaptor.getValue();
assertThat(request).isInstanceOf(HttpPost.class);
assertThat(request.getURI()).isEqualTo(this.uri);
assertThat(request.getUri()).isEqualTo(this.uri);
assertThat(request.getFirstHeader(HttpHeaders.CONTENT_TYPE)).isNull();
assertThat(request.getFirstHeader(HttpClientTransport.REGISTRY_AUTH_HEADER)).isNull();
assertThat(response.getContent()).isSameAs(this.content);
@ -130,12 +125,12 @@ class HttpClientTransportTests {
void postWithRegistryAuthShouldExecuteHttpPostWithHeader() throws Exception {
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(this.content);
given(this.statusLine.getStatusCode()).willReturn(200);
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());
HttpUriRequest request = this.requestCaptor.getValue();
assertThat(request).isInstanceOf(HttpPost.class);
assertThat(request.getURI()).isEqualTo(this.uri);
assertThat(request.getUri()).isEqualTo(this.uri);
assertThat(request.getFirstHeader(HttpHeaders.CONTENT_TYPE)).isNull();
assertThat(request.getFirstHeader(HttpClientTransport.REGISTRY_AUTH_HEADER).getValue()).isEqualTo("auth token");
assertThat(response.getContent()).isSameAs(this.content);
@ -145,12 +140,12 @@ class HttpClientTransportTests {
void postWithEmptyRegistryAuthShouldExecuteHttpPostWithoutHeader() throws Exception {
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(this.content);
given(this.statusLine.getStatusCode()).willReturn(200);
given(this.response.getCode()).willReturn(200);
Response response = this.http.post(this.uri, "");
then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture());
HttpUriRequest request = this.requestCaptor.getValue();
assertThat(request).isInstanceOf(HttpPost.class);
assertThat(request.getURI()).isEqualTo(this.uri);
assertThat(request.getUri()).isEqualTo(this.uri);
assertThat(request.getFirstHeader(HttpHeaders.CONTENT_TYPE)).isNull();
assertThat(request.getFirstHeader(HttpClientTransport.REGISTRY_AUTH_HEADER)).isNull();
assertThat(response.getContent()).isSameAs(this.content);
@ -161,17 +156,17 @@ class HttpClientTransportTests {
String content = "test";
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(this.content);
given(this.statusLine.getStatusCode()).willReturn(200);
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());
HttpUriRequest request = this.requestCaptor.getValue();
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
HttpEntity entity = request.getEntity();
assertThat(request).isInstanceOf(HttpPost.class);
assertThat(request.getURI()).isEqualTo(this.uri);
assertThat(request.getUri()).isEqualTo(this.uri);
assertThat(entity.isRepeatable()).isFalse();
assertThat(entity.getContentLength()).isEqualTo(content.length());
assertThat(entity.getContentType().getValue()).isEqualTo(APPLICATION_JSON);
assertThat(entity.getContentType()).isEqualTo(APPLICATION_JSON);
assertThat(entity.isStreaming()).isTrue();
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(entity::getContent);
assertThat(writeToString(entity)).isEqualTo(content);
@ -183,17 +178,17 @@ class HttpClientTransportTests {
String content = "test";
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(this.content);
given(this.statusLine.getStatusCode()).willReturn(200);
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());
HttpUriRequest request = this.requestCaptor.getValue();
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
HttpEntity entity = request.getEntity();
assertThat(request).isInstanceOf(HttpPost.class);
assertThat(request.getURI()).isEqualTo(this.uri);
assertThat(request.getUri()).isEqualTo(this.uri);
assertThat(entity.isRepeatable()).isFalse();
assertThat(entity.getContentLength()).isEqualTo(-1);
assertThat(entity.getContentType().getValue()).isEqualTo(APPLICATION_X_TAR);
assertThat(entity.getContentType()).isEqualTo(APPLICATION_X_TAR);
assertThat(entity.isStreaming()).isTrue();
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(entity::getContent);
assertThat(writeToString(entity)).isEqualTo(content);
@ -205,17 +200,17 @@ class HttpClientTransportTests {
String content = "test";
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(this.content);
given(this.statusLine.getStatusCode()).willReturn(200);
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());
HttpUriRequest request = this.requestCaptor.getValue();
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
HttpEntity entity = request.getEntity();
assertThat(request).isInstanceOf(HttpPut.class);
assertThat(request.getURI()).isEqualTo(this.uri);
assertThat(request.getUri()).isEqualTo(this.uri);
assertThat(entity.isRepeatable()).isFalse();
assertThat(entity.getContentLength()).isEqualTo(content.length());
assertThat(entity.getContentType().getValue()).isEqualTo(APPLICATION_JSON);
assertThat(entity.getContentType()).isEqualTo(APPLICATION_JSON);
assertThat(entity.isStreaming()).isTrue();
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(entity::getContent);
assertThat(writeToString(entity)).isEqualTo(content);
@ -227,17 +222,17 @@ class HttpClientTransportTests {
String content = "test";
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(this.content);
given(this.statusLine.getStatusCode()).willReturn(200);
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());
HttpUriRequest request = this.requestCaptor.getValue();
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
HttpEntity entity = request.getEntity();
assertThat(request).isInstanceOf(HttpPut.class);
assertThat(request.getURI()).isEqualTo(this.uri);
assertThat(request.getUri()).isEqualTo(this.uri);
assertThat(entity.isRepeatable()).isFalse();
assertThat(entity.getContentLength()).isEqualTo(-1);
assertThat(entity.getContentType().getValue()).isEqualTo(APPLICATION_X_TAR);
assertThat(entity.getContentType()).isEqualTo(APPLICATION_X_TAR);
assertThat(entity.isStreaming()).isTrue();
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(entity::getContent);
assertThat(writeToString(entity)).isEqualTo(content);
@ -245,15 +240,15 @@ class HttpClientTransportTests {
}
@Test
void deleteShouldExecuteHttpDelete() throws IOException {
void deleteShouldExecuteHttpDelete() throws Exception {
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(this.content);
given(this.statusLine.getStatusCode()).willReturn(200);
given(this.response.getCode()).willReturn(200);
Response response = this.http.delete(this.uri);
then(this.client).should().execute(this.hostCaptor.capture(), this.requestCaptor.capture());
HttpUriRequest request = this.requestCaptor.getValue();
assertThat(request).isInstanceOf(HttpDelete.class);
assertThat(request.getURI()).isEqualTo(this.uri);
assertThat(request.getUri()).isEqualTo(this.uri);
assertThat(request.getFirstHeader(HttpHeaders.CONTENT_TYPE)).isNull();
assertThat(response.getContent()).isSameAs(this.content);
}
@ -262,7 +257,7 @@ class HttpClientTransportTests {
void executeWhenResponseIsIn400RangeShouldThrowDockerException() throws IOException {
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(getClass().getResourceAsStream("errors.json"));
given(this.statusLine.getStatusCode()).willReturn(404);
given(this.response.getCode()).willReturn(404);
assertThatExceptionOfType(DockerEngineException.class).isThrownBy(() -> this.http.get(this.uri))
.satisfies((ex) -> {
assertThat(ex.getErrors()).hasSize(2);
@ -273,7 +268,7 @@ class HttpClientTransportTests {
@Test
void executeWhenResponseIsIn500RangeWithNoContentShouldThrowDockerException() throws IOException {
givenClientWillReturnResponse();
given(this.statusLine.getStatusCode()).willReturn(500);
given(this.response.getCode()).willReturn(500);
assertThatExceptionOfType(DockerEngineException.class).isThrownBy(() -> this.http.get(this.uri))
.satisfies((ex) -> {
assertThat(ex.getErrors()).isNull();
@ -285,7 +280,7 @@ class HttpClientTransportTests {
void executeWhenResponseIsIn500RangeWithMessageShouldThrowDockerException() throws IOException {
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(getClass().getResourceAsStream("message.json"));
given(this.statusLine.getStatusCode()).willReturn(500);
given(this.response.getCode()).willReturn(500);
assertThatExceptionOfType(DockerEngineException.class).isThrownBy(() -> this.http.get(this.uri))
.satisfies((ex) -> {
assertThat(ex.getErrors()).isNull();
@ -297,7 +292,7 @@ class HttpClientTransportTests {
void executeWhenResponseIsIn500RangeWithOtherContentShouldThrowDockerException() throws IOException {
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(this.content);
given(this.statusLine.getStatusCode()).willReturn(500);
given(this.response.getCode()).willReturn(500);
assertThatExceptionOfType(DockerEngineException.class).isThrownBy(() -> this.http.get(this.uri))
.satisfies((ex) -> {
assertThat(ex.getErrors()).isNull();
@ -307,7 +302,7 @@ class HttpClientTransportTests {
@Test
void executeWhenClientThrowsIOExceptionRethrowsAsDockerException() throws IOException {
given(this.client.execute(any(HttpHost.class), any(HttpRequest.class)))
given(this.client.execute(any(HttpHost.class), any(HttpUriRequest.class)))
.willThrow(new IOException("test IO exception"));
assertThatExceptionOfType(DockerConnectionException.class).isThrownBy(() -> this.http.get(this.uri))
.satisfies((ex) -> assertThat(ex.getMessage()).contains("test IO exception"));
@ -320,9 +315,8 @@ class HttpClientTransportTests {
}
private void givenClientWillReturnResponse() throws IOException {
given(this.client.execute(any(HttpHost.class), any(HttpRequest.class))).willReturn(this.response);
given(this.client.execute(any(HttpHost.class), any(HttpUriRequest.class))).willReturn(this.response);
given(this.response.getEntity()).willReturn(this.entity);
given(this.response.getStatusLine()).willReturn(this.statusLine);
}
/**
@ -330,7 +324,7 @@ class HttpClientTransportTests {
*/
static class TestHttpClientTransport extends HttpClientTransport {
protected TestHttpClientTransport(CloseableHttpClient client) {
protected TestHttpClientTransport(HttpClient client) throws URISyntaxException {
super(client, HttpHost.create("docker://localhost"));
}

View File

@ -20,7 +20,7 @@ import java.util.function.Consumer;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpHost;
import org.apache.hc.core5.http.HttpHost;
import org.junit.jupiter.api.Test;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerHost;

View File

@ -41,8 +41,8 @@ import io.spring.gradle.dependencymanagement.DependencyManagementPlugin;
import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension;
import org.antlr.v4.runtime.Lexer;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.http.HttpRequest;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
import org.apache.hc.core5.http.HttpRequest;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.GradleRunner;
import org.gradle.util.GradleVersion;