1、okhttp源码解析-整体流程
2、okhttp源码解析-拦截器RetryAndFllowUpInterceptor
3、okhttp源码解析-拦截器BridgeInterceptor
4、okhttp源码解析-拦截器CacheInterceptor
5、okhttp源码解析-拦截器ConnectInterceptor
6、okhttp源码解析-拦截器CallServerInterceptor
7、okhttp源码解析-Dispatcher任务管理器
CallServerInterceptor
1、这个拦截器是最后一个官方拦截器。
2、这个拦截器是处理输出流sink,接收流source的。
一、源码分析
上一节ConnectInterceptor,我们说到streamAllocation.newStream()在3.9v的时候。
创建只创建了HttpCodec*,而在这个拦截器会通过HttpConnect.newStream()来创建HttpStream。
- 1、httpCodec分为1和2,分别对应http1.*、http2.0的协议版本。http2.0不再是文本传输,而是二进制流传输数据。
- 2、sink、source都属于okio的io流框架内容了。以后有时间我们来撸一撸okio的内容。
@Override public Response intercept(Chain chain) throws IOException {
// 1.获取几个前面拦截方法创建的,重要类
HttpCodec httpCodec = ((RealInterceptorChain) chain).httpStream();
StreamAllocation streamAllocation = ((RealInterceptorChain) chain).streamAllocation();
Request request = chain.request();
long sentRequestMillis = System.currentTimeMillis();
//2. 先向sink(OutputStream)中写头信息
httpCodec.writeRequestHeaders(request);
Response.Builder responseBuilder = null;
// 3.判断是否有请求实体的请求,用method判断
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
// If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100
// Continue" response before transmitting the request body. If we don't get that, return what
// we did get (such as a 4xx response) without ever transmitting the request body.
//4. 如果头部添加了"100-continue", 相对于一次见到的握手操作,只有拿到服务的结果再继续
if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
httpCodec.flushRequest();
responseBuilder = httpCodec.readResponseHeaders(true);
}
//5. 当前面的"100-continue",需要握手,但又握手失败,这个时候responseBuilder不是空的
// Write the request body, unless an "Expect: 100-continue" expectation failed.
if (responseBuilder == null) {
Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
// 回调RequestBody的writeTo,写相应的数据
request.body().writeTo(bufferedRequestBody);
bufferedRequestBody.close();
}
}
//6. 这里也是调用了一次 sink.flush()
httpCodec.finishRequest();
//7. 读取头部信息,状态码,信息等
if (responseBuilder == null) {
responseBuilder = httpCodec.readResponseHeaders(false);
}
//8. 构建Response, 写入原请求,握手情况,请求时间,得到的结果时间
Response response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
int code = response.code();
//9. 通过状态码判断以及是否webSocket判断,是否返回一个空的body
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();
}
//10 .如果设置了连接 close ,断开连接
if ("close".equalsIgnoreCase(response.request().header("Connection"))
|| "close".equalsIgnoreCase(response.header("Connection"))) {
streamAllocation.noNewStreams();
}
//11. HTTP 204(no content) 代表响应报文中包含若干首部和一个状态行,但是没有实体的主体内容。
//HTTP 205(reset content) 表示响应执行成功,重置页面(Form表单),方便用户下次输入
//这里做了同样的处理,就是抛出协议异常。
if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
throw new ProtocolException(
"HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
}
return response;
}
网友评论