OKHttp攔截器之CallServerInterceptor請(qǐng)求攔截器

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

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

緊接著會(huì)判斷一下是否有請(qǐng)求體,有的話同樣也會(huì)將請(qǐng)求體也寫入服務(wù)器:

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

這個(gè)地方有一個(gè)特殊的判斷,“100-continue” 協(xié)議的判斷,這個(gè)是什么東西呢?這個(gè)是客戶端來(lái)詢問(wèn)服務(wù)端是否接受較大的數(shù)據(jù)上傳,比如說(shuō)大圖,文件之類的,那么為什么要這么做呢?舉個(gè)很簡(jiǎn)單的例子,如果客戶端想上傳一張很大的圖片,這時(shí)候如果他先問(wèn)服務(wù)端支不支持,那如果不支持的話,那么客戶端就不會(huì)傳了,也沒(méi)有這個(gè)動(dòng)作,但是如果沒(méi)有事先知道服務(wù)端不支持,那么客戶端就直接傳過(guò)來(lái)了,但是服務(wù)端不會(huì)處理,因?yàn)椴恢С郑幚聿涣?,這個(gè)時(shí)候就浪費(fèi)了上傳的資源,所以這一步就避免了浪費(fèi)資源。然后就是寫入請(qǐng)求體的操作了:

if (responseBuilder == null) {
    // Write the request body if the "Expect: 100-continue" expectation was met.
    // 寫入請(qǐng)求體
    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);
}

然后一次請(qǐng)求就結(jié)束了,后面就是讀取響應(yīng)頭的信息以及服務(wù)器返回的數(shù)據(jù):

// 結(jié)束請(qǐng)求
httpCodec.finishRequest();
if (responseBuilder == null) {
    // 讀取響應(yīng)頭
    realChain.eventListener().responseHeadersStart(realChain.call());
    responseBuilder = httpCodec.readResponseHeaders(false);
}
// 構(gòu)建Response對(duì)象
Response response = responseBuilder
        .request(request)
        .handshake(streamAllocation.connection().handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build();

這里所有的數(shù)據(jù)交換操作都在 HttpCodec 中的 SourceSink 中進(jìn)行,然后就會(huì)構(gòu)造一個(gè) Response 進(jìn)行返回,具體是怎么讀取數(shù)據(jù)流的這個(gè)在Okio框架里面實(shí)現(xiàn),這里不進(jìn)行展開(kāi),后面會(huì)專門講。

?著作權(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)容

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