OkHttp的源码分析(三)——BridgeInterceptor拦截器分析

继续上一篇文章,我们看BridgeInterceptor这个拦截器的具体工作内容

目录

BridgeInterceptor类的注释

BridgeInterceptor的代码解析

关于Cookie的设置


BridgeInterceptor类的注释

/**
* Bridges from application code to network code. First it builds a network request from a user
* request. Then it proceeds to call the network. Finally it builds a user response from the network
* response.
*/

翻译过来,大意是说:这个BridgeInterceptor是从应用程序代码到网络代码的桥梁。首先它构建一个来自用户的网络请求,然后它继续调用网络。最后,它从网络构建用户响应

这样就清楚了,他的核心就是构建网络请求

BridgeInterceptor的代码解析

@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
  val userRequest = chain.request()
  val requestBuilder = userRequest.newBuilder()

  val body = userRequest.body
  if (body != null) {
      //添加头信息
      val contentType = body.contentType()
      if (contentType != null) {
        requestBuilder.header("Content-Type", contentType.toString())
      }

      val contentLength = body.contentLength()
      if (contentLength != -1L) {
        requestBuilder.header("Content-Length", contentLength.toString())
        requestBuilder.removeHeader("Transfer-Encoding")
      } else {
        requestBuilder.header("Transfer-Encoding", "chunked")
        requestBuilder.removeHeader("Content-Length")
      }
    }

    if (userRequest.header("Host") == null) {
      requestBuilder.header("Host", userRequest.url.toHostHeader())
    }

    //默认是Keep-Alive
    if (userRequest.header("Connection") == null) {
      requestBuilder.header("Connection", "Keep-Alive")
    }

    // If we add an "Accept-Encoding: gzip" header field we're responsible for also decompressing
    // the transfer stream.
    var transparentGzip = false
    //默认支持gzip编码压缩
    if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
      //支持gzip的标识位
      transparentGzip = true
      requestBuilder.header("Accept-Encoding", "gzip")
    }

    //添加cookie
    val cookies = cookieJar.loadForRequest(userRequest.url)
    if (cookies.isNotEmpty()) {
      requestBuilder.header("Cookie", cookieHeader(cookies))
    }

    if (userRequest.header("User-Agent") == null) {
      requestBuilder.header("User-Agent", userAgent)
    }
    //发送请求,获得服务响应
    val networkResponse = chain.proceed(requestBuilder.build())
    //接受服务端返回cookie
    cookieJar.receiveHeaders(userRequest.url, networkResponse.headers)

    val responseBuilder = networkResponse.newBuilder()
        .request(userRequest)
    //如果服务返回Content-Encoding带有gzip,做转换解压缩操作
    if (transparentGzip &&
        "gzip".equals(networkResponse.header("Content-Encoding"), ignoreCase = true) &&
        networkResponse.promisesBody()) {
      val responseBody = networkResponse.body
      if (responseBody != null) {
        val gzipSource = GzipSource(responseBody.source())
        val strippedHeaders = networkResponse.headers.newBuilder()
            .removeAll("Content-Encoding")
            .removeAll("Content-Length")
            .build()
        responseBuilder.headers(strippedHeaders)
        val contentType = networkResponse.header("Content-Type")
        responseBuilder.body(RealResponseBody(contentType, -1L, gzipSource.buffer()))
    }
  }
    //构建response
    return responseBuilder.build()
}

核心部分已经注释,可以看出BridgeInterceptor核心做了三件事,

  • 首先,通过requestBuilder构建请求,添加各种请求头信息
  • 之后,将构建的请求发送出去,获得响应
  • 最后,将获得到的响应数据做转换用户可以用的response

至于里面的涉及到的请求头“Content-Type”,"Content-Length","Transfer-Encoding"等等自行了解即可

关于Cookie的设置

这里面多提一下Cookie,它是添加到请求头里面,主要作用是客户端存储访问服务器的一些信息,这些信息的作用,可以根据具体业务来设置。OkHttp默认是不保存cookie的,需要做单独设置

private final HashMap<String, List<Cookie>> cookieMap = new HashMap<>();

OkHttpClient okHttpClient = new OkHttpClient.Builder().cookieJar(new CookieJar() {
      @Override
      public void saveFromResponse(@NotNull HttpUrl httpUrl, @NotNull List<Cookie> list) {
          cookieMap.put(httpUrl.host(), list);
      }

      @Override
      public List<Cookie> loadForRequest(@NotNull HttpUrl httpUrl) {
          List<Cookie> cookies = cookieMap.get(httpUrl.host());
          return cookies != null ? cookies : new ArrayList<>();
      }
}).build();

整体来看BridgeInterceptor做的事情比较简单,就分析到这里

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ezview_uniview

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值