RetryAndFollowUpInterceptor拦截器
前面已经分析,okHttp的线程池里的请求任务的execute方法会构造拦截器链,然后通过index++依次调用chain.proceed方法来调用各种拦截器,不考虑用户自定义的拦截器的话,第一个被调用的拦截器就是RetryAndFollowUpInterceptor,请求重试拦截器,我们主要看被调用的方法intercept
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Call call = realChain.call();
EventListener eventListener = realChain.eventListener();
//StreamAllocation用于协调 连接Connections、数据流Streams 和 网络请求Calls这三个实体
StreamAllocation streamAllocation = new StreamAllocation(client.connectionPool(),
createAddress(request.url()), call, eventListener, callStackTrace);
this.streamAllocation = streamAllocation;
//重定向次数
int followUpCount = 0;
Response priorResponse = null;
while (true) {
if (canceled) {
streamAllocation.release();
throw new IOException("Canceled");
}
Response response;
boolean releaseConnection = true;
try {
//调用下层的拦截器做网络请求
response = realChain.proceed(request, streamAllocation, null, null);
releaseConnection = false;
} catch (RouteException e) {
//捕获RouteException,并判断本次请求的异常是否能通过重新请求来恢复(比方ProtocolException协议出错,则返回false不能重连)
if (!recover(e.getLastConnectException(), streamAllocation, false, request)) {
//不能则抛异常
throw e.getFirstConnectException();
}
releaseConnection = false;
//可以则continue,while循环体内重新请求一遍
continue;
} catch (IOException e) {
//逻辑和上面的一样,捕获更大范围的异常
boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
if (!recover(e, streamAllocation, requestSendStarted, request)) throw e;
releaseConnection = false;
continue;
} finally {
//释放当前的连接资源
if (releaseConnection) {
streamAllocation.streamFailed(null);
streamAllocation.release();
}
}
// Attach the prior response if it exists. Such responses never have a body.
if (priorResponse != null) {
response = response.newBuilder()
.priorResponse(priorResponse.newBuilder()
.body(null)
.build())
.build();
}
Request followUp;
try {
//如果上面返回了response,那么判断httpCode,具体的code做具体处理(比方407,代理认证失败,则调用代理管理类进行认证)
followUp = followUpRequest(response, streamAllocation.route());
} catch (IOException e) {
streamAllocation.release();
throw e;
}
//没有进一步的处理方法,(包括请求成功的)则返回null,此时直接返回response给上层处理
if (followUp == null) {
streamAllocation.release();
return response;
}
closeQuietly(response.body());
//重定向次数如果大于最大允许的重定向次数,则抛异常
if (++followUpCount > MAX_FOLLOW_UPS) {
streamAllocation.release();
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
if (followUp.body() instanceof UnrepeatableRequestBody) {
streamAllocation.release();
throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
}
if (!sameConnection(response, followUp.url())) {
streamAllocation.release();
streamAllocation = new StreamAllocation(client.connectionPool(),
createAddress(followUp.url()), call, eventListener, callStackTrace);
this.streamAllocation = streamAllocation;
} else if (streamAllocation.codec() != null) {
throw new IllegalStateException("Closing the body of " + response
+ " didn't close its backing stream. Bad interceptor?");
}
request = followUp;
priorResponse = response;
}
}