美文网首页
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

    可以看到是在RealCall中调用了这个构造方法 点击里面的cookieHeader看看

网友评论

      本文标题:BridgeIntecptor

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