6、okhttp源码解析-拦截器CallServerInterc

2020-08-31  本文已影响0人  飞奔的口罩

1、okhttp源码解析-整体流程
2、okhttp源码解析-拦截器RetryAndFllowUpInterceptor
3、okhttp源码解析-拦截器BridgeInterceptor
4、okhttp源码解析-拦截器CacheInterceptor
5、okhttp源码解析-拦截器ConnectInterceptor
6、okhttp源码解析-拦截器CallServerInterceptor
7、okhttp源码解析-Dispatcher任务管理器

CallServerInterceptor

1、这个拦截器是最后一个官方拦截器。
2、这个拦截器是处理输出流sink,接收流source的。

一、源码分析

上一节ConnectInterceptor,我们说到streamAllocation.newStream()在3.9v的时候。
创建只创建了HttpCodec*,而在这个拦截器会通过HttpConnect.newStream()来创建HttpStream。

@Override public Response intercept(Chain chain) throws IOException {

    // 1.获取几个前面拦截方法创建的,重要类
    HttpCodec httpCodec = ((RealInterceptorChain) chain).httpStream();
    StreamAllocation streamAllocation = ((RealInterceptorChain) chain).streamAllocation();
    Request request = chain.request();
    long sentRequestMillis = System.currentTimeMillis();

    //2. 先向sink(OutputStream)中写头信息
    httpCodec.writeRequestHeaders(request);

    Response.Builder responseBuilder = null;

   // 3.判断是否有请求实体的请求,用method判断
    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.
   
      //4. 如果头部添加了"100-continue", 相对于一次见到的握手操作,只有拿到服务的结果再继续
      if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
        httpCodec.flushRequest();
        responseBuilder = httpCodec.readResponseHeaders(true);
      }

      //5. 当前面的"100-continue",需要握手,但又握手失败,这个时候responseBuilder不是空的
      // Write the request body, unless an "Expect: 100-continue" expectation failed.
      if (responseBuilder == null) {
        Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
        BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);

        // 回调RequestBody的writeTo,写相应的数据
        request.body().writeTo(bufferedRequestBody);
        bufferedRequestBody.close();
      }
    }

    //6. 这里也是调用了一次 sink.flush()
    httpCodec.finishRequest();

    //7. 读取头部信息,状态码,信息等
    if (responseBuilder == null) {
      responseBuilder = httpCodec.readResponseHeaders(false);
    }

    //8. 构建Response, 写入原请求,握手情况,请求时间,得到的结果时间
    Response response = responseBuilder
        .request(request)
        .handshake(streamAllocation.connection().handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build();

    int code = response.code();
    //9. 通过状态码判断以及是否webSocket判断,是否返回一个空的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 {
      //读取Body信息
      response = response.newBuilder()
          .body(httpCodec.openResponseBody(response))
          .build();
    }

    //10 .如果设置了连接 close ,断开连接
    if ("close".equalsIgnoreCase(response.request().header("Connection"))
        || "close".equalsIgnoreCase(response.header("Connection"))) {
      streamAllocation.noNewStreams();
    }

    //11. HTTP 204(no content) 代表响应报文中包含若干首部和一个状态行,但是没有实体的主体内容。
    //HTTP 205(reset content) 表示响应执行成功,重置页面(Form表单),方便用户下次输入
    //这里做了同样的处理,就是抛出协议异常。
    if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
      throw new ProtocolException(
          "HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
    }

    return response;
  }
上一篇下一篇

猜你喜欢

热点阅读