五、OkHttp拦截器CallServerInterceptor

CallServerInterceptor是拦截器链中的最后一个拦截器,它负责向服务器发送器请求。
先看源码:

class CallServerInterceptor(private val forWebSocket: Boolean) : Interceptor {

  @Throws(IOException::class)
  override fun intercept(chain: Interceptor.Chain): Response {
    // 将拦截器链转换为实际的拦截器链对象
    val realChain = chain as RealInterceptorChain
    // 获取与服务器进行交互的Exchange对象
    val exchange = realChain.exchange!!
    // 获取请求对象
    val request = realChain.request
    // 获取请求体对象
    val requestBody = request.body
    // 记录请求发送的时间
    val sentRequestMillis = System.currentTimeMillis()

    // 写入请求头部
    exchange.writeRequestHeaders(request)

    // 初始化变量
    var invokeStartEvent = true
    var responseBuilder: Response.Builder? = null

    // 如果请求方法允许请求体,并且存在请求体
    if (HttpMethod.permitsRequestBody(request.method) && requestBody != null) {
      // HTTP header 中的 Expect 字段用于指示客户端对服务器的期望行为。它允许客户端在发送请求之前,告知服务器应如何处理请求。
      // Expect: 100-continue
      // 100-continue:客户端希望在发送请求正文之前,服务器先发送一个 100 Continue 的响应,用于确认服务器是否愿意接收请求正文。
      // 如果服务器返回了 100 Continue 响应,客户端可以继续发送请求正文;
      // 如果服务器返回其他响应码,客户端则可以终止请求,而无需发送整个请求正文。
      
      // 如果请求头部包含 "Expect: 100-continue",等待 "HTTP/1.1 100 Continue" 响应后再发送请求体
      if ("100-continue".equals(request.header("Expect"), ignoreCase = true)) {
        exchange.flushRequest()
        responseBuilder = exchange.readResponseHeaders(expectContinue = true)
        exchange.responseHeadersStart()
        invokeStartEvent = false
      }
      
      // 如果响应构建器为空,说明 "Expect: 100-continue" 预期没有被满足
      if (responseBuilder == null) {
        if (requestBody.isDuplex()) {
          // isDuplex() 方法用于判断当前请求体是否支持双向通信。
          // 如果返回值为 true,表示该请求体支持双向通信,可以在发送请求后继续向服务器发送数据。
          // 这通常用于实现类似 WebSocket 连接等需要进行实时双向通信的场景。
          
          // 如果返回值为 false,表示该请求体不支持双向通信,只能在发送请求时将请求数据发送给服务器,
          // 无法在请求发送后继续发送额外的数据。
          exchange.flushRequest()
          val bufferedRequestBody = exchange.createRequestBody(request, true).buffer()
          requestBody.writeTo(bufferedRequestBody)
        } else {
          // 写入请求体
          val bufferedRequestBody = exchange.createRequestBody(request, false).buffer()
          requestBody.writeTo(bufferedRequestBody)
          bufferedRequestBody.close()
        }
      } else {
        exchange.noRequestBody()
        if (!exchange.connection.isMultiplexed) {
          // 如果 "Expect: 100-continue" 预期未被满足,防止复用 HTTP/1 连接
          exchange.noNewExchangesOnConnection()
        }
      }
    } else {
      exchange.noRequestBody()
    }

    // 完成请求
    if (requestBody == null || !requestBody.isDuplex()) {
      exchange.finishRequest()
    }

    // 如果响应构建器为空,读取响应头部并进行处理
    if (responseBuilder == null) {
      responseBuilder = exchange.readResponseHeaders(expectContinue = false)!!
      if (invokeStartEvent) {
        exchange.responseHeadersStart()
        invokeStartEvent = false
      }
    }

    // 获取响应对象
    var response = responseBuilder
        .request(request)
        .handshake(exchange.connection.handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build()

    var code = response.code

    //如果响应码为 100,表示服务器发送了一个 100-continue 响应,但我们没有请求它。此时需要重新读取实际的响应状态。
   if (code == 100) {
      // 服务器发送了一个 100-continue 响应,尽管我们没有请求。重新尝试读取实际的响应状态。
      responseBuilder = exchange.readResponseHeaders(expectContinue = false)!!
      if (invokeStartEvent) {
        exchange.responseHeadersStart()
      }
      response = responseBuilder
          .request(request)
          .handshake(exchange.connection.handshake())
          .sentRequestAtMillis(sentRequestMillis)
          .receivedResponseAtMillis(System.currentTimeMillis())
          .build()
      code = response.code
    }

    // 结束响应头部的处理
    exchange.responseHeadersEnd(response)

    // 如果为 WebSocket 并且响应码为 101,表示正在进行协议升级
    response = if (forWebSocket && code == 101) {
      // 连接正在升级,但我们需要确保拦截器看到一个非空的响应体。
      response.newBuilder()
          .body(EMPTY_RESPONSE)
          .build()
    } else {
        // 写入响应体
      response.newBuilder()
          .body(exchange.openResponseBody(response))
          .build()
    }

    // 如果请求或响应头部包含 "Connection: close",防止在此连接上创建新的请求
    if ("close".equals(response.request.header("Connection"), ignoreCase = true) ||
        "close".equals(response.header("Connection"), ignoreCase = true)) {
      exchange.noNewExchangesOnConnection()
    }

    // 如果响应码为 204 或 205,并且响应体长度大于 0,则抛出协议异常
    if ((code == 204 || code == 205) && response.body?.contentLength() ?: -1L > 0L) {
      throw ProtocolException(
          "HTTP $code had non-zero Content-Length: ${response.body?.contentLength()}")
    }

    return response
  }
}

CallServerInterceptor是真正执行网络请求的地方,
通过ConnectInterceptor 连接拦截器获得Socket inputSteram和outputStream 并包装成了source、sink

// val source = InputStreamSource(getInputStream(), timeout)
source = rawSocket.source().buffer()
// val sink = OutputStreamSink(getOutputStream(), timeout)
sink = rawSocket.sink().buffer()

至此,Socket的连接已经建立。之后就是通过CallServerInterceptor 进行数据流的读写,

// 写入请求
requestBody.writeTo(bufferedRequestBody)
// 读取响应流
exchange.openResponseBody(response)

当读取到响应流 并包装成Response 返回后,OkHttp的完整请求至此结束!

你可能感兴趣的:(OkHttp,okhttp,CallServer)