OkHttp - Interceptors(四)

本文中源碼基于OkHttp 3.6.0

這篇文章分析 OkHttp 請求流程中的最后一個(gè) Interceptor 節(jié)點(diǎn) - CallServerInterceptor,它的任務(wù)就是向服務(wù)器發(fā)起最終的請求私蕾,完成寫入請求,讀取響應(yīng)的工作。

- CallServerInterceptor

來看請求執(zhí)行的入口 intercept 函數(shù)。

public Response intercept(Chain chain) throws IOException {
  HttpCodec httpCodec = ((RealInterceptorChain) chain).httpStream();
  StreamAllocation streamAllocation = ((RealInterceptorChain) chain).streamAllocation();
  Request request = chain.request();

  long sentRequestMillis = System.currentTimeMillis();
  // 寫入請求 Header
  httpCodec.writeRequestHeaders(request);

  Response.Builder responseBuilder = null;
  // 如果請求允許攜帶 Body瞻凤,寫入 Body
  if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
    // 如果請求 Header 中包含了 "Expect: 100-continue”,其表示客戶端希望服務(wù)器告知自己是否允許攜帶 Body,
    // 如果服務(wù)器返回狀態(tài)碼為100蔓肯,則表示允許攜帶請求體,那么 readResponseHeaders 返回 null振乏。
    if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
    // 刷新緩沖區(qū)蔗包,執(zhí)行請求
      httpCodec.flushRequest();
      responseBuilder = httpCodec.readResponseHeaders(true);
    }

    // 寫入請求 Body
    if (responseBuilder == null) {
      Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
      BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
      request.body().writeTo(bufferedRequestBody);
      bufferedRequestBody.close();
    }
  }

  // 刷新緩沖區(qū),執(zhí)行請求
  httpCodec.finishRequest();

  // 讀取響應(yīng) Header慧邮,
  if (responseBuilder == null) {
    responseBuilder = httpCodec.readResponseHeaders(false);
  }

  // 創(chuàng)建響應(yīng)
  Response response = responseBuilder
      .request(request)
      .handshake(streamAllocation.connection().handshake())
      .sentRequestAtMillis(sentRequestMillis)
      .receivedResponseAtMillis(System.currentTimeMillis())
      .build();

  int code = response.code();
  if (forWebSocket && code == 101) {
    // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
    response = response.newBuilder()
        .body(Util.EMPTY_RESPONSE)
        .build();
  } else {
    // 寫入響應(yīng) Body
    response = response.newBuilder()
        .body(httpCodec.openResponseBody(response))
        .build();
  }

  // 如果 Header 中設(shè)置了 “Connection:close”调限,關(guān)閉連接
  if ("close".equalsIgnoreCase(response.request().header("Connection"))
      || "close".equalsIgnoreCase(response.header("Connection"))) {
    streamAllocation.noNewStreams();
  }

  if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
    throw new ProtocolException(
        "HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
  }

  return response;
}

CallServerInterceptor執(zhí)行請求過程主要分為4步,利用在上一個(gè)節(jié)點(diǎn)中創(chuàng)建的HttpCodec實(shí)現(xiàn)與服務(wù)器的交互:

  1. 寫入 Request Header误澳;
  2. 寫入 Request Body耻矮;
  3. 讀取 Response Header;
  4. 讀取 Response Body忆谓。

至此裆装, Request 請求過程中上游部分就結(jié)束了,一個(gè)原始的 Response 就被創(chuàng)建出來了倡缠,這個(gè) Response 將按請求鏈上的反向路徑一步步返回到上一個(gè) Interceptor 節(jié)點(diǎn)哨免,供其繼續(xù)處理從服務(wù)器返回的 Response,直到最后返回給用戶昙沦,完成一次網(wǎng)絡(luò)請求琢唾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市盾饮,隨后出現(xiàn)的幾起案子采桃,更是在濱河造成了極大的恐慌懒熙,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件普办,死亡現(xiàn)場離奇詭異煌珊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)泌豆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門定庵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人踪危,你說我怎么就攤上這事蔬浙。” “怎么了贞远?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵畴博,是天一觀的道長。 經(jīng)常有香客問我蓝仲,道長俱病,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任袱结,我火速辦了婚禮亮隙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘垢夹。我一直安慰自己溢吻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布果元。 她就那樣靜靜地躺著促王,像睡著了一般。 火紅的嫁衣襯著肌膚如雪而晒。 梳的紋絲不亂的頭發(fā)上蝇狼,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音倡怎,去河邊找鬼迅耘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛诈胜,可吹牛的內(nèi)容都是我干的豹障。 我是一名探鬼主播冯事,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼焦匈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了昵仅?” 一聲冷哼從身側(cè)響起缓熟,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤累魔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后够滑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體垦写,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年彰触,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了梯投。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡况毅,死狀恐怖分蓖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情尔许,我是刑警寧澤么鹤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站味廊,受9級特大地震影響蒸甜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜余佛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一柠新、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧辉巡,春花似錦登颓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至痢甘,卻和暖如春喇嘱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背塞栅。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工者铜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人放椰。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓作烟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親砾医。 傳聞我的和親對象是個(gè)殘疾皇子拿撩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 這篇文章主要講 Android 網(wǎng)絡(luò)請求時(shí)所使用到的各個(gè)請求庫的關(guān)系,以及 OkHttp3 的介紹如蚜。(如理解有誤压恒,...
    小莊bb閱讀 1,159評論 0 4
  • OkHttp解析系列 OkHttp解析(一)從用法看清原理OkHttp解析(二)網(wǎng)絡(luò)連接OkHttp解析(三)關(guān)于...
    Hohohong閱讀 20,974評論 4 58
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理影暴,服務(wù)發(fā)現(xiàn),斷路器探赫,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 簡介 目前在HTTP協(xié)議請求庫中型宙,OKHttp應(yīng)當(dāng)是非常火的伦吠,使用也非常的簡單妆兑。網(wǎng)上有很多文章寫了關(guān)于OkHttp...
    第八區(qū)閱讀 1,380評論 1 5
  • 昨天停水,晚上的菜才做了一半毛仪。突然之間停水箭跳,毫無思想準(zhǔn)備,頓時(shí)心里多出許多埋怨潭千,還好谱姓,家里有預(yù)備的礦泉水,對付著把...
    卿若安閱讀 179評論 0 1