Skip to content

Commit

Permalink
feat(web): Add a generic RetrofitError exception handler (#86)
Browse files Browse the repository at this point in the history
This exception handler will propagate the underlying retrofit error
status rather than an HTTP 500 as is the current behavior.
  • Loading branch information
ajordens authored Jul 13, 2017
1 parent 0de92ff commit 485f4f5
Showing 1 changed file with 49 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.netflix.spinnaker.kork.web.exceptions;

import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.web.DefaultErrorAttributes;
Expand All @@ -24,10 +26,16 @@
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import retrofit.RetrofitError;
import retrofit.client.Header;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class GenericExceptionHandlers {
Expand Down Expand Up @@ -57,6 +65,33 @@ public void handleInvalidRequestException(Exception e, HttpServletResponse respo
response.sendError(HttpStatus.BAD_REQUEST.value(), e.getMessage());
}

@ExceptionHandler(RetrofitError.class)
public void handleRetrofitError(RetrofitError e, HttpServletResponse response, HttpServletRequest request) throws IOException {
if (e.getResponse() != null) {
Map<String, Object> additionalContext = new HashMap<>();
additionalContext.put("url", e.getResponse().getUrl());

Header contentTypeHeader = e.getResponse().getHeaders()
.stream()
.filter(h -> h.getName().equalsIgnoreCase("content-type"))
.findFirst()
.orElse(null);

if (contentTypeHeader != null && contentTypeHeader.getValue().toLowerCase().contains("application/json")) {
// include any json responses
additionalContext.put("body", CharStreams.toString(
new InputStreamReader(e.getResponse().getBody().in(), Charsets.UTF_8)
));
}

storeException(request, response, new RetrofitErrorWrapper(e.getMessage(), additionalContext));
response.sendError(e.getResponse().getStatus(), e.getMessage());
} else {
// no retrofit response (likely) indicates a NETWORK error
handleException(e, response, request);
}
}

@ExceptionHandler(Exception.class)
public void handleException(Exception e, HttpServletResponse response, HttpServletRequest request) throws IOException {
logger.error("Internal Server Error", e);
Expand All @@ -80,4 +115,18 @@ private void storeException(HttpServletRequest request, HttpServletResponse resp
// store exception as an attribute of HttpServletRequest such that it can be referenced by GenericErrorController
defaultErrorAttributes.resolveException(request, response, null, ex);
}

private static class RetrofitErrorWrapper extends RuntimeException implements HasAdditionalAttributes {
private final Map<String, Object> additionalAttributes;

public RetrofitErrorWrapper(String message, Map<String, Object> additionalAttributes) {
super(message);
this.additionalAttributes = additionalAttributes;
}

@Override
public Map<String, Object> getAdditionalAttributes() {
return additionalAttributes != null ? additionalAttributes : Collections.emptyMap();
}
}
}

0 comments on commit 485f4f5

Please sign in to comment.