整体流程
下面这张图很好的说明了OkHttp
的网络请求流程,来自于拆轮子系列:拆 OkHttp
OkHttp最简单的使用如下所示:
OkHttpClient client = new OkHttpClient.Builder().build();
Request request = new Request.Builder().url("....").build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
1. OkHttpClient.Builder
public static final class Builder {
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;//HTTP_2, Http_1_1
connectionSpecs = DEFAULT_CONNECTION_SPECS; //MODERN_TLS, CLEARTEXT
eventListenerFactory = EventListener.factory(EventListener.NONE);
proxySelector = ProxySelector.getDefault();
cookieJar = CookieJar.NO_COOKIES;
socketFactory = SocketFactory.getDefault();
hostnameVerifier = OkHostnameVerifier.INSTANCE;
certificatePinner = CertificatePinner.DEFAULT;
proxyAuthenticator = Authenticator.NONE;
authenticator = Authenticator.NONE;
connectionPool = new ConnectionPool();
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
}
- 默认
Cache
是为空 - 默认
CookieJar = CookieJar.NO_COOKIES
, 即不做cookie管理 - 创建一个
ConnectionPool(maxIdleConnections: 5, keepAliveDurations: 5, TimeUnit.Minutes)
2. Request.Builder
public static class Builder {
HttpUrl url;
String method;
Headers.Builder headers;
RequestBody body;
Object tag;
//默认请求方法是GET, 默认Headers是空的,后面会再添加
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
//根据传入的url生成一个HttpUrl对象
public Builder url(String url) {
if (url == null)
throw new NullPointerException("url == null");
//自动将web socket url替换为http的url
if (url.regionMatches(true, 0, "ws:", 0, 3)) {
url = "http:" + url.substring(3);
} else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
url = "https:" + url.substring(4);
}
HttpUrl parsed = HttpUrl.parse(url);
if (parsed == null)
throw new IllegalArgumentException("unexpected url: " + url);
return url(parsed);
}
....
}
- 默认Request的body是null
- headers也为空
3. OkHttpClient.newCall(Request request)
@Override
public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
可以看到,内部实际调用的是RealCall.newCall
来生成Call
3.1 RealCall.newRealCall
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
RealCall call = new RealCall(client, originalRequest, forWebSocket);
//默认client.eventListenerFactory返回OkHttpClient.Builder.eventListenerFactory
//Builder.eventListenerFactory是默认的EventListener.NONE即一个空实现
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
3.2 new RealCall
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
}
在RealCall
内部会创建RetryAndFollowUpInterceptor
4. RealCall.enqueue
@Override
public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed)
throw new IllegalStateException("Already Executed");
executed = true;
}
// 获取response.body().close()方法执行时的异常stack trace,将获取到的
// stack trace信息赋予retryAndFollowUpInterceptor
captureCallStackTrace();
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
RealCall.enqueue
内部手机调用的Dispatcher.enqueue
, 在调用Dispatcher.enqueue之前会创建一个AsyncCall
, AsyncCall实际就是一个Runnable
4.1 new AsyncCall
//NamedRunnable继承自Runnable, 实质是在run()方法调用子类的execute()方法,这里即AsyncCall的execute()方法
final class AsyncCall extends NamedRunnable {
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
...
}
NamedRunnable继承自Runnable, 实质是在run()方法调用子类的execute()方法,这里即AsyncCall的execute()方法
4.2 Dispatcher.enqueue
/*
* 如果一个host的同时请求数量没有达到上限的话,将传入的AsyncCall放入running队列中,并将AsyncCall放入线程池中执行该任务(即调用run()方法,
* 而AsyncCall继承自NamedRunnable, 所以最终会调用execute方法)
* 如果达到上限,则将传入的AsyncCall放入ready队列中
*/
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
如果一个host即服务器的同时请求数量没有达到上限的话,会把新建的任务放入正在运行的队列中,同时在线程池中执行该任务,如果请求数量达到上限,则先将任务放入代运行队列中
4.3 AsyncCall.execute
@Override
protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
signalledCallback = true;
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
responseCallback.onFailure(RealCall.this, e);
}
} finally {
//网络请求结束,将当前AsyncCall从running队列中删除
//检查ready队列中是否有待处理的请求,有则处理
client.dispatcher().finished(this);
}
}
线程池执行以后会调用Runnable.run
方法,同时通过之前4.1可以知道AsyncCall
继承自NamedRunnable
,最终会调用execute
方法
4.4 RealCall.getResponseWithInterceptorChain
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
//如果有自定义的Interceptor, 先添加全部的自定义Interceptor
interceptors.addAll(client.interceptors());
//添加RetryAndFollowUpInterceptor
interceptors.add(retryAndFollowUpInterceptor);
//client默认的cookieJar是一个空实现既不做cookie管理, 添加BridgeInterceptor
interceptors.add(new BridgeInterceptor(client.cookieJar()));
//client默认internalCache = null, 添加CacheInterceptor
interceptors.add(new CacheInterceptor(client.internalCache()));
//添加ConnectInterceptor
interceptors.add(new ConnectInterceptor(client));
//一般情况下forWebSocket = false, 添加client的networkInterceptors
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
//添加CallServerInterceptor
interceptors.add(new CallServerInterceptor(forWebSocket));
//创建RealInterceptorChain,并调用chain.proceed()
//eventListener是一个空实现
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.readTimeoutMillis());
return chain.proceed(originalRequest);
}
依次添加各个Interceptor
添加的顺序是:
- 用户自定义的Interceptor
- 之前创建的
RetryAndFollowUpInterceptor
- 添加一个新建的
BridgeInterceptor
- 添加一个新建的
CacheInterceptor
- 添加一个新建的
ConnectInterceptor
- 如果不是针对WebSocket, 则再添加自定义的network interceptor
- 最后添加新建的
CallServerInterceptor
4.5 RealInterceptorChain.proceed
@Override
public Response proceed(Request request) throws IOException {
//streamAllocation = null, httpCodec = null, connection = null
return proceed(request, streamAllocation, httpCodec, connection);
}
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
if (index >= interceptors.size())
throw new AssertionError();
calls++;
if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
throw new IllegalStateException(...);
}
if (this.httpCodec != null && calls > 1) {
throw new IllegalStateException(...);
}
// 依次调用各Interceptor
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, readTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
// 确保每个Interceptor都只执行一次proceed
if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
throw new IllegalStateException(...);
}
// Confirm that the intercepted response isn't null.
if (response == null) {
throw new NullPointerException(...);
}
if (response.body() == null) {
throw new IllegalStateException(...);
}
return response;
}
该方法最重要的一点是依次调用各个Interceptor
的intercept()
方法, 调用的顺序为:
- 自定义Interceptors
- RetryAndFollowUpInterceptor
- BridgeInterceptor
- CacheInterceptor
- ConnectInterceptor
- 自定义添加的Network Interceptors
- CallServerInterceptor
4.6 RetryAndFollowUpInterceptor.interceptor
Request request = chain.request();
RealInterceptorChain realChain = (RealInterceptorChain) chain;
//RealCall
Call call = realChain.call();
//EventListener的空实现
EventListener eventListener = realChain.eventListener();
//新建一个StreamAllocation, 根据OkHttpClient的SSLSocketFactory, HostnameVerifier, Dns, CertificatePinner
//等属性新建一个Address对象
//callStackTrace是之前调用RealCall.enqueue时设置的关于Response.body().close()方法的异常栈
streamAllocation = new StreamAllocation(client.connectionPool(), createAddress(request.url()),
call, eventListener, callStackTrace);
int followUpCount = 0;
Response priorResponse = null;
while (true) {
if (canceled) {
streamAllocation.release();
throw new IOException("Canceled");
}
Response response = null;
boolean releaseConnection = true;
try {
//调用下一个Interceptor, 即BridgeInterceptor的intercept方法
//NOTE: 要执行完所有Interceptor.intercept以后再去执行之后的代码逻辑
response = realChain.proceed(request, streamAllocation, null, null);
releaseConnection = false;
} catch (RouteException e) {
if (!recover(e.getLastConnectException(), false, request)) {
throw e.getLastConnectException();
}
releaseConnection = false;
continue;
} catch (IOException e) {
boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
if (!recover(e, requestSendStarted, request)) throw e;
releaseConnection = false;
continue;
} finally {
....
}
...
}
}
NOTE: 所有Interceptor是一个完整的调用链,RetryAndFollowUpInterceptor.intercept是起始处,当所有的Interceptor执行完以后,RetryAndFollowUpInterceptor才会再执行finally以后的代码逻辑
4.7 BridgeInterceptor.interceptor
Request userRequest = chain.request();
Request.Builder requestBuilder = userRequest.newBuilder();
RequestBody body = userRequest.body();
if (body != null) {
MediaType contentType = body.contentType();
if (contentType != null) {
requestBuilder.header("Content-Type", contentType.toString());
}
long contentLength = body.contentLength();
if (contentLength != -1) {
requestBuilder.header("Content-Length", Long.toString(contentLength));
requestBuilder.removeHeader("Transfer-Encoding");
} else {
requestBuilder.header("Transfer-Encoding", "chunked");
requestBuilder.removeHeader("Content-Length");
}
}
if (userRequest.header("Host") == null) {
requestBuilder.header("Host", hostHeader(userRequest.url(), false));
}
if (userRequest.header("Connection") == null) {
requestBuilder.header("Connection", "Keep-Alive");
}
// If we add an "Accept-Encoding: gzip" header field we're responsible for also decompressing
// the transfer stream.
boolean transparentGzip = false;
if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
transparentGzip = true;
requestBuilder.header("Accept-Encoding", "gzip");
}
List<Cookie> cookies = cookieJar.loadForRequest(userRequest.url());
if (!cookies.isEmpty()) {
requestBuilder.header("Cookie", cookieHeader(cookies));
}
if (userRequest.header("User-Agent") == null) {
requestBuilder.header("User-Agent", Version.userAgent());
}
//执行CacheInterceptor.intercept
Response networkResponse = chain.proceed(requestBuilder.build());
....
}
BridgeInterceptor.intercept
主要就是根据Request
添加一些必要的http请求的header
4.8 CacheInterceptor.interceptor
@Override
public Response intercept(Chain chain) throws IOException {
//默认情况下, cache = null
Response cacheCandidate = cache != null
? cache.get(chain.request())
: null;
long now = System.currentTimeMillis();
//一帮情况下,由于cacheCandidate = null, 所以直接返回一个new CacheStrategy(request, null)
CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();
Request networkRequest = strategy.networkRequest;
Response cacheResponse = strategy.cacheResponse;
if (cache != null) {
cache.trackResponse(strategy);
}
//如果cacheResponse = null, 则调用cacheCandidate的ResponseBody.close()
if (cacheCandidate != null && cacheResponse == null) {
closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it.
}
//如果既没有Request也没有Cache Response, 生成一个空body, code = 504的Response
if (networkRequest == null && cacheResponse == null) {
return new Response.Builder()
.request(chain.request())
.protocol(Protocol.HTTP_1_1)
.code(504)
.message("Unsatisfiable Request (only-if-cached)")
.body(Util.EMPTY_RESPONSE)
.sentRequestAtMillis(-1L)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
}
// 如果Request = null, 但是有缓存的Response, 返回缓存的Response
if (networkRequest == null) {
return cacheResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse))
.build();
}
//调用ConnectInterceptor.interceptor()
Response networkResponse = null;
try {
networkResponse = chain.proceed(networkRequest);
} finally {
// If we're crashing on I/O or otherwise, don't leak the cache body.
if (networkResponse == null && cacheCandidate != null) {
closeQuietly(cacheCandidate.body());
}
}
...
}
4.9 ConnectInterceptor
@Override
public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Request request = realChain.request();
StreamAllocation streamAllocation = realChain.streamAllocation();
// We need the network to satisfy this request. Possibly for validating a conditional GET.
boolean doExtensiveHealthChecks = !request.method().equals("GET");
//创建RealConnection和HttpCodec
HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
RealConnection connection = streamAllocation.connection();
//调用CallServerInterceptor.interceptor
return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
4.9.1 StreamAllocation.newStream
public HttpCodec newStream(
OkHttpClient client, Interceptor.Chain chain, boolean doExtensiveHealthChecks) {
//10000
int connectTimeout = client.connectTimeoutMillis();
//10000
int readTimeout = chain.readTimeoutMillis();
//10000
int writeTimeout = client.writeTimeoutMillis();
//true
boolean connectionRetryEnabled = client.retryOnConnectionFailure();
try {
RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout,
writeTimeout, connectionRetryEnabled, doExtensiveHealthChecks);
HttpCodec resultCodec = resultConnection.newCodec(client, chain, this);
synchronized (connectionPool) {
codec = resultCodec;
return resultCodec;
}
} catch (IOException e) {
throw new RouteException(e);
}
}
4.9.2 StreamAllocation.findHealthyConnection
private RealConnection findHealthyConnection(int connectTimeout, int readTimeout,
int writeTimeout, boolean connectionRetryEnabled, boolean doExtensiveHealthChecks)
throws IOException {
while (true) {
RealConnection candidate = findConnection(connectTimeout, readTimeout, writeTimeout,
connectionRetryEnabled);
// If this is a brand new connection, we can skip the extensive health checks.
synchronized (connectionPool) {
if (candidate.successCount == 0) {
return candidate;
}
}
// Do a (potentially slow) check to confirm that the pooled connection is still good. If it
// isn't, take it out of the pool and start again.
if (!candidate.isHealthy(doExtensiveHealthChecks)) {
noNewStreams();
continue;
}
return candidate;
}
}
4.9.3 StreamAllocation.findConnection
private RealConnection findConnection(int connectTimeout, int readTimeout, int writeTimeout,
boolean connectionRetryEnabled) throws IOException {
Route selectedRoute;
synchronized (connectionPool) {
if (released)
throw new IllegalStateException("released");
if (codec != null)
throw new IllegalStateException("codec != null");
if (canceled)
throw new IOException("Canceled");
// 如果this.connection已经创建,则直接返回this.connection
// 但第一次创建时,this.connection = null
RealConnection allocatedConnection = this.connection;
if (allocatedConnection != null && !allocatedConnection.noNewStreams) {
return allocatedConnection;
}
//从connectionPool中尝试获取,注意route = null
Internal.instance.get(connectionPool, address, this, null);
if (connection != null) {
return connection;
}
selectedRoute = route;
}
// If we need a route, make one. This is a blocking operation.
if (selectedRoute == null) {
selectedRoute = routeSelector.next();
}
RealConnection result;
synchronized (connectionPool) {
if (canceled) throw new IOException("Canceled");
// Now that we have an IP address, make another attempt at getting a connection from the pool.
// This could match due to connection coalescing.
Internal.instance.get(connectionPool, address, this, selectedRoute);
if (connection != null) {
route = selectedRoute;
return connection;
}
// Create a connection and assign it to this allocation immediately. This makes it possible
// for an asynchronous cancel() to interrupt the handshake we're about to do.
route = selectedRoute;
refusedStreamCount = 0;
result = new RealConnection(connectionPool, selectedRoute);
acquire(result);
}
// Do TCP + TLS handshakes. This is a blocking operation.
result.connect(
connectTimeout, readTimeout, writeTimeout, connectionRetryEnabled, call, eventListener);
routeDatabase().connected(result.route());
Socket socket = null;
synchronized (connectionPool) {
// Pool the connection.
Internal.instance.put(connectionPool, result);
// If another multiplexed connection to the same address was created concurrently, then
// release this connection and acquire that one.
if (result.isMultiplexed()) {
socket = Internal.instance.deduplicate(connectionPool, address, this);
result = connection;
}
}
closeQuietly(socket);
return result;
}
4.10 CallServerInterceptor.intercept
@Override
public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
//HttpCodec是在ConnectInterceptor中创建的
//如果是https协议则是Http2Codec, 否则是Http1Codec
HttpCodec httpCodec = realChain.httpStream();
StreamAllocation streamAllocation = realChain.streamAllocation();
//RealConnection也是在ConnectInterceptor中创建的
RealConnection connection = (RealConnection) realChain.connection();
Request request = realChain.request();
long sentRequestMillis = System.currentTimeMillis();
//向已经建立好的连接写入请求头部, 如果是https,还会创建Http2Stream对象
httpCodec.writeRequestHeaders(request);
Response.Builder responseBuilder = null;
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
//如果请求头部中有Except: 100-continue, 在发送body之前先发送一个请求询问server是否愿意接收数据,只有当server
//返回http/1.1 100 Continue时才继续发送数据,如果服务器没有返回这个,则直接返回server返回的code
if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
httpCodec.flushRequest();
responseBuilder = httpCodec.readResponseHeaders(true);
}
if (responseBuilder == null) {
// Write the request body if the "Expect: 100-continue" expectation was met.
// 写入Body
Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
request.body().writeTo(bufferedRequestBody);
bufferedRequestBody.close();
} else if (!connection.isMultiplexed()) {
// If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection from
// being reused. Otherwise we're still obligated to transmit the request body to leave the
// connection in a consistent state.
streamAllocation.noNewStreams();
}
}
httpCodec.finishRequest();
//读取Response的头部
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 {
response = response.newBuilder()
.body(httpCodec.openResponseBody(response))
.build();
}
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;
}
4.11 ConnectIntercptor.intercept
直接向上返回了CallServerInterceptor得到的Response
4.12 CacheInterceptor.intercept
@Override
public Response intercept(Chain chain) throws IOException {
...
//调用ConnectInterceptor.interceptor()
Response networkResponse = null;
try {
networkResponse = chain.proceed(networkRequest);
} finally {
// If we're crashing on I/O or otherwise, don't leak the cache body.
if (networkResponse == null && cacheCandidate != null) {
closeQuietly(cacheCandidate.body());
}
}
// If we have a cache response too, then we're doing a conditional get.
if (cacheResponse != null) {
if (networkResponse.code() == HTTP_NOT_MODIFIED) {
Response response = cacheResponse.newBuilder()
.headers(combine(cacheResponse.headers(), networkResponse.headers()))
.sentRequestAtMillis(networkResponse.sentRequestAtMillis())
.receivedResponseAtMillis(networkResponse.receivedResponseAtMillis())
.cacheResponse(stripBody(cacheResponse))
.networkResponse(stripBody(networkResponse))
.build();
networkResponse.body().close();
// Update the cache after combining headers but before stripping the
// Content-Encoding header (as performed by initContentStream()).
cache.trackConditionalCacheHit();
cache.update(cacheResponse, response);
return response;
} else {
closeQuietly(cacheResponse.body());
}
}
Response response = networkResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse))
.networkResponse(stripBody(networkResponse))
.build();
if (cache != null) {
if (HttpHeaders.hasBody(response) && CacheStrategy.isCacheable(response, networkRequest)) {
//将response放入缓存
CacheRequest cacheRequest = cache.put(response);
return cacheWritingResponse(cacheRequest, response);
}
//如果method是post, put, patch, delete, move,则移除缓存
if (HttpMethod.invalidatesCache(networkRequest.method())) {
try {
cache.remove(networkRequest);
} catch (IOException ignored) {
// The cache cannot be written.
}
}
}
return response;
}
4.13 BridgeInterceptor.intercept
@Override
public Response intercept(Chain chain) throws IOException {
...
Response networkResponse = chain.proceed(requestBuilder.build());
//处理Cookie
HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());
Response.Builder responseBuilder = networkResponse.newBuilder()
.request(userRequest);
//如果含有Content-Encoding:gzip,即内容是以gzip压缩过的,则解压缩,并移除
//头部中的Content-Encoding和Content-Length
if (transparentGzip
&& "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
&& HttpHeaders.hasBody(networkResponse)) {
GzipSource responseBody = new GzipSource(networkResponse.body().source());
Headers strippedHeaders = networkResponse.headers().newBuilder()
.removeAll("Content-Encoding")
.removeAll("Content-Length")
.build();
responseBuilder.headers(strippedHeaders);
responseBuilder.body(new RealResponseBody(strippedHeaders, Okio.buffer(responseBody)));
}
return responseBuilder.build();
}
4.14 RetryAndFollowUpInterceptor.intercept
@Override
public Response intercept(Chain chain) throws IOException {
....
// 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 = followUpRequest(response);
if (followUp == null) {
if (!forWebSocket) {
streamAllocation.release();
}
return response;
}
closeQuietly(response.body());
//最多重试20次
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());
}
//检查新请求的服务器地址与老地址是否相同,不相同则回收旧的StramAllocation的内存,如果相同
//则复用之前的Connection
if (!sameConnection(response, followUp.url())) {
streamAllocation.release();
streamAllocation = new StreamAllocation(client.connectionPool(),
createAddress(followUp.url()), call, eventListener, callStackTrace);
} 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;
}