Summary of okhttp 3.4.2 interceptor

Keywords: Android OkHttp network Retrofit

I wrote one in 16 years Simple configuration of RxJava+Retrofit+OkHttp combination in network request , this article can be used as a supplement to it.

As an important member of the okhttp interceptor, if we make good use of it, we will get twice the result with half the effort. First, let's look at the interceptor's core interface, Interceptor:

public interface Interceptor {
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    Connection connection();
  }
}

To implement interception, it is necessary to define a class to implement the interface Interceptor, rewrite the method intercept, which receives the parameter Chain and returns the Response to implement its own interception logic in the method.

The following is a brief summary of the functions that can be implemented in the intercept method:

Implementation interface

Before we start, we define the LoggingInterceptor to implement the interface Interceptor. The variables and methods will be used later:

public final class LoggingInterceptor implements Interceptor {

    private static final Charset UTF8 = Charset.forName("UTF-8");
    public static final String HTTP_HEADER = "<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">";
    public static final String HTTP_TAIL = "</string>";

    private 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 bodyEncoded(Headers headers) {
        String contentEncoding = headers.get("Content-Encoding");
        return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity");
    }

    private String protocol(Protocol protocol) {
        return protocol == Protocol.HTTP_1_0 ? "HTTP/1.0" : "HTTP/1.1";
    }
}

Print request

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        RequestBody requestBody = request.body();
        boolean hasRequestBody = requestBody != null;
        Connection connection = chain.connection();
        Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1;
        String requestStartMessage =
                "--> " + request.method() + ' ' + request.url() + ' ' + protocol(protocol);
        //Request method and url
        logger.log(requestStartMessage);

        logger.log("---Request header---");
        Headers headers = request.headers();
        for (int i = 0, count = headers.size(); i < count; i++) {
            logger.log(headers.name(i) + ": " + headers.value(i));
        }

        logger.log("---Request parameters---");
        HttpUrl url = request.url();
        for (String name : url.queryParameterNames()) {
            StringBuffer sb = new StringBuffer();
            sb.append(url.queryParameterValues(name));
            //Remove the superfluous"[]"
            sb.deleteCharAt(sb.length() - 1);
            sb.deleteCharAt(0);
            logger.log(name + ": " + sb);
        }

        logger.log("---Request body---");
        if (hasRequestBody && !bodyEncoded(headers)) {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
            Charset charset = UTF8;
            MediaType contentType = requestBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(UTF8);
            }
            if (isPlaintext(buffer)) {
                logger.log(buffer.readString(charset).replaceAll("&", "\n"));
            }
        }
        //End of request
        logger.log("");
        logger.log("--> END Request");
        logger.log("");

        return chain.proceed(request);
    }

Modification request

Modify request header
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request original = chain.request();
        Request.Builder requestBuilder = original.newBuilder()
                .method(original.method(), original.body());
        Headers.Builder header = new Headers.Builder();
        header.add("os", "android");
        header.add("version", "1.2.5");
        Request request = requestBuilder.headers(header.build()).build();
        return chain.proceed(request);
    }
Modify request body

This modification is only for the following requirements:

  • Get the original request body string, such as {"name":"Sbingo","job":"android developer"}
  • Add the secret Key/Value pair to the string to get {"name":"Sbingo","job":"android developer","secret":"F910EUY09"}
  • Label before and after string
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">{"name":"Sbingo","job":"android developer","secret":"F910EUY09"}</string>
  • Use the string from the previous step as the request body
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();
        Request newRequest;
        if (originalRequest.body() instanceof FormBody) {
            Request.Builder requestBuilder = originalRequest.newBuilder();
            StringBuilder jsonRequest = new StringBuilder();
            jsonRequest.append("{");
            FormBody oldFormBody = (FormBody) originalRequest.body();
            for (int i = 0; i < oldFormBody.size(); i++) {
                String name = oldFormBody.encodedName(i);
                String value = oldFormBody.encodedValue(i);
                jsonRequest.append("\"");
                jsonRequest.append(name);
                jsonRequest.append("\":\"");
                jsonRequest.append(value);
                jsonRequest.append("\"");
                jsonRequest.append(",");
            }
            jsonRequest.append("\"secret\":\"");
            jsonRequest.append("F910EUY09");
            jsonRequest.append("\"");
            jsonRequest.append("}");
            String request = HTTP_HEADER + jsonRequest.toString() + HTTP_TAIL;
            MediaType mediaType = MediaType.parse("text/xml; charset=utf-8");
            newRequest = requestBuilder.post(RequestBody.create(mediaType, request)).build();
        } else {
            throw new RuntimeException("Please use the form to submit the network request!");
        }
        return chain.proceed(newRequest);
    }

Print response

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        long startNs = System.nanoTime();
        Response response = chain.proceed(request);
        long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);

        ResponseBody responseBody = response.body();
        //Response code, url, etc
        logger.log("<-- "
                + response.code()
                + ' '
                + response.message()
                + ' '
                + response.request().url()
                + " ("
                + tookMs
                + "ms"
                + ')');

        logger.log("---Response head---");
        Headers responseHeaders = response.headers();
        for (int i = 0, count = responseHeaders.size(); i < count; i++) {
            logger.log(responseHeaders.name(i) + ": " + responseHeaders.value(i));
        }

        logger.log("---Response body---");
        if (HttpHeaders.hasBody(response) && !bodyEncoded(responseHeaders)) {
            BufferedSource source = responseBody.source();
            source.request(Long.MAX_VALUE);
            Buffer responseBuffer = source.buffer();
            Charset responseCharset = UTF8;
            MediaType responseContentType = responseBody.contentType();
            if (responseContentType != null) {
                responseCharset = responseContentType.charset(UTF8);
            }
            if (isPlaintext(responseBuffer)) {
                com.orhanobut.logger.Logger.json(responseBuffer.clone().readString(responseCharset));
            }
        }
        logger.log("");
        logger.log("<-- END Response");

        return response;
    }

Posted by krio on Fri, 03 Apr 2020 15:19:38 -0700