OKHTTP深入浅出(七)----拦截器(4)CallServerInterceptor

就剩最后一个拦截器CallServerInterceptor了,之前的请看

OKHTTP深入浅出(一)----基础理论_王胖子总叫我减肥的博客-CSDN博客

OKHTTP深入浅出(二)----基本用法_王胖子总叫我减肥的博客-CSDN博客

OKHTTP深入浅出(三)----源码流程_王胖子总叫我减肥的博客-CSDN博客

OKHTTP深入浅出(四)----拦截器(1)RetryAndFollowUpInterceptor_王胖子总叫我减肥的博客-CSDN博客
OKHTTP深入浅出(五)----拦截器(2)ridgeInterceptor与CacheInterceptor_王胖子总叫我减肥的博客-CSDN博客
OKHTTP深入浅出(六)----拦截器(3)ConnectInterceptor_王胖子总叫我减肥的博客-CSDN博客

 

 CallServerInterceptor是拦截器链的最后一个拦截器,它对服务器进行网络调用

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;
   // 这个Exchange是connectionintercept传递过来的。
    Exchange exchange = realChain.exchange();
    Request request = realChain.request();

    long sentRequestMillis = System.currentTimeMillis();

    // 将请求头写入到socket中,底层通过Exchangecodec协议类
    // 对应http1Exchange 和 http2Exchange,
   //最终是通过OKio来实现的,具体实现在realBuffersink类里
    exchange.writeRequestHeaders(request);

    // 如果请求有body的话,通过okio将body写入到socket中,用于发送给服务器
    boolean responseHeadersStarted = false;
    Response.Builder responseBuilder = null;
   // 含有body的请求
    if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
     // 如果请求头包含EXCEPT:100-continue
     // 就会等服务器返回含有http/1.1 100 Continue的响应,然后发送在发送请求body
    // 如果没有收到这个响应(例如收到的响应是4XX),那就不发送
      if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
        exchange.flushRequest();
        responseHeadersStarted = true;
        exchange.responseHeadersStart();
     // 读取响应头
        responseBuilder = exchange.readResponseHeaders(true);
      }

     // responseBuilder为 null,说明服务器返回了100,也就是可以继续发送body了
  // 底层通过Exchangecodec协议(http1Exchange 和 http2Exchange)来读取返回header的数据
      if (responseBuilder == null) {
        if (request.body().isDuplex()) {
          // Prepare a duplex body so that the application can send a request body later.
          exchange.flushRequest();
          BufferedSink bufferedRequestBody = Okio.buffer(
              exchange.createRequestBody(request, true));
          request.body().writeTo(bufferedRequestBody);
        } else {
        // 满足了“Expect:100-continue”写请求body
          BufferedSink bufferedRequestBody = Okio.buffer(
              exchange.createRequestBody(request, false));
          request.body().writeTo(bufferedRequestBody);
          bufferedRequestBody.close();
        }
      } else {
     //没有满足 "Expect: 100-continue" ,请求发送结束
        exchange.noRequestBody();
        if (!exchange.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.
          exchange.noNewExchangesOnConnection();
        }
      }
    } else {
  // 没有body请求结束
      exchange.noRequestBody();
    }

 // 请求结束的时候,
    if (request.body() == null || !request.body().isDuplex()) {
  //真正将写到socket输出流的http请求数据发送。
      exchange.finishRequest();
    }

 // 回调读取响应头的开始事件
    if (!responseHeadersStarted) {
      exchange.responseHeadersStart();
    }
 // 读取响应头
    if (responseBuilder == null) {
      responseBuilder = exchange.readResponseHeaders(false);
    }

 //创建返回提response
    Response response = responseBuilder
        .request(request)
        .handshake(exchange.connection().handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build();

    int code = response.code();
    if (code == 100) {
      //服务器又返回了一个100,尝试获取真正的响应
      response = exchange.readResponseHeaders(false)
          .request(request)
          .handshake(exchange.connection().handshake())
          .sentRequestAtMillis(sentRequestMillis)
          .receivedResponseAtMillis(System.currentTimeMillis())
          .build();

      code = response.code();
    }
  
   //回调读取响应头结束
    exchange.responseHeadersEnd(response);
  // 获取响应body
    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 body的数据
   // 底层通过Exchangecodec协议(http1Exchange 和 http2Exchange)
      response = response.newBuilder()
          .body(exchange.openResponseBody(response))
          .build();
    }

  //请求头中的connection是close,表示请求完成后要关闭连接
    if ("close".equalsIgnoreCase(response.request().header("Connection"))
        || "close".equalsIgnoreCase(response.header("Connection"))) {
      exchange.noNewExchangesOnConnection();
    }
 
 // 204 (无内容)205(重置内容)body应该为空
    if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
      throw new ProtocolException(
          "HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
    }

    return response;
  }
}

上述总体就是写入http的请求,读取响应的head和body

无论是读写,都是使用Exchange对应的方法。Exchange理解上是对ExchangeCodec的包装,这写方法内部除了事件回调和一些参数获取外,核心工作都由 ExchangeCodec 对象完成,而 ExchangeCodec实际上利用的是 Okio,而 Okio 实际上还是用的 Socket。

CallServerInterceptor的intercept方法中没有调用连接器链Chain的proceed方法,这是最后一个拦截器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值