Skip to content

Commit c2a2332

Browse files
authored
Updates B2WebApiHttpClientImpl to return subtypes of B2Exception (#179)
Return a subtype of B2Exception on errors when the response body does not conform to B2ErrorStructure. Returning a B2Exception subtype enables the B2Retryer to retry exceptions that may succeed on retry.
1 parent ea81b02 commit c2a2332

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## [Unreleased] - TBD
4+
### Added
5+
* Return a subtype of `B2Exception` on errors when the response body does not conform to `B2ErrorStructure`.
6+
Returning a `B2Exception` subtype enables the `B2Retryer` to retry exceptions that may succeed on retry.
7+
38
## [6.1.0] - 2022-09-19
49
### Added
510
* Added support for Java 8's `-parameters` option so constructor parameters do not need to be reiterated in `B2Json.constructor#params`

httpclient/src/main/java/com/backblaze/b2/client/webApiHttpClient/B2WebApiHttpClientImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,11 @@ private B2Exception extractExceptionFromErrorResponse(CloseableHttpResponse resp
284284
try {
285285
B2ErrorStructure err = B2Json.get().fromJson(responseText, B2ErrorStructure.class);
286286
return B2Exception.create(err.code, err.status, getRetryAfterSecondsOrNull(response), err.message);
287-
}
288-
catch (Throwable t) {
287+
} catch (Throwable t) {
289288
// we can't parse the response as a B2 JSON error structure.
290-
// so use the default.
291-
return new B2Exception("unknown", statusCode, getRetryAfterSecondsOrNull(response), responseText);
289+
// so use the "unknown" as the code
290+
return B2Exception.create("unknown", statusCode, getRetryAfterSecondsOrNull(response), responseText);
291+
292292
}
293293
}
294294

httpclient/src/test/java/com/backblaze/b2/client/webApiHttpClient/B2WebApiHttpClientImplTest.java

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.backblaze.b2.client.contentSources.B2Headers;
99
import com.backblaze.b2.client.contentSources.B2HeadersImpl;
1010
import com.backblaze.b2.client.exceptions.B2Exception;
11+
import com.backblaze.b2.client.exceptions.B2InternalErrorException;
1112
import com.backblaze.b2.client.structures.B2ErrorStructure;
1213
import com.backblaze.b2.client.webApiClients.B2WebApiClient;
1314
import com.backblaze.b2.json.B2Json;
@@ -73,10 +74,11 @@ public class B2WebApiHttpClientImplTest {
7374
RESPONSE_HEADERS
7475
);
7576

77+
private static final String ERROR_MESSAGE = "something went wrong";
7678
private static final B2ErrorStructure INTERNAL_ERROR_STRUCTURE = new B2ErrorStructure(
7779
HttpStatus.SC_INTERNAL_SERVER_ERROR,
7880
"bad",
79-
"something went wrong");
81+
ERROR_MESSAGE);
8082

8183

8284
private static final SimpleHttpRequestHandler.Response JSON_ERROR_RESPONSE = createResponse(
@@ -85,6 +87,12 @@ public class B2WebApiHttpClientImplTest {
8587
B2Json.toJsonOrThrowRuntime(INTERNAL_ERROR_STRUCTURE).getBytes()
8688
);
8789

90+
private static final SimpleHttpRequestHandler.Response TEXT_ERROR_RESPONSE = createResponse(
91+
HttpStatus.SC_INTERNAL_SERVER_ERROR,
92+
ContentType.TEXT_PLAIN.toString(),
93+
ERROR_MESSAGE.getBytes()
94+
);
95+
8896
@Test
8997
public void testGetContent() throws B2Exception {
9098
// large content with enableContentCompression set to true
@@ -93,11 +101,14 @@ public void testGetContent() throws B2Exception {
93101
// compressed large content with false enableContentCompression
94102
doTestGetContent(REQUEST_HEADERS, COMPRESSED_LARGE_CONTENT_RESPONSE, RESPONSE_HEADERS);
95103

96-
// error case
97-
doTestGetContentWithException(REQUEST_HEADERS, JSON_ERROR_RESPONSE, RESPONSE_HEADERS);
104+
// error case with JSON response
105+
doTestGetContentWithJsonException(REQUEST_HEADERS, JSON_ERROR_RESPONSE, RESPONSE_HEADERS);
106+
107+
// error case with text/plain response
108+
doTestGetContentWithTextException(REQUEST_HEADERS, TEXT_ERROR_RESPONSE);
98109
}
99110

100-
private void doTestGetContentWithException(Map<String, String> requestHeaders, SimpleHttpRequestHandler.Response expectedResponse, Map<String, String> responseHeaders) {
111+
private void doTestGetContentWithJsonException(Map<String, String> requestHeaders, SimpleHttpRequestHandler.Response expectedResponse, Map<String, String> responseHeaders) {
101112
final B2HeadersImpl.Builder requestHeaderBuilder = B2HeadersImpl.builder();
102113
requestHeaders.forEach(requestHeaderBuilder::set);
103114
requestHandler.setNextResponse(expectedResponse);
@@ -114,6 +125,24 @@ private void doTestGetContentWithException(Map<String, String> requestHeaders, S
114125
}
115126
}
116127

128+
private void doTestGetContentWithTextException(Map<String, String> requestHeaders, SimpleHttpRequestHandler.Response expectedResponse) {
129+
final B2HeadersImpl.Builder requestHeaderBuilder = B2HeadersImpl.builder();
130+
requestHeaders.forEach(requestHeaderBuilder::set);
131+
requestHandler.setNextResponse(expectedResponse);
132+
133+
final B2ContentMemoryWriter sink = B2ContentMemoryWriter.build();
134+
135+
// call getContent and verify the returned exception response data
136+
try {
137+
b2WebApiClient.getContent(url, requestHeaderBuilder.build(), sink);
138+
} catch (B2Exception b2Exception) {
139+
assertEquals(B2InternalErrorException.class, b2Exception.getClass());
140+
assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, b2Exception.getStatus());
141+
assertEquals("unknown", b2Exception.getCode());
142+
assertEquals(ERROR_MESSAGE, b2Exception.getMessage());
143+
}
144+
}
145+
117146
private void doTestGetContent(Map<String, String> requestHeaders, SimpleHttpRequestHandler.Response expectedResponse, Map<String, String> responseHeaders) throws B2Exception {
118147
final B2HeadersImpl.Builder requestHeaderBuilder = B2HeadersImpl.builder();
119148
requestHeaders.forEach(requestHeaderBuilder::set);

0 commit comments

Comments
 (0)