OkHttp - Interceptors(四)

本文中源碼基于OkHttp 3.6.0

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

- CallServerInterceptor

來(lái)看請(qǐng)求執(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();
  // 寫入請(qǐng)求 Header
  httpCodec.writeRequestHeaders(request);

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

    // 寫入請(qǐng)求 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í)行請(qǐng)求
  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í)行請(qǐng)求過(guò)程主要分為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 請(qǐng)求過(guò)程中上游部分就結(jié)束了,一個(gè)原始的 Response 就被創(chuàng)建出來(lái)了,這個(gè) Response 將按請(qǐng)求鏈上的反向路徑一步步返回到上一個(gè) Interceptor 節(jié)點(diǎn),供其繼續(xù)處理從服務(wù)器返回的 Response,直到最后返回給用戶,完成一次網(wǎng)絡(luò)請(qǐng)求。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容