OkHttp源码解析2

来源:互联网 发布:黑魂2日系妹捏脸数据 编辑:程序博客网 时间:2024/05/29 14:45

接着上一篇解析,主要是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 {//返回一个策略以满足使用缓存响应的requestpublic 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()

这个就是用来处理重定向的
0 0