本文中原始碼基於OkHttp 3.6.0
- 《OkHttp Request 請求執行流程》
- 《OkHttp - Interceptors(一)》
- 《OkHttp - Interceptors(二)》
- 《OkHttp - Interceptors(三)》
- 《OkHttp - Interceptors(四)》
這篇文章分析 OkHttp 請求流程中的最後一個 Interceptor 節點 - CallServerInterceptor,它的任務就是向伺服器發起最終的請求,完成寫入請求,讀取響應的工作。 ####- CallServerInterceptor 來看請求執行的入口 intercept 函式。
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”,其表示客戶端希望伺服器告知自己是否允許攜帶 Body,
// 如果伺服器返回狀態碼為100,則表示允許攜帶請求體,那麼 readResponseHeaders 返回 null。
if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
// 重新整理緩衝區,執行請求
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();
}
}
// 重新整理緩衝區,執行請求
httpCodec.finishRequest();
// 讀取響應 Header,
if (responseBuilder == null) {
responseBuilder = httpCodec.readResponseHeaders(false);
}
// 建立響應
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 {
// 寫入響應 Body
response = response.newBuilder()
.body(httpCodec.openResponseBody(response))
.build();
}
// 如果 Header 中設定了 “Connection:close”,關閉連線
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
執行請求過程主要分為4步,利用在上一個節點中建立的HttpCodec
實現與伺服器的互動:
- 寫入 Request Header;
- 寫入 Request Body;
- 讀取 Response Header;
- 讀取 Response Body。
至此, Request 請求過程中上游部分就結束了,一個原始的 Response 就被建立出來了,這個 Response 將按請求鏈上的反向路徑一步步返回到上一個 Interceptor 節點,供其繼續處理從伺服器返回的 Response,直到最後返回給使用者,完成一次網路請求。