okhttp学习系列之BridgeInterceptor拦截器

概述

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.
 */

大概意思就是作为用户网络请求和真实的网络请求的桥梁,将用户的网络请求转化为真实的网络请求,将真实的网络回复(response)转化为用户的网络回复(response)

走读代码可以看到他做了几个事情

  • 添加http请求的header,如Content-Type等
  • 对gzip类的response进行解压操作

代码走读

  @Throws(IOException::class)
  override fun intercept(chain: Interceptor.Chain): Response {
    val userRequest = chain.request()
    //根据userRequest构造一个新的request, 这大概就是说的Bridge的作用吧
    val requestBuilder = userRequest.newBuilder()

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

      val contentLength = body.contentLength()
      if (contentLength != -1L) {
        //如果contentLength存在, 则添加到Content-Lenght字段中
        requestBuilder.header("Content-Length", contentLength.toString())
        requestBuilder.removeHeader("Transfer-Encoding")
      } else {
        //如果contentLength不存在, 就认为是分块传输
        requestBuilder.header("Transfer-Encoding", "chunked")
        requestBuilder.removeHeader("Content-Length")
      }
    }

    if (userRequest.header("Host") == null) {
      //从url中解析出来host
      requestBuilder.header("Host", userRequest.url.toHostHeader())
    }

    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
    if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
      transparentGzip = true
      //默认的Accept-Encoding是gzip
      requestBuilder.header("Accept-Encoding", "gzip")
    }

    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())

    cookieJar.receiveHeaders(userRequest.url, networkResponse.headers)

    //将networkResponse转化为用户的response
    val responseBuilder = networkResponse.newBuilder()
        .request(userRequest)

    if (transparentGzip &&
        "gzip".equals(networkResponse.header("Content-Encoding"), ignoreCase = true) &&
        networkResponse.promisesBody()) {
      val responseBody = networkResponse.body
      if (responseBody != null) {
        //对gzip的返回类型进行解压
        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()))
      }
    }

    return responseBuilder.build()
  }

各个header的含义

这里复习下涉及到的各个Header的含义

  • Content-Type 表示所述的媒体资源的类型,常见的有
Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=something
  • Content-Length 表示实体内容的长度,但是有可能会不存在,具体规则参看文章https://www.cnblogs.com/lovelacelee/p/5385683.html, 主要是在http1.1及以后的版本中,如果是keep alive,则content-length与chunk必然是二选一,如果是非keep-alive,则和http1.0以后,content-Length可有可无
  • Transfer-Encoding 取值有chunked compress deflate gzip identity 。具体参看https://cloud.tencent.com/developer/section/1190008
  • Host 表示服务器的域名
  • Connection 控制网络连接是否保持打开状态,当前事务结束之后,如果发送的值是keep-alive,连接是持久的并且不关闭。这个是在http1.1之后加的特性
  • Accept-Encoding 客户端能够接受的编码格式
  • Range 告知服务端,客户端下载该文件想要从指定的位置开始下载
  • Cookie 不解释了
  • User-Agent 不解释了

CookieJar的实现

OkHttp允许客户端自己实现CookieJar,当然服务端也预定义了一些CookieJar的子类,详细查看

NoCookies

默认没有处理Cookies

RecordingCookieJar

在内存中保留了一份Cookie

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值