/** * Copyright (C) 2012 Ness Computing, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.nesscomputing.httpclient.response; import com.nesscomputing.httpclient.HttpClientResponse; import com.nesscomputing.logging.Log; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.Charset; import com.google.common.base.Charsets; import com.google.common.base.Objects; import org.apache.commons.io.IOUtils; /** * Base class to get rid of the repetitive "throw the exception out" method. */ public abstract class AbstractErrorHandlingContentConverter<T> implements ContentConverter<T> { private static final int MAX_RESPONSE_PRINT_CHARS = 4096; private static final Log LOG = Log.findLog(); @Override public T handleError(final HttpClientResponse httpClientResponse, final IOException ex) throws IOException { if (httpClientResponse != null) { LOG.trace("Failure cause is: %s", httpClientResponse.getStatusText()); } throw ex; } /** * Throw a {@link HttpResponseException} with some basic details about the failing request, * and log the first 4k of the response body for diagnostics. */ public static HttpResponseException throwHttpResponseException(HttpClientResponse response) throws IOException { LOG.warn("Remote service responded to \"%s\" with code %d (cause: %s) %s", response.getUri(), response.getStatusCode(), response.getStatusText(), printData(response)); throw new HttpResponseException(response); } private static String printData(HttpClientResponse response) throws IOException { try { if (!LOG.isInfoEnabled()) { return "(response body available, turn on INFO log to see it)"; } final String charsetName = Objects.firstNonNull(response.getCharset(), Charsets.UTF_8.name()); final Charset charset; try { charset = Charset.forName(charsetName); } catch (IllegalArgumentException e) { LOG.warn(e, "While finding charset '%s'", charsetName); return String.format("(invalid charset %s: %s)", charsetName, e); } Reader in = new InputStreamReader(response.getResponseBodyAsStream(), charset); char[] buffer = new char[MAX_RESPONSE_PRINT_CHARS]; buffer[0] = '\n'; int len = IOUtils.read(in, buffer, 1, buffer.length - 1); // Don't close the reader, we should not close the InputStream, otherwise turning // debug on/off changes the behavior... return new String(buffer, 0, len + 1); } catch (Exception e) { // Catching Exception is distasteful, but we really don't want to hide the // HttpResponseException that is about to be thrown. LOG.error(e, "While reading characters from errored response"); return String.format("(exception: %s)", e); } } }