OKHttp3–详细使用及源码分析系列之初步介绍【一】
OKHttp3–流程分析 核心类介绍 同步异步请求源码分析【二】
OKHttp3–Dispatcher分发器源码解析【三】
OKHttp3–调用对象RealCall源码解析【四】
OKHttp3–拦截器链RealInterceptorChain源码解析【五】
OKHttp3–重试及重定向拦截器RetryAndFollowUpInterceptor源码解析【六】
OKHttp3–桥接拦截器BridgeInterceptor源码解析及相关http请求头字段解析【七】
OKHttp3–缓存拦截器CacheInterceptor源码解析【八】
OKHttp3-- HTTP缓存机制解析 缓存处理类Cache和缓存策略类CacheStrategy源码分析 【九】
通过ConnectInterceptor源码掌握OKHttp3网络连接原理 呕心沥血第十弹【十】
这篇文章将对OKHttp最后一个拦截器进行解析,总算快要结束了;上一篇文章讲到连接拦截器,即客户端已经与服务端进行了连接,那接下来的操作自然就是发送接收数据了,看看官网的注释
这是拦截器链上的最后一个拦截器,向服务器发起网络访问
那接下来就从源码看看它是如何实现发送请求数据,接收响应数据的
@Override public Response intercept(Chain chain) throws IOException {RealInterceptorChain realChain = (RealInterceptorChain) chain;HttpCodec httpCodec = realChain.httpStream();StreamAllocation streamAllocation = realChain.streamAllocation();RealConnection connection = (RealConnection) tion();Request request = quest();long sentRequestMillis = System.currentTimeMillis();httpCodec.writeRequestHeaders(request);Response.Builder responseBuilder = null;if (HttpMethod.hod()) && 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.if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {httpCodec.flushRequest();responseBuilder = adResponseHeaders(true);}if (responseBuilder == null) {// Write the request body if the "Expect: 100-continue" expectation was met.Sink requestBodyOut = ateRequestBody(request, request.body().contentLength());BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);request.body().writeTo(bufferedRequestBody);bufferedRequestBody.close();} 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 NewStreams();}}httpCodec.finishRequest();if (responseBuilder == null) {responseBuilder = adResponseHeaders(false);}Response response = quest(request).tion().handshake()).sentRequestAtMillis(sentRequestMillis).receivedResponseAtMillis(System.currentTimeMillis()).build();int code = de();if (forWebSocket && code == 101) {// Connection is upgrading, but we need to ensure interceptors see a non-null sponse = wBuilder().body(Util.EMPTY_RESPONSE).build();} else {response = wBuilder().body(httpCodec.openResponseBody(response)).build();}if ("close".quest().header("Connection"))|| "close".equalsIgnoreCase(response.header("Connection"))) {NewStreams();}if ((code == 204 || code == 205) && response.body().contentLength() > 0) {throw new ProtocolException("HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());}return response;}
这里代码我们分开看
第一部分:获取网络组件
RealInterceptorChain realChain = (RealInterceptorChain) chain;HttpCodec httpCodec = realChain.httpStream();StreamAllocation streamAllocation = realChain.streamAllocation();RealConnection connection = (RealConnection) tion();Request request = quest();
这里通过拦截器链拿到了四个对象
第二部分:发送请求
long sentRequestMillis = System.currentTimeMillis();httpCodec.writeRequestHeaders(request);Response.Builder responseBuilder = null;if (HttpMethod.hod()) && request.body() != null) {if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {httpCodec.flushRequest();responseBuilder = adResponseHeaders(true);}if (responseBuilder == null) {Sink requestBodyOut = ateRequestBody(request, request.body().contentLength());BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);request.body().writeTo(bufferedRequestBody);bufferedRequestBody.close();} else if (!connection.isMultiplexed()) {NewStreams();}}httpCodec.finishRequest();
这部分主要是用来发送请求
第一个if判断的意思是:如果请求头中包含【Expect: 100- Continue】,那么就发送100-continue的请求,然后获取服务器的响应,看服务器是否同意接受请求体,如果服务器的响应码是HTTP_CONTINUE,即100,那这个responseBuilder 即为null
第二个判断:上面一个判断可以知道如果服务器同意接受请求体数据,那么responseBuilder 为null,接下来就构建输出流BufferedSink对象,将请求体数据写到其缓冲区
第三个判断:也就是responseBuilder 不为null,意思是服务器不同意接受该请求体,且同时这个连接不支持多路复用,也就是说这是一个Http/1.x的请求,那么我们就需要标记该连接不能再被复用,同时关闭相关的Socket
接下来就是将缓存区的数据写到Socket中,发送出去,到这里发送请求已经完成
第三部分:构建响应
if (responseBuilder == null) {responseBuilder = adResponseHeaders(false);}Response response = quest(request).tion().handshake()).sentRequestAtMillis(sentRequestMillis).receivedResponseAtMillis(System.currentTimeMillis()).build();
首先获取响应头部信息,然后构建响应Response 对象
第四部分:处理响应
int code = de();if (forWebSocket && code == 101) {// Connection is upgrading, but we need to ensure interceptors see a non-null sponse = wBuilder().body(Util.EMPTY_RESPONSE).build();} else {response = wBuilder().body(httpCodec.openResponseBody(response)).build();}if ("close".quest().header("Connection"))|| "close".equalsIgnoreCase(response.header("Connection"))) {NewStreams();}if ((code == 204 || code == 205) && response.body().contentLength() > 0) {throw new ProtocolException("HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());}return response;
可以看到最后一个拦截器的代码比较简单,当然了你要是没有看前面的系列文章,可能会觉得有点懵;拦截器链上的五个拦截器分析完了,后续的文章将会介绍下OKHttp中有关WebSocket的知识点
本文发布于:2024-01-29 02:17:11,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170646583212013.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |