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

@@ -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;