本文中源码基于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,直到最后返回给用户,完成一次网络请求。
网友评论