源码系列--OkHttp(CallServerInterceptor)
Github下载源码地址https://github.com/square/okhttp
我们今天来看看拦截器里的CallServerInterceptor
来看CallServerInterceptor类的intercept方法
1)源码:
Exchange exchange = realChain.exchange();
Request request = realChain.request();
RealInterceptorChain类分别返回Exchange和Request对象
2)源码
exchange.writeRequestHeaders(request)
进到Exchange类
public void writeRequestHeaders(Request request) throws IOException { try { eventListener.requestHeadersStart(call); codec.writeRequestHeaders(request); eventListener.requestHeadersEnd(call, request); } catch (IOException e) { eventListener.requestFailed(call, e); trackFailure(e); throw e; } }
进到ExchangeCodec的实现类Http1ExchangeCodec(Http1.1版本)的writeRequestHeaders方法
@Override public void writeRequestHeaders(Request request) throws IOException { String requestLine = RequestLine.get( request, realConnection.route().proxy().type()); writeRequest(request.headers(), requestLine); }
进到RequestLine的get方法
public static String get(Request request, Proxy.Type proxyType) { StringBuilder result = new StringBuilder(); result.append(request.method()); result.append(' '); if (includeAuthorityInRequestLine(request, proxyType)) { result.append(request.url()); } else { result.append(requestPath(request.url())); } result.append(" HTTP/1.1"); return result.toString(); }
这里是一些字符串的拼接和请求的判断
紧接着是Http1ExchangeCodec的writeRequest方法
public void writeRequest(Headers headers, String requestLine) throws IOException { if (state != STATE_IDLE) throw new IllegalStateException("state: " + state); sink.writeUtf8(requestLine).writeUtf8("\r\n"); for (int i = 0, size = headers.size(); i < size; i++) { sink.writeUtf8(headers.name(i)) .writeUtf8(": ") .writeUtf8(headers.value(i)) .writeUtf8("\r\n"); } sink.writeUtf8("\r\n"); state = STATE_OPEN_REQUEST_BODY; }
可以看到是通过Okio的BufferedSink实现的
Exchange类的writeRequestHeaders方法的catch中的trackFailure会走失败流程,输出ErrorCode
3)源码
responseBuilder = exchange.readResponseHeaders(true);
进到Exchange类的readResponseHeaders方法,然后再进到Http1ExchangeCodec类的readResponseHeaders方法
看名字都知道是读响应头信息,进到StatusLine的parse方法里
4)源码
BufferedSink bufferedRequestBody = Okio.buffer( exchange.createRequestBody(request, true));
最终进到Http1ExchangeCodec类的createRequestBody方法中
5)CallServerInterceptor类的intercept方法最后是生成response
源码:
Response response = responseBuilder .request(request) .handshake(exchange.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 response = exchange.readResponseHeaders(false) .request(request) .handshake(exchange.connection().handshake()) .sentRequestAtMillis(sentRequestMillis) .receivedResponseAtMillis(System.currentTimeMillis()) .build(); code = response.code(); } exchange.responseHeadersEnd(response); if (forWebSocket && code == 101) { // 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(exchange.openResponseBody(response)) .build(); }
总的来说,还是比较简单的,150行左右的代码。先写请求头,然后发送请求,最后得到响应
而且有两个类Http1ExchangeCodec和Http2ExchangeCodec,很好的适配了不同的http版本
欢迎关注我的微信公众号:安卓圈
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2016-04-30 fragment生命周期