OkHttp是一款网络请求框架,【OkHttp传送门】,为了在开发中使用的更加得心应手,必然的要去探究其源码,分析其中的工作原理,而且还能学习框架的设计思想。文章主要对OkHttp整体的工作流程进行分析,所以一些操作方法并没有涉及,读者可以通过传送门阅读文档自行实践。在分析之前,先看一张整体的流程图(本文内容会根据图的流程展开):
OkHttp请求网络的简单示例
private static final String URL_CONTENT = "https://www.baidu.com/";
public static void doOkHttp() {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.retryOnConnectionFailure(true) //连接失败后进行重连
.build();
final Request request = new Request.Builder()
.url(URL_CONTENT)
.build();
//异步方式请求网络
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//请求失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//请求成功,对response进行处理
}
});
}
上面的代码,首先创建一个okHttpClient对象,调用newCall()并且request作为参数传入,然后执行enqueue(),并且new一个Callback,请求结果的回调,这个过程是异步的。
//execute()是同步的方式请求网络,会阻塞UI线程,所以一般情况都是通过异步的方式请求网络
okHttpClient.newCall(request).execute();
1、OkHttpClient的build()过程。
public Builder() {
dispatcher = new Dispatcher(); //异步请求调度器
protocols = DEFAULT_PROTOCOLS;//请求协议集合,默认为http/1.1和Http/2
connectionSpecs = DEFAULT_CONNECTION_SPECS;//连接规格
eventListenerFactory = EventListener.factory(EventListener.NONE);//事件监听器
proxySelector = ProxySelector.getDefault();//代理选择器
cookieJar = CookieJar.NO_COOKIES;//http cookies 提供持久化策略
socketFactory = SocketFactory.getDefault(); //socket工厂类
hostnameVerifier = OkHostnameVerifier.INSTANCE;//对host基本接口的验证
certificatePinner = CertificatePinner.DEFAULT; //约束的信任证书
proxyAuthenticator = Authenticator.NONE;//代理身份认证
authenticator = Authenticator.NONE;
connectionPool = new ConnectionPool();//连接复用池
dns = Dns.SYSTEM;//默认使用系统的dns
followSslRedirects = true; //遵循SSL重定向
followRedirects = true;//普通重定向
retryOnConnectionFailure = true;//连接失败后进行重新连接
connectTimeout = 10_000;//连接超时时间
readTimeout = 10_000;//读取数据超时时间
writeTimeout = 10_000;//发送数据超时时间
pingInterval = 0;//时间间隔
}
public OkHttpClient build() {
return new OkHttpClient(this);
}
OkHttpClient(Builder builder) {
this.dispatcher = builder.dispatcher;
this.proxy = builder.proxy;
this.protocols = builder.protocols;
this.connectionSpecs = builder.connectionSpecs;
this.interceptors = Util.immutableList(builder.interceptors);//自定义的拦截器
this.networkInterceptors = Util.immutableList(builder.networkInterceptors);//网络拦截器
this.eventListenerFactory = builder.eventListenerFactory;
this.proxySelector = builder.proxySelector;
this.cookieJar = builder.cookieJar;
this.cache = builder.cache;//创建OkHttpClient对象时的自定义缓存
this.internalCache = builder.internalCache;//内部缓存
this.socketFactory = builder.socketFactory;
boolean isTLS = false;
for (ConnectionSpec spec : connectionSpecs) {
isTLS = isTLS || spec.isTls();
}
if (builder.sslSocketFactory != null || !isTLS) {
this.sslSocketFactory = builder.sslSocketFactory;
this.certificateChainCleaner = builder.certificateChainCleaner;
} else {
X509TrustManager trustManager = systemDefaultTrustManager();
this.sslSocketFactory = systemDefaultSslSocketFactory(trustManager);
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
}
this.hostnameVerifier = builder.hostnameVerifier;
this.certificatePinner = builder.certificatePinner.withCertificateChainCleaner(
certificateChainCleaner);
this.proxyAuthenticator = builder.proxyAuthenticator;
this.authenticator = builder.authenticator;
this.connectionPool = builder.connectionPool;
this.dns = builder.dns;
this.followSslRedirects = builder.followSslRedirects;
this.followRedirects = builder.followRedirects;
this.retryOnConnectionFailure = builder.retryOnConnectionFailure;
this.connectTimeout = builder.connectTimeout;
this.readTimeout = builder.readTimeout;
this.writeTimeout = builder.writeTimeout;
this.pingInterval = builder.pingInterval;
if (interceptors.contains(null)) {
throw new IllegalStateException("Null interceptor: " + interceptors);
}
if (networkInterceptors.contains(null)) {
throw new IllegalStateException("Null network interceptor: " + networkInterceptors);
}
}
通过建造者模式创建OkHttpClient对象,并且配置各种参数。
2、Request的Builder()的过程
public Builder() {
this.method = "GET"; //请求方法,默认GET
this.headers = new Headers.Builder();//创建请求头
}
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}
Request(Builder builder) {
this.url = builder.url; //请求url
this.method = builder.method;//请求方法
this.headers = builder.headers.build();//请求头
this.body = builder.body;//请求体
this.tag = builder.tag != null ? builder.tag : this;
}
Request也是以建造者模式创建对象,配置参数。关于HTTP报文结构图(左图对应Request,右图对应Response):
3、okHttpClient.newCall()
public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
//RealCall # newRealCall
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
调用newCall()实际返回的是一个RealCall(继承自Call)对象。RealCall内部封装了网络请求和请求结果回调。那么,上面的异步请求实际调用的是RealCall的enqueue()方法。
4、RealCall # enqueue()
public void enqueue(Callback responseCallback) {
synchronized (this) {
//若任务已经执行,则抛出IllegalStateException
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
//跟踪调用堆栈
captureCallStackTrace();
//监听开始事件
eventListener.callStart(this);
// 1
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
上面代码的核心是注释1处,client.dispatcher()返回一个Dispatcher对象,异步请求调度器,里面会对任务进行分辨,是立刻执行还是放入等待队列。AsyncCall继承NamedRunnable(实现了Runnable接口)类,接着进入Dispatcher的enqueue()方法:
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
从代码可以发现,Dispatcher的enqueue()是一个同步方法,maxRequests是最大请求数(值为64),maxRequestsPerHost是Host最大请求数据(值为5),当满足这两个条件时,把任务添加到执行队列runningAsyncCalls,立刻执行,否则加入等待队列readyAsyncCalls,等待异步调用。executorService()内部创建了一个执行任务的线程池,并且返回一个执行对象ExecutorService。
executorService()的内部实现:
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
以单例模式中的懒汉模式创建了一个线程池。其实上面创建的线程池和我们直接用Executors的newCachedThreadPool()创建是类似的,核心线程数为0,线程空闲时的超时时间60s,直接提交策略。关于线程池的分析,可以阅读【探索Java 线程池】这篇文章。在这里,往线程池中添加的任务对象是AsyncCall,那么看看AsyncCall的内部实现:
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
String host() {
return originalRequest.url().host();
}
Request request() {
return originalRequest;
}
RealCall get() {
return RealCall.this;
}
@Override
protected void execute() {
boolean signalledCallback = false;
try {
//核心请求
Response response = getResponseWithInterceptorChain();
//根据是否取消RetryAndFollowUpInterceptor,分别回调onFailure或onResponse
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 {
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
//请求完毕,移除runningAsyncCalls中当前执行的Call。
//并且查找等待队列readyAsyncCalls是否存在任务,存在,则添加执行队列runningAsyncCalls,然后执行任务
//如果runningAsyncCalls不存在任务,且idleCallback不为null,则启动空闲状态Runnable
client.dispatcher().finished(this);
}
}
}
NamedRunnable实现了Runnable接口,在其run()方法内部调用了execute()方法,这里运用了设计模式中的模板模式,那么,这里就把任务交给了AsyncCall的execute()方法。通过代码的注释可以知道,把请求交由了getResponseWithInterceptorChain()方法,这个方法直译过来意思就是:用拦截器链获取响应报文。而方法内部也正运用了设计模式中的责任链模式。
模板模式
优点:封装不变部分,扩展可变部分;提取公共部分代码,便于维护。
缺点:在代码阅读方面可能会带来相对的难度。责任链模式
优点:对请求者和处理者关系解耦,提高了代码灵活性。
缺点:如果处理者太多,过多的遍历会导致性能降低。
回到OkHttp的请求流程,上面已经把任务交由了getResponseWithInterceptorChain()方法,那么,看下其内部实现。
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List interceptors = new ArrayList<>();
//初始化OkHttpClient对象时添加的自定义interceptors
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
//添加用户自定义的networkInterceptors
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
getResponseWithInterceptorChain()内部添加各种拦截器,利用RealInterceptorChain将已有的拦截器进行串联,然后proceed()开始遍历拦截器。
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
... ....//省略部分代码
// Call the next interceptor in the chain.
//遍历拦截器链,index代表责任链中拦截器的下标,初始值为0
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
... ...//省略部分代码
return response;
}
5、分析各个拦截器的作用
- RetryAndFollowUpInterceptor:在连接失败后进行重新连接,必要时进行重定向,如果调用被取消,可能会抛出IOException
- BridgeInterceptor:构建访问网络的桥梁,首先,将用户请求转换成网络请求,然后访问网络,最后将网络响应转换成用户响应。
- CacheInterceptor:缓存拦截器,从缓存中获取服务器请求,或者把服务器响应写入缓存中。
- ConnectInterceptor:打开一个连接,去连接目标服务器。
- CallServerInterceptor:拦截器链中的最后一个链点,通过网络请求服务器。
链式执行流程:
5.1、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();
//用于分配一个到服务器特定的HttpStream,内部封装了ConnectionPool连接池,管理Http的连接
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) {
// The attempt to connect via a route failed. The request will not have been sent.
if (!recover(e.getLastConnectException(), streamAllocation, false, request)) {
throw e.getLastConnectException();
}
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();
}
}
// Attach the prior response if it exists. Such responses never have a body.
//检测前一个Response
if (priorResponse != null) {
response = response.newBuilder()
.priorResponse(priorResponse.newBuilder()
.body(null)
.build())
.build();
}
Request followUp = followUpRequest(response, streamAllocation.route());
//followUp为null,表示不要重定向,释放资源并且返回response
if (followUp == null) {
if (!forWebSocket) {
streamAllocation.release();
}
return response;
}
//关闭response的body
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());
}
//检测地址是否相同,释放旧连接,重新创建一个新的连接
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;
}
}
5.2、BridgeInterceptor # intercept()
public Response intercept(Chain chain) throws IOException {
Request userRequest = chain.request();
Request.Builder requestBuilder = userRequest.newBuilder();
//将用户的Request构造成服务器的Request
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");
}
//使用Gzip压缩
boolean transparentGzip = false;
if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
transparentGzip = true;
requestBuilder.header("Accept-Encoding", "gzip");
}
//设置cookies
List 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());
}
//传入已构造好的服务器Request,调用下一个拦截器,获取服务器的networkResponse
Response networkResponse = chain.proceed(requestBuilder.build());
//保存networkResponse的cookie
HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());
//后续则是把networkResponse构造成用户的response
Response.Builder responseBuilder = networkResponse.newBuilder()
.request(userRequest);
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);
String contentType = networkResponse.header("Content-Type");
responseBuilder.body(new RealResponseBody(contentType, -1L, Okio.buffer(responseBody)));
}
return responseBuilder.build();
}
5.3、CacheInterceptor # intercept()
public Response intercept(Chain chain) throws IOException {
Response cacheCandidate = cache != null
? cache.get(chain.request())
: null;
//获取当前时间
long now = System.currentTimeMillis();
//获取缓存策略
CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();
Request networkRequest = strategy.networkRequest;
Response cacheResponse = strategy.cacheResponse;
//从缓存中追踪Response
if (cache != null) {
cache.trackResponse(strategy);
}
//如果缓存不适用,则关闭
if (cacheCandidate != null && cacheResponse == null) {
closeQuietly(cacheCandidate.body());
}
// 如果网络被禁止,且缓存为空,则返回失败
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();
}
// 不需要网络时,从缓存中获取
if (networkRequest == null) {
return cacheResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse))
.build();
}
Response networkResponse = null;
try {
//调用下一个拦截者,从网络获取Response
networkResponse = chain.proceed(networkRequest);
} finally {
// 关闭body,防止内存泄露
if (networkResponse == null && cacheCandidate != null) {
closeQuietly(cacheCandidate.body());
}
}
// 如果缓存中存在Response,同时检测networkResponse是否被修改
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 response = networkResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse))
.networkResponse(stripBody(networkResponse))
.build();
//把之前未缓存的添加至缓存中
if (cache != null) {
if (HttpHeaders.hasBody(response) && CacheStrategy.isCacheable(response, networkRequest)) {
// Offer this request to the cache.
CacheRequest cacheRequest = cache.put(response);
return cacheWritingResponse(cacheRequest, response);
}
if (HttpMethod.invalidatesCache(networkRequest.method())) {
try {
cache.remove(networkRequest);
} catch (IOException ignored) {
// The cache cannot be written.
}
}
}
return response;
}
5.4、ConnectInterceptor # intercept()
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");
//获取httpCodec 对象,HttpCodec的实现类有Http1Codec和Http2Codec
//分别对应Http1.1和Http2
//HttpCodec主要是对Http请求和Http响应进行编解码
HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
RealConnection connection = streamAllocation.connection();
//调用下一个拦截器
return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
StreamAllocation的newStream()方法内部实现
public HttpCodec newStream(
OkHttpClient client, Interceptor.Chain chain, boolean doExtensiveHealthChecks) {
int connectTimeout = chain.connectTimeoutMillis();
int readTimeout = chain.readTimeoutMillis();
int writeTimeout = chain.writeTimeoutMillis();
int pingIntervalMillis = client.pingIntervalMillis();
boolean connectionRetryEnabled = client.retryOnConnectionFailure();
try {
//寻找一个可用连接
RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout,
writeTimeout, pingIntervalMillis, connectionRetryEnabled, doExtensiveHealthChecks);
//根据具体的resultConnection 创建resultCodec对象
HttpCodec resultCodec = resultConnection.newCodec(client, chain, this);
synchronized (connectionPool) {
codec = resultCodec;
return resultCodec;
}
} catch (IOException e) {
throw new RouteException(e);
}
}
5.5、CallServerInterceptor # intercept()
public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
HttpCodec httpCodec = realChain.httpStream();
StreamAllocation streamAllocation = realChain.streamAllocation();
RealConnection connection = (RealConnection) realChain.connection();
Request request = realChain.request();
long sentRequestMillis = System.currentTimeMillis();
realChain.eventListener().requestHeadersStart(realChain.call());
//写入请求头
httpCodec.writeRequestHeaders(request);
realChain.eventListener().requestHeadersEnd(realChain.call(), request);
Response.Builder responseBuilder = null;
//检测是否有body的请求方法
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
//如果请求头是"100-continue",等待服务器的响应
if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
httpCodec.flushRequest();
realChain.eventListener().responseHeadersStart(realChain.call());
responseBuilder = httpCodec.readResponseHeaders(true);
}
if (responseBuilder == null) {
// Write the request body if the "Expect: 100-continue" expectation was met.
realChain.eventListener().requestBodyStart(realChain.call());
long contentLength = request.body().contentLength();
//将请求体转换成sink,并封装在CountingSink 内部
CountingSink requestBodyOut =
new CountingSink(httpCodec.createRequestBody(request, contentLength));
BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
request.body().writeTo(bufferedRequestBody);
bufferedRequestBody.close();
realChain.eventListener()
.requestBodyEnd(realChain.call(), requestBodyOut.successfulCount);
} 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();
//从httpCodec中获取响应头
if (responseBuilder == null) {
realChain.eventListener().responseHeadersStart(realChain.call());
responseBuilder = httpCodec.readResponseHeaders(false);
}
//构建response
Response response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
//如果服务器返回的状态码是100,再次尝试读取具体的response
int code = response.code();
if (code == 100) {
// server sent a 100-continue even though we did not request one.
// try again to read the actual response
responseBuilder = httpCodec.readResponseHeaders(false);
response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
code = response.code();
}
realChain.eventListener()
.responseHeadersEnd(realChain.call(), response);
//如果是WebSocket,并且返回状态码为101,表示响应body为空
if (forWebSocket && code == 101) {
response = response.newBuilder()
.body(Util.EMPTY_RESPONSE)
.build();
} else {
//读取body
response = response.newBuilder()
.body(httpCodec.openResponseBody(response))
.build();
}
//如果响应头部是"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;
}
到这里,OkHttp的执行流程就分析完毕了。
关于OkHttp3系列的其它文章:
OkHttp3 源码解析 连接池的复用
OkHttp3源码解析内部缓存