package com.r0ysue.learnokhttp; /* * Copyright (C) 2015 Square, 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. */ import android.util.Log; import java.io.EOFException; import java.io.IOException; import java.nio.charset.Charset; import java.util.concurrent.TimeUnit; import okhttp3.Connection; import okhttp3.Headers; import okhttp3.Interceptor; import okhttp3.MediaType; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import okhttp3.ResponseBody; import okhttp3.internal.http.HttpHeaders; import okio.Buffer; import okio.BufferedSource; import okio.GzipSource; public final class okhttp3Logging implements Interceptor { private static final String TAG = "okhttpGET"; private static final Charset UTF8 = Charset.forName("UTF-8"); @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); RequestBody requestBody = request.body(); boolean hasRequestBody = requestBody != null; Connection connection = chain.connection(); String requestStartMessage = "--> " + request.method() + ' ' + request.url(); Log.e(TAG, requestStartMessage); if (hasRequestBody) { // Request body headers are only present when installed as a network interceptor. Force // them to be included (when available) so there values are known. if (requestBody.contentType() != null) { Log.e(TAG, "Content-Type: " + requestBody.contentType()); } if (requestBody.contentLength() != -1) { Log.e(TAG, "Content-Length: " + requestBody.contentLength()); } } Headers headers = request.headers(); for (int i = 0, count = headers.size(); i < count; i++) { String name = headers.name(i); // Skip headers from the request body as they are explicitly logged above. if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) { Log.e(TAG, name + ": " + headers.value(i)); } } if (!hasRequestBody) { Log.e(TAG, "--> END " + request.method()); } else if (bodyHasUnknownEncoding(request.headers())) { Log.e(TAG, "--> END " + request.method() + " (encoded body omitted)"); } else { Buffer buffer = new Buffer(); requestBody.writeTo(buffer); Charset charset = UTF8; MediaType contentType = requestBody.contentType(); if (contentType != null) { charset = contentType.charset(UTF8); } Log.e(TAG, ""); if (isPlaintext(buffer)) { Log.e(TAG, buffer.readString(charset)); Log.e(TAG, "--> END " + request.method() + " (" + requestBody.contentLength() + "-byte body)"); } else { Log.e(TAG, "--> END " + request.method() + " (binary " + requestBody.contentLength() + "-byte body omitted)"); } } long startNs = System.nanoTime(); Response response; try { response = chain.proceed(request); } catch (Exception e) { Log.e(TAG, "<-- HTTP FAILED: " + e); throw e; } long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs); ResponseBody responseBody = response.body(); long contentLength = responseBody.contentLength(); String bodySize = contentLength != -1 ? contentLength + "-byte" : "unknown-length"; Log.e(TAG, "<-- " + response.code() + (response.message().isEmpty() ? "" : ' ' + response.message()) + ' ' + response.request().url() + " (" + tookMs + "ms" + (", " + bodySize + " body:" + "") + ')'); Headers myheaders = response.headers(); for (int i = 0, count = myheaders.size(); i < count; i++) { Log.e(TAG, myheaders.name(i) + ": " + myheaders.value(i)); } if (!HttpHeaders.hasBody(response)) { Log.e(TAG, "<-- END HTTP"); } else if (bodyHasUnknownEncoding(response.headers())) { Log.e(TAG, "<-- END HTTP (encoded body omitted)"); } else { BufferedSource source = responseBody.source(); source.request(Long.MAX_VALUE); // Buffer the entire body. Buffer buffer = source.buffer(); Long gzippedLength = null; if ("gzip".equalsIgnoreCase(myheaders.get("Content-Encoding"))) { gzippedLength = buffer.size(); GzipSource gzippedResponseBody = null; try { gzippedResponseBody = new GzipSource(buffer.clone()); buffer = new Buffer(); buffer.writeAll(gzippedResponseBody); } finally { if (gzippedResponseBody != null) { gzippedResponseBody.close(); } } } Charset charset = UTF8; MediaType contentType = responseBody.contentType(); if (contentType != null) { charset = contentType.charset(UTF8); } if (!isPlaintext(buffer)) { Log.e(TAG, ""); Log.e(TAG, "<-- END HTTP (binary " + buffer.size() + "-byte body omitted)"); return response; } if (contentLength != 0) { Log.e(TAG, ""); Log.e(TAG, buffer.clone().readString(charset)); } if (gzippedLength != null) { Log.e(TAG, "<-- END HTTP (" + buffer.size() + "-byte, " + gzippedLength + "-gzipped-byte body)"); } else { Log.e(TAG, "<-- END HTTP (" + buffer.size() + "-byte body)"); } } return response; } /** * Returns true if the body in question probably contains human readable text. Uses a small sample * of code points to detect unicode control characters commonly used in binary file signatures. */ static boolean isPlaintext(Buffer buffer) { try { Buffer prefix = new Buffer(); long byteCount = buffer.size() < 64 ? buffer.size() : 64; buffer.copyTo(prefix, 0, byteCount); for (int i = 0; i < 16; i++) { if (prefix.exhausted()) { break; } int codePoint = prefix.readUtf8CodePoint(); if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { return false; } } return true; } catch (EOFException e) { return false; // Truncated UTF-8 sequence. } } private boolean bodyHasUnknownEncoding(Headers myheaders) { String contentEncoding = myheaders.get("Content-Encoding"); return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity") && !contentEncoding.equalsIgnoreCase("gzip"); } }