RetryAndFollowUpInterceptor
RetryAndFollowUpInterceptor
有两个功能,一个是重试,一个是重定向。如果
Call
被取消,
RetryAndFollowUpInterceptor
将抛出异常。
我们来一起分析一下。
public final class RetryAndFollowUpInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Call call = realChain.call();
EventListener eventListener = realChain.eventListener();
StreamAllocation streamAllocation = new StreamAllocation(client.connectionPool(),
createAddress(request.url()), call, eventListener, callStackTrace);
this.streamAllocation = streamAllocation;
......
}
}
上面代码主要是创建
StreamAllocation
对象。后面还会再做分析,它用于协调
Connection
,
Stream
,
Call
。
public final class RetryAndFollowUpInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
......
int followUpCount = 0;
Response priorResponse = null;
while (true) {
if (canceled) {
streamAllocation.release();
throw new IOException("Canceled");
}
·····
}
}
}
判断是否取消了请求,如果是的就就直接抛出异常。
public final class RetryAndFollowUpInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
......
int followUpCount = 0;
Response priorResponse = null;
while (true) {
......
Response response;
boolean releaseConnection = true;
try {
response = realChain.proceed(request, streamAllocation, null, null);
releaseConnection = false;
} catch (RouteException e) {
// The attempt to connect via a route failed. The request will not have been sent.
if (!recover(e.getLastConnectException(), streamAllocation, false, request)) {
throw e.getFirstConnectException();
}
releaseConnection = false;
continue;
} catch (IOException e) {
// An attempt to communicate with a server failed. The request may have been sent.
boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
if (!recover(e, streamAllocation, requestSendStarted, request)) throw e;
releaseConnection = false;
continue;
} finally {
// We're throwing an unchecked exception. Release any resources.
if (releaseConnection) {
streamAllocation.streamFailed(null);
streamAllocation.release();
}
}
······
}
}
}
循环处理请求。
- 尝试着从责任链中获取响应
,Response
- 如果出现异常
,RouteException
尝试着去恢复,并继续。IOException
public final class RetryAndFollowUpInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
......
int followUpCount = 0;
Response priorResponse = null;
while (true) {
......
if (priorResponse != null) {
response = response.newBuilder()
.priorResponse(priorResponse.newBuilder()
.body(null)
.build())
.build();
}
......
}
}
}
如果上次的请求的
Response
不为
null
,添加到当前的
Response
中。
public final class RetryAndFollowUpInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
......
int followUpCount = 0;
Response priorResponse = null;
while (true) {
......
Request followUp;
try {
followUp = followUpRequest(response, streamAllocation.route());
} catch (IOException e) {
streamAllocation.release();
throw e;
}
if (followUp == null) {
streamAllocation.release();
return response;
}
......
}
}
}
调用
followUpRequest
获取下次请求
Request
,
followUpRequest
中包括重定向,认证错误等处理。如果
followUp
为
null
说明不能进行下次重试或者重定向了,直接返回。
public final class RetryAndFollowUpInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
......
int followUpCount = 0;
Response priorResponse = null;
while (true) {
......
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;
}
}
}
先是关闭
response
的
body
。
接着就是判断
followUpCount
是否超过了最大的
MAX_FOLLOW_UPS
,超过了直接抛出异常。
接着判断
followUp
的
body
是否是
UnrepeatableRequestBody
的实例,如果是,直接抛出异常。
接着通过
sameConnection
方法判断相应的
response
和
followUp
是否是同一个连接,如果是重定向二者不会相同,需要重新创建
StreamAllocation
最后是赋值到相应的变量。继续循环。