zoukankan      html  css  js  c++  java
  • OkHttp拦截器之获取Response.body的内容

    当使用拦截器获取Response.body.string()后,后面的操作就直接返回Failed了,是因为流只能被使用一次的原因,破解如下

    灵感HttpLoggingInterceptor

    public final class HttpLoggingInterceptor implements Interceptor {
      private static final Charset UTF8 = Charset.forName("UTF-8");
    
      @Override public Response intercept(Chain chain) throws IOException {
        Level level = this.level;
    
        Request request = chain.request();
    
        //如果Log Level 级别为NONOE,则不打印,直接返回
        if (level == Level.NONE) {
          return chain.proceed(request);
        }
    
        //是否打印body
        boolean logBody = level == Level.BODY;
        //是否打印header
        boolean logHeaders = logBody || level == Level.HEADERS;
    
        //获得请求body
        RequestBody requestBody = request.body();
        //请求body是否为空
        boolean hasRequestBody = requestBody != null;
    
        //获得Connection,内部有route、socket、handshake、protocol方法
        Connection connection = chain.connection();
        //如果Connection为null,返回HTTP_1_1,否则返回connection.protocol()
        Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1;
        //比如: --> POST http://121.40.227.8:8088/api http/1.1
        String requestStartMessage = "--> " + request.method() + ' ' + request.url() + ' ' + protocol;
        if (!logHeaders && hasRequestBody) {
          requestStartMessage += " (" + requestBody.contentLength() + "-byte body)";
        }
        logger.log(requestStartMessage);
    
        //打印 Request
        if (logHeaders) {
          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) {
              logger.log("Content-Type: " + requestBody.contentType());
            }
            if (requestBody.contentLength() != -1) {
              logger.log("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)) {
              logger.log(name + ": " + headers.value(i));
            }
          }
    
          if (!logBody || !hasRequestBody) {
            logger.log("--> END " + request.method());
          } else if (bodyEncoded(request.headers())) {
            logger.log("--> END " + request.method() + " (encoded body omitted)");
          } else {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
    
            //编码设为UTF-8
            Charset charset = UTF8;
            MediaType contentType = requestBody.contentType();
            if (contentType != null) {
              charset = contentType.charset(UTF8);
            }
    
            logger.log("");
            if (isPlaintext(buffer)) {
              logger.log(buffer.readString(charset));
              logger.log("--> END " + request.method()
                  + " (" + requestBody.contentLength() + "-byte body)");
            } else {
              logger.log("--> END " + request.method() + " (binary "
                  + requestBody.contentLength() + "-byte body omitted)");
            }
          }
        }
    
        //打印 Response
        long startNs = System.nanoTime();
        Response response;
        try {
          response = chain.proceed(request);
        } catch (Exception e) {
          logger.log("<-- 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";
        //比如 <-- 200 OK http://121.40.227.8:8088/api (36ms)
        logger.log("<-- " + response.code() + ' ' + response.message() + ' '
            + response.request().url() + " (" + tookMs + "ms" + (!logHeaders ? ", "
            + bodySize + " body" : "") + ')');
    
        if (logHeaders) {
          Headers headers = response.headers();
          for (int i = 0, count = headers.size(); i < count; i++) {
            logger.log(headers.name(i) + ": " + headers.value(i));
          }
    
          if (!logBody || !HttpEngine.hasBody(response)) {
            logger.log("<-- END HTTP");
          } else if (bodyEncoded(response.headers())) {
            logger.log("<-- END HTTP (encoded body omitted)");
          } else {
            BufferedSource source = responseBody.source();
            source.request(Long.MAX_VALUE); // Buffer the entire body.
            Buffer buffer = source.buffer();
    
            Charset charset = UTF8;
            MediaType contentType = responseBody.contentType();
            if (contentType != null) {
              try {
                charset = contentType.charset(UTF8);
              } catch (UnsupportedCharsetException e) {
                logger.log("");
                logger.log("Couldn't decode the response body; charset is likely malformed.");
                logger.log("<-- END HTTP");
    
                return response;
              }
            }
    
            if (!isPlaintext(buffer)) {
              logger.log("");
              logger.log("<-- END HTTP (binary " + buffer.size() + "-byte body omitted)");
              return response;
            }
    
            if (contentLength != 0) {
              logger.log("");
                
              //获取Response的body的字符串 并打印
              logger.log(buffer.clone().readString(charset));
            }
    
            logger.log("<-- 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) throws EOFException {
        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");
      }
    }

    修改

    public class MyInterceptor implements Interceptor {
        private static final Charset UTF8 = Charset.forName("UTF-8");
    
        @Override
        public Response intercept(Chain chain) throws IOException {
    
            Request request = chain.request();
            Response response = chain.proceed(request);
    
            ResponseBody responseBody = response.body();
            long contentLength = responseBody.contentLength();
            
            //注意 >>>>>>>>> okhttp3.4.1这里变成了 !HttpHeader.hasBody(response)
            //if (!HttpEngine.hasBody(response)) { 
            if(!HttpHeaders.hasBody(response)){ //HttpHeader -> 改成了 HttpHeaders,看版本进行选择
                //END HTTP
            } else if (bodyEncoded(response.headers())) {
                //HTTP (encoded body omitted)
            } else {
                BufferedSource source = responseBody.source();
                source.request(Long.MAX_VALUE); // Buffer the entire body.
                Buffer buffer = source.buffer();
    
                Charset charset = UTF8;
                MediaType contentType = responseBody.contentType();
                if (contentType != null) {
                    try {
                        charset = contentType.charset(UTF8);
                    } catch (UnsupportedCharsetException e) {
                        //Couldn't decode the response body; charset is likely malformed.
                        return response;
                    }
                }
    
                if (!isPlaintext(buffer)) {
                    L.i("<-- END HTTP (binary " + buffer.size() + "-byte body omitted)");
                    return response;
                }
    
                if (contentLength != 0) {
                    String result = buffer.clone().readString(charset);
                    
                    //获取到response的body的string字符串
                    //do something .... <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                }
    
                L.i("<-- END HTTP (" + buffer.size() + "-byte body)");
            }
            return response;
        }
           
        static boolean isPlaintext(Buffer buffer) throws EOFException {
            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");
        }
    }
  • 相关阅读:
    实例属性 类属性 实例域 类域
    研究数据集
    static 静态域 类域 静态方法 工厂方法 he use of the static keyword to create fields and methods that belong to the class, rather than to an instance of the class 非访问修饰符
    accessor mothod mutator mothod 更改器方法 访问器方法 类的方法可以访问类的任何一个对象的私有域!
    上钻 下钻 切片 转轴 降采样
    识别会话
    Performance Tuning Using Linux Process Management Commands
    Secure Hash Algorithm 3
    grouped differently across partitions
    spark 划分stage Wide vs Narrow Dependencies 窄依赖 宽依赖 解析 作业 job stage 阶段 RDD有向无环图拆分 任务 Task 网络传输和计算开销 任务集 taskset
  • 原文地址:https://www.cnblogs.com/matd/p/12876937.html
Copyright © 2011-2022 走看看