在《 Okhttp源码简单解析(一) 》这篇博客简单分析了Okhttp请求的执行流程,通过该篇博客我们知道OkHttp的核心网络请求中内置“拦截器”发挥了重大作用;本篇就对OkHttp内置拦截器链上第二个拦截器BridgeInterceptor的 作用进行简单的分析(第一个拦截器为RetryAndFollowUpInterceptor,因为本系列博客逻辑顺序关系,这个拦截器放后面讲解)。

Bridge,桥,什么桥?当然是链接客户端代码和网络代码的桥梁。正如官方对此类的注释所说: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.

该拦截器是链接客户端代码和网络代码的桥梁,它首先将客户端构建的Request对象信息构建成真正的网络请求;然后发起网络请求,最后就是讲服务器返回的消息封装成一个Response对象。

所以BridgeInterceptor的作用大体体现如下(既然是拦截器当然是核心逻辑是intercept方法中):

 public Response intercept(Chain chain) throws IOException {
    //1.对Request进行处理
    Request newRequest = builderNetWorkRequestFromUserRequest();

    //2 调用后续的内置拦截器,返回服务器请求
    Response networkResponse = chain.proceed(requestBuilder.build());

    //对Response进行处理,并返回Response对象
    handleResponse();

    return networkResponse ;
 } 

在进一步分析BridgeInterceptor之前,在说一点“课外”的知识,简单看一下一个正真的http请求都包含了什么:为此,我在浏览器地址栏里请求了我一片博客的地址,用FireBug查看其网络请求得到如图信息:

可以发现除了请求URL之外,浏览器还给你拼接了请求头信息,所以既然上面所说BridgeInterceptor的第一步是将用户请求创建真正的Network Request,那么这些头信息也是少不了的,看看该拦截器是怎么捯饬的:

    //获取用户构建的Request对象
    Request userRequest = chain.request();

    Request.Builder requestBuilder = userRequest.newBuilder();

    RequestBody body = userRequest.body();
    //设置Content-Type
    if (body != null) {
      MediaType contentType = body.contentType();
      if (contentType != null) {
        requestBuilder.header("Content-Type", contentType.toString());
      }

      //Content-Length和Transfer-Encoding互斥
      long contentLength = body.contentLength();
      if (contentLength != -1) {
        requestBuilder.header("Content-Length", Long.toString(contentLength));
        requestBuilder.removeHeader("Transfer-Encoding");
      } else {
        requestBuilder.header("Transfer-Encoding", "chunked");
        requestBuilder.removeHeader("Content-Length");
      }
    }

    //设置Host
    if (userRequest.header("Host") == null) {
      requestBuilder.header("Host", hostHeader(userRequest.url(), false));
    }

    //设置Connection头
    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.
    boolean transparentGzip = false;
    if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
      transparentGzip = true;
      requestBuilder.header("Accept-Encoding", "gzip");
    }

    List<Cookie> cookies = cookieJar.loadForRequest(userRequest.url());
    if (!cookies.isEmpty()) {
      requestBuilder.header("Cookie", cookieHeader(cookies));
    }

    if (userRequest.header("User-Agent") == null) {
      requestBuilder.header("User-Agent", Version.userAgent());
    }

上面的代码逻辑也很简单,就是为Request设置User-Agent、Cookie、Accept-Encoding等相关请求头信息。到此为止一个完整的NetWork Request 就构建完毕,是时候发起真正的网络请求了。当然根据《Okhtt源码简单解析(一)》这篇所述,真正发起网络网络请求的就是连接器链上剩下拦截器的功能了:

//拦截器链继续往下运行
Response networkResponse = chain.proceed(requestBuilder.build());

当然就不是本篇要介绍的重点。根据拦截器的作用原理,此时剩下拦截器工作就是返回真正的网络响应了(当然此响应可能是缓存的,也可能是服务器返回的最新数据)。

//响应header, 如果没有自定义配置cookieJar==null,则什么都不做
 HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());

    Response.Builder responseBuilder = networkResponse.newBuilder()
        .request(userRequest);
    //判断服务器是否支持gzip压缩格式,如果支持则交给kio压缩
    if (transparentGzip&& "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
        && HttpHeaders.hasBody(networkResponse)) {
      GzipSource responseBody = new GzipSource(networkResponse.body().source());
      Headers strippedHeaders = networkResponse.headers().newBuilder()
          .removeAll("Content-Encoding")
          .removeAll("Content-Length")
          .build();
      responseBuilder.headers(strippedHeaders);
      responseBuilder.body(new RealResponseBody(strippedHeaders, Okio.buffer(responseBody)));
    }

    return responseBuilder.build();

到此为止本篇博客就完毕了,至于网络其他相关知识,会另开一片博客说明。本篇只是假的的对该拦截器的功能最粗略基本的说明,对 CookieJar或者gzip压缩功能的说明以及网络知识的相关说明另开篇写之,如有不当之处欢迎批评指正

