/** Log response data. Returns replacement {@link TypedInput}. */ private static TypedInput logResponse( String url, int statusCode, TypedInput body, long elapsedTime) throws IOException { LOGGER.fine("<--- HTTP " + statusCode + " " + url + " (" + elapsedTime + "ms)"); byte[] bodyBytes = Utils.streamToBytes(body.in()); String bodyString = new String(bodyBytes, UTF_8); for (int i = 0; i < bodyString.length(); i += LOG_CHUNK_SIZE) { int end = Math.min(bodyString.length(), i + LOG_CHUNK_SIZE); LOGGER.fine(bodyString.substring(i, end)); } LOGGER.fine("<--- END HTTP"); // Since we consumed the entire input stream, return a new, identical one from its bytes. return new TypedByteArray(body.mimeType(), bodyBytes); }
/** * Execute an HTTP request. * * @return HTTP response object of specified {@code type}. * @throws RetrofitError Thrown if any error occurs during the HTTP request. */ private Object invokeRequest(RestMethodInfo methodDetails, Object[] args) { methodDetails.init(); // Ensure all relevant method information has been loaded. String url = server.getUrl(); try { Request request = new RequestBuilder(converter) // .setApiUrl(server.getUrl()) .setArgs(args) .setHeaders(headers.get()) .setMethodInfo(methodDetails) .build(); url = request.getUrl(); if (!methodDetails.isSynchronous) { // If we are executing asynchronously then update the current thread with a useful name. Thread.currentThread().setName(THREAD_PREFIX + url); } if (LOGGER.isLoggable(Level.FINE)) { logRequest(request); } Object profilerObject = null; if (profiler != null) { profilerObject = profiler.beforeCall(); } long start = System.nanoTime(); Response response = clientProvider.get().execute(request); long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start); int statusCode = response.getStatus(); if (profiler != null) { RequestInformation requestInfo = getRequestInfo(server, methodDetails, request); profiler.afterCall(requestInfo, elapsedTime, statusCode, profilerObject); } TypedInput body = response.getBody(); if (LOGGER.isLoggable(Level.FINE)) { // Replace the response since the logger needs to consume the entire input stream. body = logResponse(url, response.getStatus(), body, elapsedTime); } List<Header> headers = response.getHeaders(); for (Header header : headers) { if (HTTP.CONTENT_TYPE.equalsIgnoreCase(header.getName()) // && !UTF_8.equalsIgnoreCase(Utils.parseCharset(header.getValue()))) { throw new IOException("Only UTF-8 charset supported."); } } Type type = methodDetails.type; if (statusCode >= 200 && statusCode < 300) { // 2XX == successful request if (type.equals(Response.class)) { return response; } if (body == null) { return null; } try { return converter.fromBody(body, type); } catch (ConversionException e) { throw RetrofitError.conversionError(url, response, converter, type, e); } } throw RetrofitError.httpError(url, response, converter, type); } catch (RetrofitError e) { throw e; // Pass through our own errors. } catch (IOException e) { throw RetrofitError.networkError(url, e); } catch (Throwable t) { throw RetrofitError.unexpectedError(url, t); } }