美文网首页
OkHttp的CallServerInterceptor请求服务

OkHttp的CallServerInterceptor请求服务

作者: 几行代码 | 来源:发表于2019-01-30 15:47 被阅读0次

连接拦截器中用到的复用连接池ConnectionPool传送门:https://www.jianshu.com/p/522b3c7bf333
先回忆一下整个拦截器的流程:

image.png

可以看到CallServerInterceptor是最后一个拦截器,主要工作就是,写入请求头、写入请求体,读取响应头、读取响应体。

/** This is the last interceptor in the chain. It makes a network call to the server.
 * 将http请求写入到io流中,也可以从io流中读取服务器返回给我们客服端的数据
 * */
public final class CallServerInterceptor implements Interceptor {
    private final boolean forWebSocket;

    public CallServerInterceptor(boolean forWebSocket) {
        this.forWebSocket = forWebSocket;
    }

    @Override public Response intercept(@NonNull 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); // 向socket当中写入请求的头部的信息
        realChain.eventListener().requestHeadersEnd(realChain.call(), request);

        Response.Builder responseBuilder = null;
        if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
            // If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100
            // Continue" response before transmitting the request body. If we don't get that, return
            // what we did get (such as a 4xx response) without ever transmitting the request body.
            // 如果请求中存在“Expect:100-continue”标头,请在发送请求主体之前等待“HTTP / 1.1 100 Continue”响应。
            // 如果我们没有得到,请返回我们得到的内容(例如4xx响应),而不发送请求主体。
            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();
                CountingSink requestBodyOut =
                        new CountingSink(httpCodec.createRequestBody(request, contentLength));
                BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);

                request.body().writeTo(bufferedRequestBody); // 向socket当中写入请求的body信息
                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(); // 完成了整个网络请求的写入工作

        if (responseBuilder == null) {
            realChain.eventListener().responseHeadersStart(realChain.call());
            responseBuilder = httpCodec.readResponseHeaders(false); // 读取网络响应的头部信息
        }

        Response response = responseBuilder
                .request(request)
                .handshake(streamAllocation.connection().handshake())
                .sentRequestAtMillis(sentRequestMillis)
                .receivedResponseAtMillis(System.currentTimeMillis())
                .build();

        // 读取响应体
        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);

        if (forWebSocket && code == 101) { // 读取网络请求的body信息
            // 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;
    }

    static final class CountingSink extends ForwardingSink {
        long successfulCount;

        CountingSink(Sink delegate) {
            super(delegate);
        }

        @Override public void write(Buffer source, long byteCount) throws IOException {
            super.write(source, byteCount);
            successfulCount += byteCount;
        }
    }
}

到这里说所有的拦截器就分析完了,我们总结一下OkHttp中一次网络请求的大致过程:
1.Call对象对请求的封装
2.dispatch对请求的分发
3.getResponseWithInterceptorChain()的使用
具体:
RetryAndFollowUpInterceptor
CacheInterceptor
BridgeInterceptor
ConnectInterceptor
CallServerInterceptor

附上一张整体流程图:


11111.png

OkHttp入门用法的传送门:https://www.jianshu.com/p/500abf06f447

相关文章

网友评论

      本文标题:OkHttp的CallServerInterceptor请求服务

      本文链接:https://www.haomeiwen.com/subject/bglcsqtx.html