OkHttp之BridgeInterceptor简单分析的更多相关文章

  1. Okhttp之CacheInterceptor简单分析

    <OkHttp之BridgeInterceptor简单分析 >简单分析了BridgeInterceptor的工作原理,在Okhttp的拦截器链上BridgeInterceptor的下一个拦 ...

  2. Okhttp之CallServerInterceptor简单分析

    在Okhttp源码分析专栏的几篇博客分析了Okhttp几个拦截器的主要功能,还剩下最后一个拦截器CallServerInterceptor没有分析,本篇博客就简单分析下该拦截器的功能. 在Okhttp ...

  3. OkHttp之ConnectInterceptor简单分析

    在< Okhttp之CacheInterceptor简单分析 >这篇博客中简单的分析了下缓存拦截器的工作原理,通过此博客我们知道在执行完CacheInterceptor之后会执行下一个浏览 ...

  4. Okhttp之连接池ConnectionPool简单分析(一)

    开篇声明:由于本篇博文用到的一些观点或者结论在之前的博文中都已经分析过,所以本篇博文直接拿来用,建议读此博文的Monkey们按照下面的顺序读一下博主以下博文,以便于对此篇博文的理解: <Okht ...

  5. Okhttp对http2的支持简单分析

    在< Okhttp之RealConnection建立链接简单分析>一文中简单的分析了RealConnection的connect方法的作用:打开一个TCP链接或者打开一个隧道链接,在打开t ...

  6. Okhttp之RealConnection建立链接简单分析

    在之前的博客中我们知道Okhttp在发起链接请求先从链接池中获取连接,如果链接池中没有链接则创建新的链接RealConnection对象,然后执行其connet方法打开SOCKET链接(详见< ...

  7. Okhttp之RouteSelector简单解析

    继前面的几篇OKhttp的拦截器简单分析之后,对于后续Okhttp之间的分析自己也着实琢磨了一段时间,是分析RealConnection?还是ConnectionPool,随着对Okhttp源码的深入 ...

  8. 简单分析JavaScript中的面向对象

    初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...

  9. CSipSimple 简单分析

    简介 CSipSimple是一款可以在android手机上使用的支持sip的网络电话软件,可以在上面设置使用callda网络电话.连接使用方式最好是使用wifi,或者3g这样上网速度快,打起电话来效果 ...

随机推荐

  1. Jquery7 表单选择器

    学习要点: 1.常规选择器 2.表单选择器 3.表单过滤器 表单作为 HTML 中一种特殊的元素,操作方法较为多样性和特殊性,开发者不但可以使用之前的常规选择器或过滤器,也可以使用 jQuery 为表 ...

  2. 再谈CSS动画 - 说点不知道的(一)贝塞尔曲线

    今天重新翻看<CSS 揭秘>"过渡与动画"一章,并把该章代码重新敲了一遍,代码托管在我的Github,在此总结一些心得. 动画的奥秘 在网页中添加动画的目的是让用户有更 ...

  3. Linux后台运行命令,nohup和&的区别

    &的意思是在后台运行, 什么意思呢?  意思是说, 当你在执行 ./a.out & 的时候, 即使你用ctrl C,  那么a.out照样运行(因为对SIGINT信号免疫). 但是要注 ...

  4. 爬虫之Requests: 让 HTTP 服务人类

    Requests: 让 HTTP 服务人类 虽然Python的标准库中 urllib2 模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 “ ...

  5. HTML请求与相应

    HTTP的请求与响应 HTTP通信由两部分组成: 客户端请求消息 与 服务器响应消息 浏览器发送HTTP请求的过程: 当用户在浏览器的地址栏中输入一个URL并按回车键之后,浏览器会向HTTP服务器发送 ...

  6. Protocol Buffers数据传输及存储协议简单使用

    我们知道Protocol Buffers是Google定义的一种跨语言.跨平台.可扩展的数据传输及存储的协议,因为将字段协议分别放在传输两端,传输数据中只包含数据本身,不需要包含字段说明,所以传输数据 ...

  7. HTML中table的td宽度无法固定问题

    设置了 width="10%" 依然会被内容撑大, 加了 style="word-break:break-all;" 属性就好了.效果是内容自动回车. 此属性不 ...

  8. 直播P2P技术2-低延迟模型

    低延迟模型 由上一篇文章我们知道:网状拓扑虽最大化利用了所有节点的资源却无法降低数据延迟,而树状拓扑尽管数据传输效率高,延迟低,但只利用了少部分节点的带宽资源,不适应高码率的直播P2P网络. 那么如何 ...

  9. Vue——解决[Vue warn]: Invalid prop: custom validator check failed for prop "index". found in错误

    Invalid prop: custom validator check failed for prop "index". 错误重现: 使用element-ui的菜单,在SubMe ...

  10. Vue 及框架响应式系统原理

    个人bolg地址 全局概览 Vue运行内部运行机制 总览图: 初始化及挂载 在 new Vue()之后. Vue 会调用 _init 函数进行初始化,也就是这里的 init 过程,它会初始化生命周期. ...