終于到了OKHttp最終發起請求的地方,在上個攔截器中找到了一個連接,客戶端與服務端已經建立起了連接,連接之后我們自然是要從服務器獲取到我們想要的數據了,這時候就是客戶端與服務端進行數據交換操作了;首先呢,在這個攔截器中拿到上一個連接攔截器中獲取到的 HttpCodec 和 RealConnection,然后將客戶端的請求頭信息寫入到服務端:
// 寫入請求頭信息
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 中的 Source 和 Sink 中進行,然后就會構造一個 Response 進行返回,具體是怎么讀取數據流的這個在Okio框架里面實現,這里不進行展開,后面會專門講。