Merge branch '3.3.x' into 3.4.x

Closes gh-44630
This commit is contained in:
Moritz Halbritter 2025-03-06 17:39:26 +01:00
commit 2e74ce8bf2
3 changed files with 60 additions and 13 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.
@ -36,7 +36,6 @@ import org.apache.hc.core5.http.Header;
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;
@ -51,6 +50,7 @@ import org.springframework.util.StringUtils;
* @author Phillip Webb
* @author Mike Smithson
* @author Scott Frederick
* @author Moritz Halbritter
*/
abstract class HttpClientTransport implements HttpTransport {
@ -159,12 +159,12 @@ abstract class HttpClientTransport implements HttpTransport {
ClassicHttpResponse response = this.client.executeOpen(this.host, request, null);
int statusCode = response.getCode();
if (statusCode >= 400 && statusCode <= 500) {
HttpEntity entity = response.getEntity();
Errors errors = (statusCode != 500) ? getErrorsFromResponse(entity) : null;
Message message = getMessageFromResponse(entity);
StatusLine statusLine = new StatusLine(response);
byte[] content = readContent(response);
response.close();
Errors errors = (statusCode != 500) ? deserializeErrors(content) : null;
Message message = deserializeMessage(content);
throw new DockerEngineException(this.host.toHostString(), request.getUri(), statusCode,
statusLine.getReasonPhrase(), errors, message);
response.getReasonPhrase(), errors, message);
}
return new HttpClientResponse(response);
}
@ -173,19 +173,38 @@ abstract class HttpClientTransport implements HttpTransport {
}
}
private Errors getErrorsFromResponse(HttpEntity entity) {
private byte[] readContent(ClassicHttpResponse response) throws IOException {
HttpEntity entity = response.getEntity();
if (entity == null) {
return null;
}
try (InputStream stream = entity.getContent()) {
if (stream == null) {
return null;
}
return stream.readAllBytes();
}
}
private Errors deserializeErrors(byte[] content) {
if (content == null) {
return null;
}
try {
return SharedObjectMapper.get().readValue(entity.getContent(), Errors.class);
return SharedObjectMapper.get().readValue(content, Errors.class);
}
catch (IOException ex) {
return null;
}
}
private Message getMessageFromResponse(HttpEntity entity) {
private Message deserializeMessage(byte[] content) {
if (content == null) {
return null;
}
try {
return (entity.getContent() != null)
? SharedObjectMapper.get().readValue(entity.getContent(), Message.class) : null;
Message message = SharedObjectMapper.get().readValue(content, Message.class);
return (message.getMessage() != null) ? message : null;
}
catch (IOException ex) {
return null;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2025 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.
@ -57,6 +57,7 @@ import static org.mockito.BDDMockito.then;
* @author Phillip Webb
* @author Mike Smithson
* @author Scott Frederick
* @author Moritz Halbritter
*/
@ExtendWith(MockitoExtension.class)
class HttpClientTransportTests {
@ -309,6 +310,18 @@ class HttpClientTransportTests {
});
}
@Test
void shouldReturnErrorsAndMessage() throws IOException {
givenClientWillReturnResponse();
given(this.entity.getContent()).willReturn(getClass().getResourceAsStream("message-and-errors.json"));
given(this.response.getCode()).willReturn(404);
assertThatExceptionOfType(DockerEngineException.class).isThrownBy(() -> this.http.get(this.uri))
.satisfies((ex) -> {
assertThat(ex.getErrors()).hasSize(2);
assertThat(ex.getResponseMessage().getMessage()).contains("test message");
});
}
@Test
void executeWhenClientThrowsIOExceptionRethrowsAsDockerException() throws IOException {
given(this.client.executeOpen(any(HttpHost.class), any(HttpUriRequest.class), isNull()))

View File

@ -0,0 +1,15 @@
{
"message": "test message",
"errors": [
{
"code": "TEST1",
"message": "Test One",
"detail": 123
},
{
"code": "TEST2",
"message": "Test Two",
"detail": "fail"
}
]
}