OkHttp3源码解析--拦截器CallServerInterceptor

本文深入解析CallServerInterceptor的工作原理,这是OkHttp中处理服务器请求的最后一个拦截器。文章详细介绍了如何通过该拦截器写入请求数据,处理期望继续请求,读取响应数据,并最终构建完整的服务器响应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是做后一个拦截器,ConnectInterceptor已经连接到服务器了,接下来我们就是写入请求数据以及读出返回数据了:

  • 写入请求头

  • 写入请求体

  • 读取响应头

  • 读取响应体

看一下代码:

/** This is the last interceptor in the chain. It makes a network call to the server. */
public final class CallServerInterceptor implements Interceptor {
  private final boolean forWebSocket;public CallServerInterceptor(boolean forWebSocket) {
    this.forWebSocket = forWebSocket;
  }@Override public Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;//拦截器链对象
    HttpCodec httpCodec = realChain.httpStream();//依旧负责编码HTTP requests和解码HTTP responses
    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) {
      // 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();
        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));//使用httpCodec创建Http协议中的请求实体
        BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
​
        request.body().writeTo(bufferedRequestBody);//写入请求内容
        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();
​
    realChain.eventListener()
        .responseHeadersEnd(realChain.call(), response);
    //响应码
    int code = response.code();
    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(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;
    }
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值