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