OkHttp源码解析2

接着上一篇解析,主要是HttpEngine,这个类中有三个重要方法,也是OkHttp的主要方法:发送请求—-sendRequest(),读取响应—–readResponse(),处理重定向——-followUpRequest()。

一、发送请求—-sendRequest()

/**
     * 找出响应源是什么,同时,如果有需要,会打开一个套接字到该响应源。准备请求头部,并准备开始写入请求正文,如果响应源存在。
     */
    public void sendRequest() throws RequestException, RouteException, IOException {
        if (cacheStrategy != null) return; // Already sent.
        if (transport != null) throw new IllegalStateException();
        //根据userRequest初始化一个新的Request
        Request request = networkRequest(userRequest);
        //根据OkHttpClient得到缓存
        InternalCache responseCache = Internal.instance.internalCache(client);
        //如果缓存响应可用,即responseCache不为null,则根据键"request"从Cache中取出response
        Response cacheCandidate = responseCache != null
                ? responseCache.get(request)
                : null;

        long now = System.currentTimeMillis();
        cacheStrategy = new CacheStrategy.Factory(now, request, cacheCandidate).get();
        networkRequest = cacheStrategy.networkRequest;
        cacheResponse = cacheStrategy.cacheResponse;
        //缓存可用
if (responseCache != null) {
        responseCache.trackResponse(cacheStrategy);
}
        //缓存不可用,就关闭。
if (cacheCandidate != null && cacheResponse == null) {
            closeQuietly(cacheCandidate.body()); 
}
//networkRequest != null,说明网络可用,且cache不可用
if (networkRequest != null) {
 //建立一个新连接,除非从重定向中继承一个connection
            if (connection == null) {
                connect();
            }
            transport = Internal.instance.newTransport(connection, this);
if (callerWritesRequestBody && permitsRequestBody() && requestBodyOut == null) {
     long contentLength = OkHeaders.contentLength(request);
     if (bufferRequestBody) {
          if (contentLength > Integer.MAX_VALUE) {
                        throw new IllegalStateException("Use setFixedLengthStreamingMode() or "
                                + "setChunkedStreamingMode() for requests larger than 2 GiB.");
}

if (contentLength != -1) {                        transport.writeRequestHeaders(networkRequest);
 requestBodyOut = new RetryableSink((int) contentLength);
} else {

   requestBodyOut = new RetryableSink();
}
} else {
                    transport.writeRequestHeaders(networkRequest);
                    requestBodyOut = transport.createRequestBody(networkRequest, contentLength);
                }
            }

        } else {//networkRequest为null, 要么cache可用,要么网络被禁止使用
            // We aren't using the network. Recycle a connection we may have inherited from a redirect.
            if (connection != null) {
                Internal.instance.recycle(client.getConnectionPool(), connection);
                connection = null;
            }

 if (cacheResponse != null) {
                //缓存响应可用,就通过cacheResponse给userResponse赋值
                // We have a valid cached response. Promote it to the user response immediately.
                this.userResponse = cacheResponse.newBuilder()
                        .request(userRequest)
                        .priorResponse(stripBody(priorResponse))
                        .cacheResponse(stripBody(cacheResponse))
                        .build();
            } else {
                //如果网络被禁止使用,且缓存不可用,就构造一个504的Response,并赋值给userResponse
 this.userResponse = new Response.Builder()
                        .request(userRequest)
                        .priorResponse(stripBody(priorResponse))
                        .protocol(Protocol.HTTP_1_1)
                        .code(504)
                        .message("Unsatisfiable Request (only-if-cached)")
                        .body(EMPTY_BODY)
                        .build();
            }
            //根据缓存response 或者 自己构造的504 Response进行gzip压缩
            userResponse = unzip(userResponse);
        }
    }

中间有用到缓存处理策略

public final class CacheStrategy {

//返回一个策略以满足使用缓存响应的request
public CacheStrategy get() {
  CacheStrategy candidate = getCandidate();

  if (candidate.networkRequest != null && request.cacheControl().onlyIfCached()) {
//网络被禁止使用,且cache不可用,就创建新的CacheStrategy
    // We're forbidden from using the network and the cache is insufficient.
    return new CacheStrategy(null, null);
  }

  return candidate;
}

/** 返回一个策略以取得可以使用网络的request */
private CacheStrategy getCandidate() {
  // 没有cacheResponse,也就是cache不可用
  if (cacheResponse == null) {
//最终就是走网络,所以把第二个参数置为null
    return new CacheStrategy(request, null);
  }
//对于https,如果缺少必要的握手,则删除该缓存响应,认为cache不可用。
  if (request.isHttps() && cacheResponse.handshake() == null) {
//最终就是走网络,所以把第二个参数置为null
    return new CacheStrategy(request, null);
  }
  if (!isCacheable(cacheResponse, request)) {
//最终就是走网络,所以把第二个参数置为null
    return new CacheStrategy(request, null);
  }

  CacheControl requestCaching = request.cacheControl();
  if (requestCaching.noCache() || hasConditions(request)) {
//最终就是走网络,所以把第二个参数置为null
    return new CacheStrategy(request, null);
  }

//判断cache是否过期:通过是否过期,最后修改时间等
  long ageMillis = cacheResponseAge();
  long freshMillis = computeFreshnessLifetime();

  if (requestCaching.maxAgeSeconds() != -1) {
    freshMillis = Math.min(freshMillis, SECONDS.toMillis(requestCaching.maxAgeSeconds()));
  }

  省略........

//如果cacheResponse可用,且不过期,就使用缓存,不走网络
    return new CacheStrategy(null, builder.build());
  }

