OKHttp攔截器之CallServerInterceptor請求攔截器

終于到了OKHttp最終發起請求的地方,在上個攔截器中找到了一個連接,客戶端與服務端已經建立起了連接,連接之后我們自然是要從服務器獲取到我們想要的數據了,這時候就是客戶端與服務端進行數據交換操作了;首先呢,在這個攔截器中拿到上一個連接攔截器中獲取到的 HttpCodecRealConnection,然后將客戶端的請求頭信息寫入到服務端:

// 寫入請求頭信息
httpCodec.writeRequestHeaders(request);
realChain.eventListener().requestHeadersEnd(realChain.call(), request);

緊接著會判斷一下是否有請求體,有的話同樣也會將請求體也寫入服務器:

if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
    if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
        httpCodec.flushRequest();
        realChain.eventListener().responseHeadersStart(realChain.call());
        // 讀取服務器頭部信息
        responseBuilder = httpCodec.readResponseHeaders(true);
    }
}

這個地方有一個特殊的判斷,“100-continue” 協議的判斷,這個是什么東西呢?這個是客戶端來詢問服務端是否接受較大的數據上傳,比如說大圖,文件之類的,那么為什么要這么做呢?舉個很簡單的例子,如果客戶端想上傳一張很大的圖片,這時候如果他先問服務端支不支持,那如果不支持的話,那么客戶端就不會傳了,也沒有這個動作,但是如果沒有事先知道服務端不支持,那么客戶端就直接傳過來了,但是服務端不會處理,因為不支持,處理不了,這個時候就浪費了上傳的資源,所以這一步就避免了浪費資源。然后就是寫入請求體的操作了:

if (responseBuilder == null) {
    // Write the request body if the "Expect: 100-continue" expectation was met.
    // 寫入請求體
    realChain.eventListener().requestBodyStart(realChain.call());
    long contentLength = request.body().contentLength();
    CountingSink requestBodyOut =
            new CountingSink(httpCodec.createRequestBody(request, contentLength));
    BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
    request.body().writeTo(bufferedRequestBody);
    bufferedRequestBody.close();
    realChain.eventListener().requestBodyEnd(realChain.call(), requestBodyOut.successfulCount);
}

然后一次請求就結束了,后面就是讀取響應頭的信息以及服務器返回的數據:

// 結束請求
httpCodec.finishRequest();
if (responseBuilder == null) {
    // 讀取響應頭
    realChain.eventListener().responseHeadersStart(realChain.call());
    responseBuilder = httpCodec.readResponseHeaders(false);
}
// 構建Response對象
Response response = responseBuilder
        .request(request)
        .handshake(streamAllocation.connection().handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build();

這里所有的數據交換操作都在 HttpCodec 中的 SourceSink 中進行,然后就會構造一個 Response 進行返回,具體是怎么讀取數據流的這個在Okio框架里面實現,這里不進行展開,后面會專門講。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容