本文中源碼基于OkHttp 3.6.0
- 《OkHttp Request 請求執(zhí)行流程》
- 《OkHttp - Interceptors(一)》
- 《OkHttp - Interceptors(二)》
- 《OkHttp - Interceptors(三)》
- 《OkHttp - Interceptors(四)》
這篇文章分析 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ù)器的交互:
- 寫入 Request Header误澳;
- 寫入 Request Body耻矮;
- 讀取 Response Header;
- 讀取 Response Body忆谓。
至此裆装, Request 請求過程中上游部分就結(jié)束了,一個(gè)原始的 Response 就被創(chuàng)建出來了倡缠,這個(gè) Response 將按請求鏈上的反向路徑一步步返回到上一個(gè) Interceptor 節(jié)點(diǎn)哨免,供其繼續(xù)處理從服務(wù)器返回的 Response,直到最后返回給用戶昙沦,完成一次網(wǎng)絡(luò)請求琢唾。