X-Git-Url: https://juplo.de/gitweb/?p=facebook-errors;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fde%2Fjuplo%2Ffacebook%2Ferrors%2FGraphApiErrorResponseErrorHandler.java;fp=src%2Fmain%2Fjava%2Fde%2Fjuplo%2Ffacebook%2Ferrors%2FGraphApiErrorResponseErrorHandler.java;h=123c7f3d6a696bae2a3c23c2681b4006954ec774;hp=0000000000000000000000000000000000000000;hb=201cae17e8ce4face5f533bf03f050a146abb5c4;hpb=4fda7c67e6efd4f80e7437c75c76dbeb56f404c7 diff --git a/src/main/java/de/juplo/facebook/errors/GraphApiErrorResponseErrorHandler.java b/src/main/java/de/juplo/facebook/errors/GraphApiErrorResponseErrorHandler.java new file mode 100644 index 0000000..123c7f3 --- /dev/null +++ b/src/main/java/de/juplo/facebook/errors/GraphApiErrorResponseErrorHandler.java @@ -0,0 +1,155 @@ +package de.juplo.facebook.errors; + + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.ResponseErrorHandler; + + + +/** + * Error-Handler for error-messages from the Facebook Graph-API. + *

+ * This error-handler handels responses withe the HTTP-status code + * {@code 400 BAD REQUEST}. It tries to extract and parse the error-message + * from the HTTP-body. Successfully extracted and parsed messages are mapped + * to a hierarchy of exceptions, that reflects the hierarchy of the error- + * codes and -types. + *

+ * If the HTTP-status-code of the response is not {@code 400 BAD REQUEST} or + * the HTTP-body could not be extracted or parsed, this error-handler + * delegates the handling to its parent. + * + * @see Graph-API Documentation + * @see Inofficial Wiki For Facebook-Developers + * @author Kai Moritz + */ +public class GraphApiErrorResponseErrorHandler implements ResponseErrorHandler +{ + private final static Logger LOG = + LoggerFactory.getLogger(GraphApiErrorResponseErrorHandler.class); + + private final ResponseErrorHandler parent; + + + public GraphApiErrorResponseErrorHandler() + { + this(null); + } + + public GraphApiErrorResponseErrorHandler(ResponseErrorHandler errorHandler) + { + this.parent = + errorHandler == null + ? new DefaultResponseErrorHandler() + : errorHandler; + } + + + @Override + public boolean hasError(ClientHttpResponse response) throws IOException + { + return + HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series()) + || this.parent.hasError(response); + } + + @Override + public void handleError(final ClientHttpResponse response) throws IOException + { + GraphApiErrorResponseErrorHandler.handleError(parent, response); + } + + public static void handleError( + final ResponseErrorHandler parent, + final ClientHttpResponse response + ) + throws + IOException + { + if (response.getBody() == null) + { + // There is no body to interpret in the HTTP-message + LOG.warn("Could not convert the response into an exception, because there is no message-body."); + parent.handleError(response); + return; + } + + final byte[] body = FileCopyUtils.copyToByteArray(response.getBody()); + GraphApiException error; + + try + { + error = GraphApiException.create(response.getStatusCode(), response.getHeaders(), body); + if (LOG.isInfoEnabled()) + LOG.info("error-response: {}", new String(body, Charset.forName("UTF-8"))); + } + catch (Exception e) + { + // The body of the HTTP-message could not be parsed. + // Let the parent error-handler try to handle the response. + + LOG.warn( + "Could not convert the response into an exception, " + + "because the body is unparsable: error={}, body={}", + e.toString(), + new String(body, Charset.forName("UTF-8")) + ); + + // To do so, we have to wrap the original response to fill in + // the buffered body, if needed + ClientHttpResponse buffered = new ClientHttpResponse() + { + @Override + public HttpStatus getStatusCode() throws IOException + { + return response.getStatusCode(); + } + + @Override + public synchronized InputStream getBody() throws IOException + { + return new ByteArrayInputStream(body); + } + + @Override + public HttpHeaders getHeaders() + { + return response.getHeaders(); + } + + @Override + public String getStatusText() throws IOException + { + return response.getStatusText(); + } + + @Override + public void close() + { + response.close(); + } + + @Override + public int getRawStatusCode() throws IOException + { + return response.getRawStatusCode(); + } + }; + + parent.handleError(buffered); + return; + } + + throw error; + } +}