  Request.Builder conditionalRequestBuilder = request.newBuilder();

   省略........
}
}

二、读取响应—–readResponse()

/*** 刷新剩余的请求头和正文,解析http响应头,并且开始读取http响应正文,前提是正文存在。*/
public void readResponse() throws IOException {
    if (userResponse != null) {
            return; // Already ready.
     }

        //网络不可用,且缓存不可用
        if (networkRequest == null && cacheResponse == null) {
            throw new IllegalStateException("call sendRequest() first!");
        }
        //如果网络不可用,则说明没有可读取的响应体,就不再往下执行
        if (networkRequest == null) {
            return; // No network response to read.
        }

        Response networkResponse;

        if (forWebSocket) {
            //将header写入socket
            transport.writeRequestHeaders(networkRequest);
            //发送request,并读取response
            networkResponse = readNetworkResponse();

        } else if (!callerWritesRequestBody) {
            //先执行拦截器,再发送request,并读取response
            networkResponse = new com.squareup.okhttp.internal.http.HttpEngine.NetworkInterceptorChain(0, networkRequest).proceed(networkRequest);

        } else {
            //发送请求体buffer
            // Emit the request body's buffer so that everything is in requestBodyOut.
            if (bufferedRequestBody != null && bufferedRequestBody.buffer().size() > 0) {
                bufferedRequestBody.emit();
            }

            // Emit the request headers if we haven't yet. We might have just learned the Content-Length.
            if (sentRequestMillis == -1) {
                if (OkHeaders.contentLength(networkRequest) == -1
                        && requestBodyOut instanceof RetryableSink) {
                    long contentLength = ((RetryableSink) requestBodyOut).contentLength();
                    networkRequest = networkRequest.newBuilder()
                            .header("Content-Length", Long.toString(contentLength))
                            .build();
                }
                //写入到socket
                transport.writeRequestHeaders(networkRequest);
            }

            // 将请求体写入到socket
            if (requestBodyOut != null) {
                if (bufferedRequestBody != null) {
                    // This also closes the wrapped requestBodyOut.
                    bufferedRequestBody.close();
                } else {
                    requestBodyOut.close();
                }
                if (requestBodyOut instanceof RetryableSink) {
                    transport.writeRequestBody((RetryableSink) requestBodyOut);
                }
            }

            networkResponse = readNetworkResponse();
        }

        receiveHeaders(networkResponse.headers());

        // 如果缓存可用,且不过期,就使用缓存response
        if (cacheResponse != null) {
            if (validate(cacheResponse, networkResponse)) {
                userResponse = cacheResponse.newBuilder()
                        .request(userRequest)
                        .priorResponse(stripBody(priorResponse))
                        .headers(combine(cacheResponse.headers(), networkResponse.headers()))
                        .cacheResponse(stripBody(cacheResponse))
                        .networkResponse(stripBody(networkResponse))
                        .build();
                networkResponse.body().close();
                releaseConnection();

                // Update the cache after combining headers but before stripping the
                // Content-Encoding header (as performed by initContentStream()).
                InternalCache responseCache = Internal.instance.internalCache(client);
                responseCache.trackConditionalCacheHit();
                responseCache.update(cacheResponse, stripBody(userResponse));
                userResponse = unzip(userResponse);
                return;
            } else {
                closeQuietly(cacheResponse.body());
            }
        }
        //根据networkResponse构造response,并将其缓存
        userResponse = networkResponse.newBuilder()
                .request(userRequest)
                .priorResponse(stripBody(priorResponse))
                .cacheResponse(stripBody(cacheResponse))
                .networkResponse(stripBody(networkResponse))
                .build();

        if (hasBody(userResponse)) {
            maybeCache();
            userResponse = unzip(cacheWritingResponse(storeRequest, userResponse));
        }
    }

还有中间方法

private Response readNetworkResponse() throws IOException {
        //将请求刷新出去
        transport.finishRequest();
        //读取response headers并构造networkResponse
        Response networkResponse = transport.readResponseHeaders()
                .request(networkRequest)
                .handshake(connection.getHandshake())
                .header(OkHeaders.SENT_MILLIS, Long.toString(sentRequestMillis))
                .header(OkHeaders.RECEIVED_MILLIS, Long.toString(System.currentTimeMillis()))
                .build();

        if (!forWebSocket) {
            networkResponse = networkResponse.newBuilder()
                    .body(transport.openResponseBody(networkResponse))
                    .build();
        }

        Internal.instance.setProtocol(connection, networkResponse.protocol());
        return networkResponse;
    }

三、followUpRequest()

这个就是用来处理重定向的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值