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的完整请求至此结束!