美文网首页
BridgeIntecptor

BridgeIntecptor

作者: 追风z | 来源:发表于2020-08-06 14:36 被阅读0次
    //从url里面获取cookie
          //这个cookieJar是Okhttp上面设置的那个cookieJar
    List<Cookie> cookies = cookieJar.loadForRequest(userRequest.url());
    if (!cookies.isEmpty()) {
      //将所有的cookie添加到cookie头
      requestBuilder.header("Cookie", cookieHeader(cookies));
    }
    
    
    public final class BridgeInterceptor implements Interceptor {
      /**
       * 用来处理Cookie的保存和读取
       */
      private final CookieJar cookieJar;
    
    可以看到是在构造方法里面传入的
      public BridgeInterceptor(CookieJar cookieJar) {
        this.cookieJar = cookieJar;
      }
    
    image.png

    可以看到是在RealCall中调用了这个构造方法

    image.png

    点击里面的cookieHeader看看

    /** Returns a 'Cookie' HTTP request header with all cookies, like {@code a=b; c=d}. */
      //用来将所有的Coookie转换成,key1=value1; key2=value2,例如:a=b; c=d
      private String cookieHeader(List<Cookie> cookies) {
        StringBuilder cookieHeader = new StringBuilder();
    //遍历cookies列表
          //相当于这个种形式 name=value;key=value
        for (int i = 0, size = cookies.size(); i < size; i++) {
          if (i > 0) {
            cookieHeader.append("; ");
          }
          Cookie cookie = cookies.get(i);
          cookieHeader.append(cookie.name()).append('=').append(cookie.value());
        }
        return cookieHeader.toString();
      }
    
        if (userRequest.header("User-Agent") == null) {
          requestBuilder.header("User-Agent", Version.userAgent());
        }
    
        //这里调用下一个拦截器(最后一个拦截器返回回来的网络数据了)
          //这段代码上面是处理器,下面是处理响应Response
        Response networkResponse = chain.proceed(requestBuilder.build());
    
    //从网络的相应中获取Cookie,这个方法里面或保存
    HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());
    
    -->点击跳转:
        public static void receiveHeaders(CookieJar cookieJar, HttpUrl url, Headers headers) {
          //如果没有设置cookie的代理,就直接返回
          if (cookieJar == CookieJar.NO_COOKIES) return;
        
          //从header中解析出cookie
          List<Cookie> cookies = Cookie.parseAll(url, headers);
          if (cookies.isEmpty()) return;
        
          //然后调用保存方法
          cookieJar.saveFromResponse(url, cookies);
        }
    -->点击跳转:查看Cookie.parseAll(url, headers)
        
          public static List<Cookie> parseAll(HttpUrl url, Headers headers) {
            List<String> cookieStrings = headers.values("Set-Cookie");
            List<Cookie> cookies = null;
        
            for (int i = 0, size = cookieStrings.size(); i < size; i++) {
              Cookie cookie = Cookie.parse(url, cookieStrings.get(i));
              if (cookie == null) continue;
              if (cookies == null) cookies = new ArrayList<>();
              cookies.add(cookie);
            }
        
            return cookies != null
                ? Collections.unmodifiableList(cookies)
                : Collections.<Cookie>emptyList();
          }
    
    ============================================
        //根据网络的响应创建一个Builder,这和前面从请求体创建一个Builder类似
        Response.Builder responseBuilder = networkResponse.newBuilder()
            .request(userRequest);
    
        if (transparentGzip
            && "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
            && HttpHeaders.hasBody(networkResponse)) {
          //在这里处理响应体是gzip类型的工作
          //networkResponse.body().source():可以理解为就是输入流
          //这里其实是一个包装设计模式
          GzipSource responseBody = new GzipSource(networkResponse.body().source());
          Headers strippedHeaders = networkResponse.headers().newBuilder()
              .removeAll("Content-Encoding")
              .removeAll("Content-Length")
              .build();
          responseBuilder.headers(strippedHeaders);
          //这里用了一个包装类RealResponseBody,用来转换gzip响应体,这个后面再分析
          //Okio.buffer可以理解为包装后的输入流
          responseBuilder.body(new RealResponseBody(strippedHeaders, Okio.buffer(responseBody)));
        }
    
        //然后根据响应体Builder创建一个Response
        return responseBuilder.build();
    
    -->点击跳转:RealResponseBody
    
        public final class RealResponseBody extends ResponseBody {
          private final Headers headers;
          private final BufferedSource source;
        
          public RealResponseBody(Headers headers, BufferedSource source) {
            this.headers = headers;
            this.source = source;
          }
        
          @Override public MediaType contentType() {
            String contentType = headers.get("Content-Type");
            return contentType != null ? MediaType.parse(contentType) : null;
          }
        
          @Override public long contentLength() {
            return HttpHeaders.contentLength(headers);
          }
        
          @Override public BufferedSource source() {
            return source;
          }
        }
    responseBody-->new GzipSource(networkResponse.body().source());
    也就是我们本地在读取这个Gzip响应的时候会调用这个GzipSource的read方法
    在这个方法里面吧真实的流给拆出来了(原来的流是GZip的流,这里把它拆成真实的流了)
         public long read(Buffer sink, long byteCount) throws IOException {
            if (byteCount < 0L) {
                throw new IllegalArgumentException("byteCount < 0: " + byteCount);
            } else if (byteCount == 0L) {
                return 0L;
            } else {
                if (this.section == 0) {
                    this.consumeHeader();
                    this.section = 1;
                }
    
                if (this.section == 1) {
                    long offset = sink.size;
                    long result = this.inflaterSource.read(sink, byteCount);
                    if (result != -1L) {
                        this.updateCrc(sink, offset, result);
                        return result;
                    }
    
                    this.section = 2;
                }
    
                if (this.section == 2) {
                    this.consumeTrailer();
                    this.section = 3;
                    if (!this.source.exhausted()) {
                        throw new IOException("gzip finished without exhausting source");
                    }
                }
    
                return -1L;
            }
        }
    

    相关文章

      网友评论

          本文标题:BridgeIntecptor

          本文链接:https://www.haomeiwen.com/subject/erszrktx.html