16c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer/* 26c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Copyright (C) 2015 Square, Inc. 36c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * 46c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Licensed under the Apache License, Version 2.0 (the "License"); 56c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * you may not use this file except in compliance with the License. 66c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * You may obtain a copy of the License at 76c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * 86c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * http://www.apache.org/licenses/LICENSE-2.0 96c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * 106c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Unless required by applicable law or agreed to in writing, software 116c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * distributed under the License is distributed on an "AS IS" BASIS, 126c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * See the License for the specific language governing permissions and 146c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * limitations under the License. 156c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer */ 166c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererpackage com.squareup.okhttp.logging; 176c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 186c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.Connection; 196c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.Headers; 206c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.Interceptor; 216c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.MediaType; 226c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.OkHttpClient; 236c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.Protocol; 246c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.Request; 256c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.RequestBody; 266c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.Response; 276c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.ResponseBody; 286c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.internal.Platform; 296c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.internal.http.HttpEngine; 306c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport java.io.IOException; 316c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport java.nio.charset.Charset; 326c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport java.util.concurrent.TimeUnit; 336c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport okio.Buffer; 346c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport okio.BufferedSource; 356c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 366c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer/** 376c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * An OkHttp interceptor which logs request and response information. Can be applied as an 386c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * {@linkplain OkHttpClient#interceptors() application interceptor} or as a 396c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * {@linkplain OkHttpClient#networkInterceptors() network interceptor}. 406c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * <p> 416c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * The format of the logs created by this class should not be considered stable and may change 426c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * slightly between releases. If you need a stable logging format, use your own interceptor. 436c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer */ 446c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererpublic final class HttpLoggingInterceptor implements Interceptor { 456c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer private static final Charset UTF8 = Charset.forName("UTF-8"); 466c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 476c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer public enum Level { 486c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer /** No logs. */ 496c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer NONE, 506c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer /** 516c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Logs request and response lines. 526c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * <p> 536c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Example: 546c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * <pre>{@code 556c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * --> POST /greeting HTTP/1.1 (3-byte body) 566c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * 576c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * <-- HTTP/1.1 200 OK (22ms, 6-byte body) 586c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * }</pre> 596c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer */ 606c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer BASIC, 616c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer /** 626c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Logs request and response lines and their respective headers. 636c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * <p> 646c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Example: 656c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * <pre>{@code 666c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * --> POST /greeting HTTP/1.1 676c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Host: example.com 686c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Content-Type: plain/text 696c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Content-Length: 3 706c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * --> END POST 716c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * 726c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * <-- HTTP/1.1 200 OK (22ms) 736c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Content-Type: plain/text 746c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Content-Length: 6 756c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * <-- END HTTP 766c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * }</pre> 776c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer */ 786c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer HEADERS, 796c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer /** 806c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Logs request and response lines and their respective headers and bodies (if present). 816c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * <p> 826c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Example: 836c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * <pre>{@code 846c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * --> POST /greeting HTTP/1.1 856c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Host: example.com 866c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Content-Type: plain/text 876c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Content-Length: 3 886c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * 896c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Hi? 906c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * --> END GET 916c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * 926c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * <-- HTTP/1.1 200 OK (22ms) 936c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Content-Type: plain/text 946c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Content-Length: 6 956c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * 966c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * Hello! 976c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * <-- END HTTP 986c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer * }</pre> 996c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer */ 1006c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer BODY 1016c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1026c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1036c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer public interface Logger { 1046c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer void log(String message); 1056c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1066c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer /** A {@link Logger} defaults output appropriate for the current platform. */ 1076c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Logger DEFAULT = new Logger() { 1086c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer @Override public void log(String message) { 1096c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Platform.get().log(message); 1106c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1116c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer }; 1126c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1136c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1146c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer public HttpLoggingInterceptor() { 1156c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer this(Logger.DEFAULT); 1166c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1176c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1186c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer public HttpLoggingInterceptor(Logger logger) { 1196c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer this.logger = logger; 1206c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1216c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1226c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer private final Logger logger; 1236c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1246c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer private volatile Level level = Level.NONE; 1256c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1266c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer /** Change the level at which this interceptor logs. */ 1276c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer public HttpLoggingInterceptor setLevel(Level level) { 1286c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (level == null) throw new NullPointerException("level == null. Use Level.NONE instead."); 1296c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer this.level = level; 1306c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer return this; 1316c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1326c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1336c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer public Level getLevel() { 1346c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer return level; 1356c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1366c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1376c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer @Override public Response intercept(Chain chain) throws IOException { 1386c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Level level = this.level; 1396c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1406c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Request request = chain.request(); 1416c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (level == Level.NONE) { 1426c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer return chain.proceed(request); 1436c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1446c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1456c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer boolean logBody = level == Level.BODY; 1466c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer boolean logHeaders = logBody || level == Level.HEADERS; 1476c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1486c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer RequestBody requestBody = request.body(); 1496c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer boolean hasRequestBody = requestBody != null; 1506c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1516c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Connection connection = chain.connection(); 1526c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Protocol protocol = connection != null ? connection.getProtocol() : Protocol.HTTP_1_1; 1536c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer String requestStartMessage = 1546c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer "--> " + request.method() + ' ' + request.httpUrl() + ' ' + protocol(protocol); 1556c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (!logHeaders && hasRequestBody) { 1566c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer requestStartMessage += " (" + requestBody.contentLength() + "-byte body)"; 1576c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1586c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log(requestStartMessage); 1596c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1606c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (logHeaders) { 1616c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (hasRequestBody) { 1626c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer // Request body headers are only present when installed as a network interceptor. Force 1636c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer // them to be included (when available) so there values are known. 1646c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (requestBody.contentType() != null) { 1656c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log("Content-Type: " + requestBody.contentType()); 1666c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1676c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (requestBody.contentLength() != -1) { 1686c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log("Content-Length: " + requestBody.contentLength()); 1696c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1706c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1716c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1726c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Headers headers = request.headers(); 1736c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer for (int i = 0, count = headers.size(); i < count; i++) { 1746c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer String name = headers.name(i); 1756c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer // Skip headers from the request body as they are explicitly logged above. 1766c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) { 1776c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log(name + ": " + headers.value(i)); 1786c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1796c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1806c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1816c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (!logBody || !hasRequestBody) { 1826c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log("--> END " + request.method()); 1836c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } else if (bodyEncoded(request.headers())) { 1846c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log("--> END " + request.method() + " (encoded body omitted)"); 1856c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } else { 1866c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Buffer buffer = new Buffer(); 1876c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer requestBody.writeTo(buffer); 1886c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1896c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Charset charset = UTF8; 1906c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer MediaType contentType = requestBody.contentType(); 1916c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (contentType != null) { 1926c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer contentType.charset(UTF8); 1936c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 1946c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1956c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log(""); 1966c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log(buffer.readString(charset)); 1976c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 1986c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log("--> END " + request.method() 1996c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer + " (" + requestBody.contentLength() + "-byte body)"); 2006c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 2016c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 2026c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 2036c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer long startNs = System.nanoTime(); 2046c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Response response = chain.proceed(request); 2056c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs); 2066c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 2076c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer ResponseBody responseBody = response.body(); 2086c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log("<-- " + protocol(response.protocol()) + ' ' + response.code() + ' ' 2096c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer + response.message() + " (" + tookMs + "ms" 2106c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer + (!logHeaders ? ", " + responseBody.contentLength() + "-byte body" : "") + ')'); 2116c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 2126c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (logHeaders) { 2136c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Headers headers = response.headers(); 2146c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer for (int i = 0, count = headers.size(); i < count; i++) { 2156c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log(headers.name(i) + ": " + headers.value(i)); 2166c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 2176c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 2186c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (!logBody || !HttpEngine.hasBody(response)) { 2196c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log("<-- END HTTP"); 2206c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } else if (bodyEncoded(response.headers())) { 2216c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log("<-- END HTTP (encoded body omitted)"); 2226c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } else { 2236c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer BufferedSource source = responseBody.source(); 2246c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer source.request(Long.MAX_VALUE); // Buffer the entire body. 2256c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Buffer buffer = source.buffer(); 2266c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 2276c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer Charset charset = UTF8; 2286c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer MediaType contentType = responseBody.contentType(); 2296c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (contentType != null) { 2306c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer charset = contentType.charset(UTF8); 2316c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 2326c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 2336c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer if (responseBody.contentLength() != 0) { 2346c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log(""); 2356c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log(buffer.clone().readString(charset)); 2366c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 2376c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 2386c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer logger.log("<-- END HTTP (" + buffer.size() + "-byte body)"); 2396c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 2406c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 2416c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 2426c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer return response; 2436c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 2446c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 2456c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer private boolean bodyEncoded(Headers headers) { 2466c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer String contentEncoding = headers.get("Content-Encoding"); 2476c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity"); 2486c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 2496c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 2506c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer private static String protocol(Protocol protocol) { 2516c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer return protocol == Protocol.HTTP_1_0 ? "HTTP/1.0" : "HTTP/1.1"; 2526c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 2536c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer} 254