Skip to content

Commit

Permalink
- fixes error response implementation in java to avoid bypassing nati…
Browse files Browse the repository at this point in the history
…ve response handler

Signed-off-by: Vincent Biret <vibiret@microsoft.com>
  • Loading branch information
baywet committed Feb 8, 2022
1 parent c9512ab commit 3b5f7a3
Showing 1 changed file with 18 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,15 @@ public <ModelType extends Parsable> CompletableFuture<Iterable<ModelType>> sendC
Objects.requireNonNull(requestInfo, "parameter requestInfo cannot be null");

return this.getHttpResponseMessage(requestInfo)
.thenCompose(r -> this.throwFailedResponse(r, errorMappings))
.thenCompose(response -> {
if(responseHandler == null) {
try {
this.throwFailedResponse(response, errorMappings);
final ParseNode rootNode = getRootParseNode(response);
final Iterable<ModelType> result = rootNode.getCollectionOfObjectValues(targetClass);
return CompletableFuture.completedStage(result);
} catch(ApiException ex) {
return CompletableFuture.failedFuture(ex);
} catch(IOException ex) {
return CompletableFuture.failedFuture(new RuntimeException("failed to read the response body", ex));
} finally {
Expand All @@ -119,13 +121,15 @@ public <ModelType extends Parsable> CompletableFuture<ModelType> sendAsync(@Nonn
Objects.requireNonNull(requestInfo, "parameter requestInfo cannot be null");

return this.getHttpResponseMessage(requestInfo)
.thenCompose(r -> this.throwFailedResponse(r, errorMappings))
.thenCompose(response -> {
if(responseHandler == null) {
try {
this.throwFailedResponse(response, errorMappings);
final ParseNode rootNode = getRootParseNode(response);
final ModelType result = rootNode.getObjectValue(targetClass);
return CompletableFuture.completedStage(result);
} catch(ApiException ex) {
return CompletableFuture.failedFuture(ex);
} catch(IOException ex) {
return CompletableFuture.failedFuture(new RuntimeException("failed to read the response body", ex));
} finally {
Expand All @@ -142,10 +146,10 @@ private String getMediaTypeAndSubType(final MediaType mediaType) {
@Nonnull
public <ModelType> CompletableFuture<ModelType> sendPrimitiveAsync(@Nonnull final RequestInformation requestInfo, @Nonnull final Class<ModelType> targetClass, @Nullable final ResponseHandler responseHandler, @Nullable final HashMap<String, Class<? extends Parsable>> errorMappings) {
return this.getHttpResponseMessage(requestInfo)
.thenCompose(r -> this.throwFailedResponse(r, errorMappings))
.thenCompose(response -> {
if(responseHandler == null) {
try {
this.throwFailedResponse(response, errorMappings);
if(targetClass == Void.class) {
return CompletableFuture.completedStage(null);
} else {
Expand Down Expand Up @@ -175,6 +179,8 @@ public <ModelType> CompletableFuture<ModelType> sendPrimitiveAsync(@Nonnull fina
}
return CompletableFuture.completedStage((ModelType)result);
}
} catch(ApiException ex) {
return CompletableFuture.failedFuture(ex);
} catch(IOException ex) {
return CompletableFuture.failedFuture(new RuntimeException("failed to read the response body", ex));
} finally {
Expand All @@ -189,13 +195,15 @@ public <ModelType> CompletableFuture<Iterable<ModelType>> sendPrimitiveCollectio
Objects.requireNonNull(requestInfo, "parameter requestInfo cannot be null");

return this.getHttpResponseMessage(requestInfo)
.thenCompose(r -> this.throwFailedResponse(r, errorMappings))
.thenCompose(response -> {
if(responseHandler == null) {
try {
this.throwFailedResponse(response, errorMappings);
final ParseNode rootNode = getRootParseNode(response);
final Iterable<ModelType> result = rootNode.getCollectionOfPrimitiveValues(targetClass);
return CompletableFuture.completedStage(result);
} catch(ApiException ex) {
return CompletableFuture.failedFuture(ex);
} catch(IOException ex) {
return CompletableFuture.failedFuture(new RuntimeException("failed to read the response body", ex));
} finally {
Expand All @@ -213,16 +221,16 @@ private ParseNode getRootParseNode(final Response response) throws IOException {
return rootNode;
}
}
private CompletableFuture<Response> throwFailedResponse(final Response response, final HashMap<String, Class<? extends Parsable>> errorMappings) {
if (response.isSuccessful()) return CompletableFuture.completedFuture(response);
private Response throwFailedResponse(final Response response, final HashMap<String, Class<? extends Parsable>> errorMappings) throws IOException, ApiException {
if (response.isSuccessful()) return response;

final String statusCodeAsString = Integer.toString(response.code());
final Integer statusCode = response.code();
if (errorMappings == null ||
!errorMappings.containsKey(statusCodeAsString) &&
!(statusCode >= 400 && statusCode < 500 && errorMappings.containsKey("4XX")) &&
!(statusCode >= 500 && statusCode < 600 && errorMappings.containsKey("5XX"))) {
return CompletableFuture.failedFuture(new ApiException("the server returned an unexpected status code and no error class is registered for this code " + statusCode));
throw new ApiException("the server returned an unexpected status code and no error class is registered for this code " + statusCode);
}
final Class<? extends Parsable> errorClass = errorMappings.containsKey(statusCodeAsString) ?
errorMappings.get(statusCodeAsString) :
Expand All @@ -232,13 +240,11 @@ private CompletableFuture<Response> throwFailedResponse(final Response response,
try {
final ParseNode rootNode = getRootParseNode(response);
final Parsable error = rootNode.getObjectValue(errorClass);
if (error instanceof Exception) {
return CompletableFuture.failedFuture((Exception)error);
if (error instanceof ApiException) {
throw (ApiException)error;
} else {
return CompletableFuture.failedFuture(new ApiException("unexpected error type " + error.getClass().getName()));
throw new ApiException("unexpected error type " + error.getClass().getName());
}
} catch (IOException ex) {
return CompletableFuture.failedFuture(ex);
} finally {
response.close();
}
Expand Down

0 comments on commit 3b5f7a3

Please sign in to comment.