Okio根据Socket,获取读写缓冲区,负责读写底层Request与Response的Header与Body消息,由Okio的BufferedSource与BufferedSink实现。
CallServerInterceptor拦截器
public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
//上一个拦截器ConnectInterceptor创建的HttpCpdec
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;
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
//请求Header{"Expect":"100-continue”}协议
if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
httpCodec.flushRequest();
realChain.eventListener().responseHeadersStart(realChain.call());
responseBuilder = httpCodec.readResponseHeaders(true);
}
if (responseBuilder == null) {
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);
bufferedRequestBody.close();
realChain.eventListener()
.requestBodyEnd(realChain.call(), requestBodyOut.successfulCount);
} else if (!connection.isMultiplexed()) {
streamAllocation.noNewStreams();
}
}
//Sink的flush
httpCodec.finishRequest();
//利用Source读取Response的Header
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();
//服务端返回100,客户端即使没有发送100-continue,重新构建Response
if (code == 100) {
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) {
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;
}
Http1Codec类BufferedSink的writeUtf8方法写入请求headers。
1,请求body不空,且非GET和HEAD时,如果Header中包括(Expect:100-continue)协议,先flush请求一次,读取服务器返回信息。
2,服务器返回code 100时,先不创建Responsebuilder,返回null,继续将请求body写入。只有服务端支持100,或客户端不发送100-cotinue时,直接写入request.body()。
客户端发送了100-continue,但服务器不支持,将返回非100code,Responsebuilder不空,不会写入body。
3,flush刷新请求,读取服务器返回headers,根据builder构建Response,
4,客户端Header没有请求100-continue字段时,服务器发送一个code100,需要重新读取真实read the actual response,我怀疑是为了重试读取。
Request的header写入
写入header的第一行
GET url HTTP/1.1
下面一行开始是header内容的key和value
读取构建Response
协议。message,code,和header
一行一行的读取header
String line = source.readUtf8LineStrict(headerLimit);
构建Response的headers
第一行StatusLine statusLine = StatusLine.parse(readHeaderLine());
包括message,协议和code。
HTTP/1.1 403 Forbidden
总结
利用Okio框架操作IO,HttpCodec封装了BufferedSource和BufferedSink,数据流缓冲区读写,数据源是RealConnection的Socket。**BufferedSink是写入,BufferedSource是读取。
任重而道远
网友评论