OkHttp - Interceptors(四)

作者: Joe_H | 来源:发表于2017-04-09 19:24 被阅读0次

本文中源码基于OkHttp 3.6.0

这篇文章分析 OkHttp 请求流程中的最后一个 Interceptor 节点 - CallServerInterceptor,它的任务就是向服务器发起最终的请求,完成写入请求,读取响应的工作。

- CallServerInterceptor

来看请求执行的入口 intercept 函数。

public Response intercept(Chain chain) throws IOException {
  HttpCodec httpCodec = ((RealInterceptorChain) chain).httpStream();
  StreamAllocation streamAllocation = ((RealInterceptorChain) chain).streamAllocation();
  Request request = chain.request();

  long sentRequestMillis = System.currentTimeMillis();
  // 写入请求 Header
  httpCodec.writeRequestHeaders(request);

  Response.Builder responseBuilder = null;
  // 如果请求允许携带 Body,写入 Body
  if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
    // 如果请求 Header 中包含了 "Expect: 100-continue”,其表示客户端希望服务器告知自己是否允许携带 Body,
    // 如果服务器返回状态码为100,则表示允许携带请求体,那么 readResponseHeaders 返回 null。
    if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
    // 刷新缓冲区,执行请求
      httpCodec.flushRequest();
      responseBuilder = httpCodec.readResponseHeaders(true);
    }

    // 写入请求 Body
    if (responseBuilder == null) {
      Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
      BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
      request.body().writeTo(bufferedRequestBody);
      bufferedRequestBody.close();
    }
  }

  // 刷新缓冲区,执行请求
  httpCodec.finishRequest();

  // 读取响应 Header,
  if (responseBuilder == null) {
    responseBuilder = httpCodec.readResponseHeaders(false);
  }

  // 创建响应
  Response response = responseBuilder
      .request(request)
      .handshake(streamAllocation.connection().handshake())
      .sentRequestAtMillis(sentRequestMillis)
      .receivedResponseAtMillis(System.currentTimeMillis())
      .build();

  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 {
    // 写入响应 Body
    response = response.newBuilder()
        .body(httpCodec.openResponseBody(response))
        .build();
  }

  // 如果 Header 中设置了 “Connection:close”,关闭连接
  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;
}

CallServerInterceptor执行请求过程主要分为4步,利用在上一个节点中创建的HttpCodec实现与服务器的交互:

  1. 写入 Request Header;
  2. 写入 Request Body;
  3. 读取 Response Header;
  4. 读取 Response Body。

至此, Request 请求过程中上游部分就结束了,一个原始的 Response 就被创建出来了,这个 Response 将按请求链上的反向路径一步步返回到上一个 Interceptor 节点,供其继续处理从服务器返回的 Response,直到最后返回给用户,完成一次网络请求。

相关文章

网友评论

    本文标题:OkHttp - Interceptors(四)

    本文链接:https://www.haomeiwen.com/subject/optjattx.html