这是链中的最后一个拦截器。它对服务器进行网络调用。
##源码解析
Http 协议分为两种,请求报文和响应报文,请求报文里面有请求头、Body,而响应报文里面有响应头、Body、响应码,但是实际不止这些,还有请求方式(Get 还是 Post)、协议类型(Http 还是 Https)、协议版本(Http 1.0 还是 Http 2.0),我们如果使用最原始的方式,将这些信息统一转换成纯文本再传给后台,那么会有一个问题,我们将无法管控这些信息,因此 OkHttp 在请求的过程中将这些信息包装成了对象,而在传输的时候将这些对象转换成纯文本给后台,而响应的时候也雷同。所以 Http 编解码器就成为了负责对象和文本之间相互转换的工具。
会判断当前请求方式是否支持写入 Body,在这里我们可以看到,Get 和 Head 请求是不能有 Body 的,所以就算你在 Get 或 Head 请求上面指定了 Body,OkHttp 也不会帮你传过去。
在写出请求头之后,接下来就是写出请求的 Body。
关于requestBody.isDuplex(),是检查请求是否双工,对于常规的HTTP调用,请求总是在响应开始接收之前完成发送。使用双工,请求和响应可以交错!也就是说,请求正文字节可以在接收到响应头或正文字节之后发送。
如果是双工的,则准备一个双工主体,以便应用程序稍后可以发送请求主体。
请求报文处理结束,接下来处理响应报文。
先处理 Header 再处理 Body。
再把请求发送的时间和请求响应的时间设置给 Response 对象,有了这两个时间,我们可以直接通过计算来得出请求耗时。
我们可以看到,当响应码为 100 时,这个时候拦截器又读取了一次响应,
-
状态码100含义:客户端应当继续发送请求。这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝。客户端应当继续发送请求的剩余部分,或者如果请求已经完成,忽略这个响应。服务器必须在请求完成后向客户端发送一个最终响应。
-
原来这块属于 Http 协议的内容,当后台返回的响应码是 100 的时候,我们应当遵守协议的规则,再发起一次网络请求来重新获取响应的内容
-
当然这块 OkHttp 已经帮我们处理了,所以我们不需要自己再去处理了
读完响应头部分,接着就是把后台返回的 Body 部分通过 Http 编解码器读取并转换成 Java 对象
-
状态码101:服务器已经理解了客户端的请求,并将通过Upgrade 消息头通知客户端采用不同的协议来完成这个请求。在发送完这个响应最后的空行后,服务器将会切换到在Upgrade 消息头中定义的那些协议。 只有在切换新的协议更有好处的时候才应该采取类似措施。例如,切换到新的HTTP 版本比旧版本更有优势,或者切换到一个实时且同步的协议以传送利用此类特性的资源。
-
WebSocket 和 Http 属于 TCP 协议,都是应用层协议,WeSocket 的出现是为了解决 Http 只能单向通讯的问题,也就是只能客户端请求服务器的问题,而 WebSocket 可以建立双向通讯,也就是客户端和服务器可以相互访问,常被用于解决使用 Http 不断轮询来获取最新数据的问题。
-
状态码204服务器成功处理了请求,但不需要返回任何实体内容,并且希望返回更新了的元信息。响应可能通过实体头部的形式,返回新的或更新后的元信息。如果存在这些头部信息,则应当与所请求的变量相呼应。 如果客户端是浏览器的话,那么用户浏览器应保留发送了该请求的页面,而不产生任何文档视图上的变化,即使按照规范新的或更新后的元信息应当被应用到用户浏览器活动视图中的文档。 由于204响应被禁止包含任何消息体,因此它始终以消息头后的第一个空行结尾。
-
状态码205:服务器成功处理了请求,且没有返回任何内容。但是与204响应不同,返回此状态码的响应要求请求者重置文档视图。该响应主要是被用于接受用户输入后,立即重置表单,以便用户能够轻松地开始另一次输入。 与204响应一样,该响应也被禁止包含任何消息体,且以消息头后的第一个空行结束。
总结:
这个拦截器的作用其实很简单,就是将 Request 对象中的请求头和请求的 Body 写出给后台,再将后台返回的响应头和响应的 Body 写入到 Response 对象中,这个写出写入过程都由一个 Http 编解码器来完成。通过这个拦截器,我们还知道了 OkHttp 是支持 WebSocket 的,只不过 WebSocket 需要借助一次 Http 请求来完成 TCP 握手,这个过程称之为协议升级。