c 拦截请求虚拟服务器,OkHttp的CallServerInterceptor请求服务器拦截器剖析

连接拦截器中用到的复用连接池ConnectionPool传送门:https://www.jianshu.com/p/522b3c7bf333

先回忆一下整个拦截器的流程:

9e402c33b322

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

附上一张整体流程图:

9e402c33b322

11111.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值