Skip to content

Commit 0d4e000

Browse files
committed
Preserve response body on errors when using ReactiveCredHubTemplate
Resolves #69 Signed-off-by: Roy Clarkson <roy.clarkson@broadcom.com>
1 parent db6e7e5 commit 0d4e000

3 files changed

Lines changed: 93 additions & 1 deletion

File tree

spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubException.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.credhub.core;
1818

19+
import org.springframework.http.HttpHeaders;
1920
import org.springframework.http.HttpStatusCode;
2021
import org.springframework.web.client.HttpStatusCodeException;
2122

@@ -45,4 +46,15 @@ public CredHubException(HttpStatusCode statusCode) {
4546
super(statusCode);
4647
}
4748

49+
/**
50+
* Create a new exception with the provided error status code, headers, and response
51+
* body.
52+
* @param statusCode an {@link HttpStatusCode} indicating an error
53+
* @param headers the response headers
54+
* @param responseBody the response body as a byte array
55+
*/
56+
public CredHubException(HttpStatusCode statusCode, HttpHeaders headers, byte[] responseBody) {
57+
super(statusCode, statusCode.toString(), headers, responseBody, null);
58+
}
59+
4860
}

spring-credhub-core/src/main/java/org/springframework/credhub/core/ExceptionUtils.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ public static void throwExceptionOnError(ResponseEntity<?> response) {
5252
* @return the generated error
5353
*/
5454
public static Mono<Throwable> buildError(ClientResponse response) {
55-
return Mono.error(new CredHubException(response.statusCode()));
55+
return response.bodyToMono(byte[].class)
56+
.defaultIfEmpty(new byte[0])
57+
.map((body) -> new CredHubException(response.statusCode(), response.headers().asHttpHeaders(), body));
5658
}
5759

5860
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2016-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.credhub.core;
18+
19+
import org.junit.jupiter.api.Test;
20+
import reactor.core.publisher.Mono;
21+
import reactor.test.StepVerifier;
22+
23+
import org.springframework.http.HttpStatus;
24+
import org.springframework.http.ResponseEntity;
25+
import org.springframework.web.reactive.function.client.ClientResponse;
26+
27+
import static org.assertj.core.api.Assertions.assertThat;
28+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
29+
30+
class ExceptionUtilsUnitTests {
31+
32+
@Test
33+
void throwExceptionOnErrorPreservesStatusCode() {
34+
ResponseEntity<String> response = ResponseEntity.status(HttpStatus.FORBIDDEN).body("access denied");
35+
36+
assertThatExceptionOfType(CredHubException.class)
37+
.isThrownBy(() -> ExceptionUtils.throwExceptionOnError(response))
38+
.satisfies((ex) -> assertThat(ex.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN));
39+
}
40+
41+
@Test
42+
void throwExceptionOnErrorDoesNothingForOk() {
43+
ResponseEntity<String> response = ResponseEntity.ok("success");
44+
45+
ExceptionUtils.throwExceptionOnError(response);
46+
}
47+
48+
@Test
49+
void buildErrorPreservesStatusCodeAndResponseBody() {
50+
ClientResponse clientResponse = ClientResponse.create(HttpStatus.FORBIDDEN)
51+
.body("{\"error\":\"access denied\"}")
52+
.build();
53+
54+
Mono<Throwable> error = ExceptionUtils.buildError(clientResponse);
55+
56+
StepVerifier.create(error).assertNext((ex) -> {
57+
assertThat(ex).isInstanceOf(CredHubException.class);
58+
CredHubException credHubException = (CredHubException) ex;
59+
assertThat(credHubException.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN);
60+
assertThat(credHubException.getResponseBodyAsString()).isEqualTo("{\"error\":\"access denied\"}");
61+
}).verifyComplete();
62+
}
63+
64+
@Test
65+
void buildErrorHandlesEmptyBody() {
66+
ClientResponse clientResponse = ClientResponse.create(HttpStatus.INTERNAL_SERVER_ERROR).build();
67+
68+
Mono<Throwable> error = ExceptionUtils.buildError(clientResponse);
69+
70+
StepVerifier.create(error).assertNext((ex) -> {
71+
assertThat(ex).isInstanceOf(CredHubException.class);
72+
CredHubException credHubException = (CredHubException) ex;
73+
assertThat(credHubException.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
74+
assertThat(credHubException.getResponseBodyAsString()).isEmpty();
75+
}).verifyComplete();
76+
}
77+
78+
}

0 commit comments

Comments
 (0)