OkHttp源码解析(拦截器分析)

58 阅读3分钟

对于OKHttp的源码解析,我一共分了三章

OkHttp源码解析(使用与基本类介绍)

OKHttp源码解析(流程分析)

OkHttp源码解析(拦截器分析)

这一章我们主要来了解一下拦截器

拦截器

按照拦截器的添加顺序来看:

  • client.interceptors():这是由开发者设置的,会在所有的拦截器处理之前进行最早的拦截器处理,可用于添加一些公共参数,如 自定义header、自定义log、参数判断等。
  • RetryAndFollowUpInterceptor:重试与重定向拦截器。会对连接做一些初始化工作,以及请求失败的重试工作,重定向的后续请求操作
  • BridgeInterceptor:桥接拦截器。主要是帮我们生成HTTP请求头的内容。
  • CacheInterceptor:缓存拦截器。在真正向服务器发起请求之前,先判断是否命中缓存。缓存如果命中,则直接使用缓存的内容,不用再向服务器发起请求。从而减小网络访问的开销。
  • ConnectInterceptor:负责建立连接。
  • client.networkInterceptors():开发者自己设置的,这个拦截器一般做网络调试用,用户自定义,插在连接拦截器和请求服务拦截器之间。
  • CallServerInterceptor():向服务器发起请求并读取服务器的响应。

RetryAndFollowUpInterceptor 重试与重定向拦截器

主要处理一下几个问题

  • 1.异常,或者协议重试(408客户端超时,权限问题,503服务暂时不处理,retry-after为0)
  • 2.重定向
  • 3.重试的次数不能超过20次。
class RetryAndFollowUpInterceptor(private val client: OkHttpClient) : Interceptor {

    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val realChain = chain as RealInterceptorChain
        var request = chain.request
        val call = realChain.call
        var followUpCount = 0
        var priorResponse: Response? = null
        var newExchangeFinder = true
        var recoveredFailures = listOf<IOException>()
        while (true) {
            //这里会新建一个ExchangeFinder,ConnectInterceptor会使用到
            call.enterNetworkInterceptorExchange(request, newExchangeFinder)

            var response: Response
            var closeActiveExchange = true
            try {
                if (call.isCanceled()) {
                    throw IOException("Canceled")
                }

                try {
                    response = realChain.proceed(request)
                    newExchangeFinder = true
                } catch (e: RouteException) {
                    // 尝试通过路由连接失败,该请求将不会被发送
                    // The attempt to connect via a route failed. The request will not have been sent.
                    if (!recover(e.lastConnectException, call, request, requestSendStarted = false)) {
                        throw e.firstConnectException.withSuppressed(recoveredFailures)
                    } else {
                        recoveredFailures += e.firstConnectException
                    }
                    newExchangeFinder = false
                    continue
                } catch (e: IOException) {
                    //尝试与服务器通信失败。该请求可能已发送。
                    // An attempt to communicate with a server failed. The request may have been sent.
                    if (!recover(e, call, request, requestSendStarted = e !is ConnectionShutdownException)) {
                        throw e.withSuppressed(recoveredFailures)
                    } else {
                        recoveredFailures += e
                    }
                    newExchangeFinder = false
                    continue
                }
                // 尝试关联上一个response,注意:body是为null
                // Attach the prior response if it exists. Such responses never have a body.
                if (priorResponse != null) {
                    response = response.newBuilder()
                        .priorResponse(priorResponse.newBuilder()
                                .body(null)
                                .build())
                        .build()
                }

                val exchange = call.interceptorScopedExchange
                // 会根据 responseCode 来判断,构建一个新的request并返回来重试或者重定向
                val followUp = followUpRequest(response, exchange)

                if (followUp == null) {
                    if (exchange != null && exchange.isDuplex) {
                        call.timeoutEarlyExit()
                    }
                    closeActiveExchange = false
                    return response
                }

                // 如果请求体是一次性的, 不需要再次重试
                val followUpBody = followUp.body
                if (followUpBody != null && followUpBody.isOneShot()) {
                    closeActiveExchange = false
                    return response
                }

                response.body?.closeQuietly()
                // 最大重试次数,不同的浏览器是不同的
                // MAX_FOLLOW_UPS    Chrome 21次; Firefox 20次; Safari 16次; HTTP1.0 建议5次。
                if (++followUpCount > MAX_FOLLOW_UPS) {
                    throw ProtocolException("Too many follow-up requests: $followUpCount")
                }

                request = followUp
                priorResponse = response
            } finally {
                call.exitNetworkInterceptorExchange(closeActiveExchange)
            }
        }
    }

    // 判断是否需要重连, false->不尝试重连   true->尝试重连
    private fun recover(
        e: IOException,
        call: RealCall,
        userRequest: Request,
        requestSendStarted: Boolean
    ): Boolean {
        // 客户端禁止重连
        // The application layer has forbidden retries.
        if (!client.retryOnConnectionFailure) return false

        // 不能再次发送该请求体
        // We can't send the request body again.
        if (requestSendStarted && requestIsOneShot(e, userRequest)) return false

        // 发生的异常是致命的,无法恢复的
        // This exception is fatal.
        if (!isRecoverable(e, requestSendStarted)) return false

        // 没有更多的路由尝试重连
        // No more routes to attempt.
        if (!call.retryAfterFailure()) return false
        
        // 对于故障恢复,将相同的路由选择器与新连接一起使用
        // For failure recovery, use the same route selector with a new connection.
        return true
    }
        ...省略代码...
}

  • 调用RealCall的enterNetworkInterceptorExchange方法实例化一个ExchangeFinder在RealCall对象中。
  • 执行RealCall的proceed 方法,进入下一个拦截器,进行下一步的请求处理。
  • 如果出现路由异常,则通过recover方法校验,当前的连接是否可以重试,不能重试则抛出异常,离开当前的循环。

BridgeInterceptor 桥接拦截器

主要处理了如下几个问题:

  • 主要将Content-Type、Content-Length、Host等一些数据添加到头部。
  • 拿到数据之后对数据进行处理,判断是否为gzip,进行对数据数据解压。
class BridgeInterceptor(private val cookieJar: CookieJar) : Interceptor {

    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        // 获取原始的请求数据
        val userRequest = chain.request()
        // 在原始的request的参数基础上创建一个新的 builder
        val requestBuilder = userRequest.newBuilder()
        
        // 获取原始请求的body
        // 重新构建请求 添加一些必要的请求头信息
        val body = userRequest.body
        if (body != null) {
            val contentType = body.contentType()
            if (contentType != null) {
                requestBuilder.header("Content-Type", contentType.toString())
            }

            val contentLength = body.contentLength()
            if (contentLength != -1L) {
                requestBuilder.header("Content-Length", contentLength.toString())
                requestBuilder.removeHeader("Transfer-Encoding")
            } else {
                requestBuilder.header("Transfer-Encoding", "chunked")
                requestBuilder.removeHeader("Content-Length")
            }
        }

        if (userRequest.header("Host") == null) {
            requestBuilder.header("Host", userRequest.url.toHostHeader())
        }

        if (userRequest.header("Connection") == null) {
            requestBuilder.header("Connection", "Keep-Alive")
        }

        var transparentGzip = false
        if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
            transparentGzip = true
            requestBuilder.header("Accept-Encoding", "gzip")
        }

        // 添加cookie
        val cookies = cookieJar.loadForRequest(userRequest.url)
        if (cookies.isNotEmpty()) {
            requestBuilder.header("Cookie", cookieHeader(cookies))
        }

        // 添加 user-Agent
        if (userRequest.header("User-Agent") == null) {
            requestBuilder.header("User-Agent", userAgent)
        }

        // 使用新的builder构建一个新的request,然后执行下一个拦截器来处理请求
        val networkResponse = chain.proceed(requestBuilder.build())

        cookieJar.receiveHeaders(userRequest.url, networkResponse.headers)
        
        // 创建一个新的responseBuilder,目的是将原始请求数据构建到response中
        val responseBuilder = networkResponse.newBuilder()
            .request(userRequest)

        if (transparentGzip &&
                "gzip".equals(networkResponse.header("Content-Encoding"), ignoreCase = true) &&
                networkResponse.promisesBody()) {
            val responseBody = networkResponse.body
            if (responseBody != null) {
                val gzipSource = GzipSource(responseBody.source())
                val strippedHeaders = networkResponse.headers.newBuilder()
                    .removeAll("Content-Encoding")
                    .removeAll("Content-Length")
                    .build()
                // 修改response header信息,移除Content-Encoding,Content-Length信息
                responseBuilder.headers(strippedHeaders)
                val contentType = networkResponse.header("Content-Type")
                // 修改response body信息
                responseBuilder.body(RealResponseBody(contentType, -1L, gzipSource.buffer()))
            }
        }

        return responseBuilder.build()
    }

    /** Returns a 'Cookie' HTTP request header with all cookies, like `a=b; c=d`. */
    private fun cookieHeader(cookies: List<Cookie>): String = buildString {
        cookies.forEachIndexed { index, cookie ->
            if (index > 0) append("; ")
            append(cookie.name).append('=').append(cookie.value)
        }
    }
}

  • 设置头部的Content-Type.说明内容类型是什么
  • 如果contentLength大于等于0,则设置头部的Content-Length(说明内容大小是多少);否则设置头部的Transfer-Encoding为chunked(说明传输编码为分块传输)
  • 如果Host不存在,设置头部的Host(在Http 1.1之后出现,可以通过同一个URL访问到不同主机,从而实现服务器虚拟服务器的负载均衡。如果1.1之后不设置就会返回404)。
  • 如果Connection不存在,设置头部的Connection为Keep-Alive(代表连接状态需要保持活跃)
  • 如果Accept-Encoding且Range为空,则强制设置Accept-Encoding为gzip(说明请求将会以gzip方式压缩)
  • 从CookieJar的缓存中取出cookie设置到头部的Cookie
  • 如果User-Agent为空,则设置User-Agent到头部

CacheInterceptor 缓存拦截器

用户通过OkHttpClient.cache来配置缓存,缓存拦截器通过CacheStrategy来判断是使用网络还是缓存来构建response

class CacheInterceptor(internal val cache: Cache?) : Interceptor {

    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val call = chain.call()
        // 通过request从OkHttpClient.cache中获取缓存
        val cacheCandidate = cache?.get(chain.request())

        val now = System.currentTimeMillis()

        // 创建缓存策略
        val strategy = CacheStrategy.Factory(now, chain.request(), cacheCandidate).compute()
        // 为空表示不使用网络,反之,则表示使用网络
        val networkRequest = strategy.networkRequest
        // 为空表示不使用缓存,反之,则表示使用缓存
        val cacheResponse = strategy.cacheResponse
        
        // 追踪网络与缓存的使用情况
        cache?.trackResponse(strategy)
        val listener = (call as? RealCall)?.eventListener ?: EventListener.NONE

        // 有缓存 但是不适用,关闭它
        if (cacheCandidate != null && cacheResponse == null) {
            // The cache candidate wasn't applicable. Close it.
            cacheCandidate.body?.closeQuietly()
        }

        // 如果网络被禁止,但是缓存又是空的,构建一个code为504的response,并返回
        // If we're forbidden from using the network and the cache is insufficient, fail.
        if (networkRequest == null && cacheResponse == null) {
            return Response.Builder()
                .request(chain.request())
                .protocol(Protocol.HTTP_1_1)
                .code(HTTP_GATEWAY_TIMEOUT)
                .message("Unsatisfiable Request (only-if-cached)")
                .body(EMPTY_RESPONSE)
                .sentRequestAtMillis(-1L)
                .receivedResponseAtMillis(System.currentTimeMillis())
                .build().also {
                    listener.satisfactionFailure(call, it)
                }
        }

        // 如果我们禁用了网络不使用网络,且有缓存,直接根据缓存内容构建并返回response
        // If we don't need the network, we're done.
        if (networkRequest == null) {
            return cacheResponse!!.newBuilder()
                .cacheResponse(stripBody(cacheResponse))
                .build().also {
                    listener.cacheHit(call, it)
                }
        }

        // 为缓存添加监听
        if (cacheResponse != null) {
            listener.cacheConditionalHit(call, cacheResponse)
        } else if (cache != null) {
            listener.cacheMiss(call)
        }

        var networkResponse: Response? = null
        try {
            //责任链往下处理,从服务器返回response 赋值给 networkResponse
            networkResponse = chain.proceed(networkRequest)
        } finally {
            // 捕获I/O或其他异常,请求失败,networkResponse为空,且有缓存的时候,不暴露缓存内容
            // If we're crashing on I/O or otherwise, don't leak the cache body.
            if (networkResponse == null && cacheCandidate != null) {
                // 否则关闭缓存响应体
                cacheCandidate.body?.closeQuietly()
            }
        }

        // 如果有缓存
        // If we have a cache response too, then we're doing a conditional get.
        if (cacheResponse != null) {
            // 且网络返回response code为304的时候,使用缓存内容新构建一个Response返回。
            if (networkResponse?.code == HTTP_NOT_MODIFIED) {
                val response = cacheResponse.newBuilder()
                    .headers(combine(cacheResponse.headers, networkResponse.headers))
                    .sentRequestAtMillis(networkResponse.sentRequestAtMillis)
                    .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis)
                    .cacheResponse(stripBody(cacheResponse))
                    .networkResponse(stripBody(networkResponse))
                    .build()

                networkResponse.body!!.close()

                // Update the cache after combining headers but before stripping the
                // Content-Encoding header (as performed by initContentStream()).
                cache!!.trackConditionalCacheHit()
                cache.update(cacheResponse, response)
                return response.also {
                    listener.cacheHit(call, it)
                }
            } else {
                // 否则关闭缓存响应体
                cacheResponse.body?.closeQuietly()
            }
        }

        // 构建网络请求的response
        val response = networkResponse!!.newBuilder()
            .cacheResponse(stripBody(cacheResponse))
            .networkResponse(stripBody(networkResponse))
            .build()

        // 如果cache不为null,即用户在OkHttpClient中配置了缓存,则将上一步新构建的网络请求response存到cache中
        if (cache != null) {
            // 根据response的code,header以及CacheControl.noStore来判断是否可以缓存
            if (response.promisesBody() && CacheStrategy.isCacheable(response, networkRequest)) {
                // 将该response存入缓存
                val cacheRequest = cache.put(response)
                return cacheWritingResponse(cacheRequest, response).also {
                    if (cacheResponse != null) {
                        // This will log a conditional cache miss only.
                        listener.cacheMiss(call)
                    }
                }
            }

            // 根据请求方法来判断缓存是否有效,只对Get请求进行缓存,其它方法的请求则移除
            if (HttpMethod.invalidatesCache(networkRequest.method)) {
                try {
                    // 缓存无效,将该请求缓存从client缓存配置中移除
                    cache.remove(networkRequest)
                } catch (_: IOException) {
                    // The cache cannot be written.
                }
            }
        }

        return response
    }
}

网络请求前:

  • 首先根据request从OkHttpClient.cache中获取缓存,通过CacheStrategy获取本次请求的请求体及缓存的响应体。
  • 如果 请求体networkRequest和响应体cacheResponse都为空的话,则返回错误码为 504
  • 如果 请求体networkRequest为空 响应体cacheResponse不为空的话,则将该响应体返回
  • 如果请求体networkRequest不为空的话,则进入下一个拦截器。

网络请求后:

  • 如果当前cacheResponse不为空,且 networkResponse状态码为304, 则代表数据没有变化,那么就会根据 cacheResponse 构建一个新的 response,根据当前时间更新到缓存当中,并返回到上一拦截器中
  • 如果networkResponse状态码不为304,则判断是否进行缓存,最后返回到上一拦截器中

ConnectInterceptor 连接拦截器

object ConnectInterceptor : Interceptor {
    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val realChain = chain as RealInterceptorChain
        // 初始化一个 exchange对象
        val exchange = realChain.call.initExchange(chain)
        // 根据这个exchange对象 来复制创建一个新的连接责任链
        val connectedChain = realChain.copy(exchange = exchange)
        // 执行该连接责任链
        return connectedChain.proceed(realChain.request)
    }
}

这里核心的一个东西是 exchange,让我们来看一下 initExchange这个方法

internal fun initExchange(chain: RealInterceptorChain): Exchange {
    synchronized(this) {
        check(expectMoreExchanges) { "released" }
        check(!responseBodyOpen)
        check(!requestBodyOpen)
    }

    // 这里的 exchangeFinder 就是在 RetryAndFollowUpInterceptor中创建的
    val exchangeFinder = this.exchangeFinder!!
    // 返回一个ExchangeCodec, 
    // ExchangeCodec 是一个编解码器,对request进行编码 并对Response进行解码
    val codec = exchangeFinder.find(client, chain)
    // 根据exchangeFinder与codec新构建一个Exchange对象,并返回
    val result = Exchange(this, eventListener, exchangeFinder, codec)
    this.interceptorScopedExchange = result
    this.exchange = result
    synchronized(this) {
        this.requestBodyOpen = true
        this.responseBodyOpen = true
    }

    if (canceled) throw IOException("Canceled")
    return result
}

ExchangeFinder.find()

fun find(
    client: OkHttpClient,
    chain: RealInterceptorChain
): ExchangeCodec {
    try {
        // 查找一个合格可用的连接,返回一个 RealConnection 对象
        val resultConnection = findHealthyConnection(
            connectTimeout = chain.connectTimeoutMillis,
            readTimeout = chain.readTimeoutMillis,
            writeTimeout = chain.writeTimeoutMillis,
            pingIntervalMillis = client.pingIntervalMillis,
            connectionRetryEnabled = client.retryOnConnectionFailure,
            doExtensiveHealthChecks = chain.request.method != "GET"
        )
        // 根据连接,创建并返回一个请求响应编码器
        // Http1ExchangeCodec 或者 Http2ExchangeCodec,分别对应Http1协议与Http2协议
        return resultConnection.newCodec(client, chain)
    } catch (e: RouteException) {
        trackFailure(e.lastConnectException)
        throw e
    } catch (e: IOException) {
        trackFailure(e)
        throw RouteException(e)
    }
}

findHealthyConnection()

// 查找连接,如果连接正常,则返回该连接。如果它不正常,则重复该过程,直到找到正常的连接。
private fun findHealthyConnection(
    connectTimeout: Int,
    readTimeout: Int,
    writeTimeout: Int,
    pingIntervalMillis: Int,
    connectionRetryEnabled: Boolean,
    doExtensiveHealthChecks: Boolean
): RealConnection {
    while (true) {
        // 查找连接
        val candidate = findConnection(
            connectTimeout = connectTimeout,
            readTimeout = readTimeout,
            writeTimeout = writeTimeout,
            pingIntervalMillis = pingIntervalMillis,
            connectionRetryEnabled = connectionRetryEnabled
        )

        // 确认连接是否可用,可用则直接返回
        // Confirm that the connection is good.
        if (candidate.isHealthy(doExtensiveHealthChecks)) {
            return candidate
        }

        // 如果不合格,则标记为不可用,从连接池中移除
        // If it isn't, take it out of the pool.
        candidate.noNewExchanges()

        // Make sure we have some routes left to try. One example where we may exhaust all the routes
        // would happen if we made a new connection and it immediately is detected as unhealthy.
        if (nextRouteToTry != null) continue

        val routesLeft = routeSelection?.hasNext() ?: true
        if (routesLeft) continue

        val routesSelectionLeft = routeSelector?.hasNext() ?: true
        if (routesSelectionLeft) continue

        throw IOException("exhausted all routes")
    }
}

findConnection()

private fun findConnection(
    connectTimeout: Int,
    readTimeout: Int,
    writeTimeout: Int,
    pingIntervalMillis: Int,
    connectionRetryEnabled: Boolean
): RealConnection {
    if (call.isCanceled()) throw IOException("Canceled")

    // 先重试重连 call 中的connection,不需要重新去获取连接
    // Attempt to reuse the connection from the call.
    val callConnection = call.connection // This may be mutated by releaseConnectionNoEvents()!
    if (callConnection != null) {
        var toClose: Socket? = null
        synchronized(callConnection) {
            if (callConnection.noNewExchanges || !sameHostAndPort(callConnection.route().address.url)) {
                toClose = call.releaseConnectionNoEvents()
            }
        }

        // 如果 call中的 connection没有被释放,则重用它
        // If the call's connection wasn't released, reuse it. We don't call connectionAcquired() here
        // because we already acquired it.
        if (call.connection != null) {
            check(toClose == null)
            return callConnection
        }
        // 如果 call 中的 connection 已经被释放了,则关闭 socket
        // The call's connection was released.
        toClose?.closeQuietly()
        eventListener.connectionReleased(call, callConnection)
    }

    // 需要一个新的连接,所以重置一些状态
    // We need a new connection. Give it fresh stats.
    refusedStreamCount = 0
    connectionShutdownCount = 0
    otherFailureCount = 0

    // 尝试从连接池中获取一个连接
    // Attempt to get a connection from the pool.
    if (connectionPool.callAcquirePooledConnection(address, call, null, false)) {
        val result = call.connection!!
        eventListener.connectionAcquired(call, result)
        return result
    }

    // 如果连接池中是空的,准备下次尝试连接的路由
    // Nothing in the pool. Figure out what route we'll try next.
    val routes: List<Route>?
    val route: Route
    if (nextRouteToTry != null) {
        // Use a route from a preceding coalesced connection.
        routes = null
        route = nextRouteToTry!!
        nextRouteToTry = null
    } else if (routeSelection != null && routeSelection!!.hasNext()) {
        // Use a route from an existing route selection.
        routes = null
        route = routeSelection!!.next()
    } else {
        // Compute a new route selection. This is a blocking operation!
        var localRouteSelector = routeSelector
        if (localRouteSelector == null) {
            localRouteSelector = RouteSelector(address, call.client.routeDatabase, call, eventListener)
            this.routeSelector = localRouteSelector
        }
        val localRouteSelection = localRouteSelector.next()
        routeSelection = localRouteSelection
        routes = localRouteSelection.routes

        if (call.isCanceled()) throw IOException("Canceled")

        // 第三次,再次尝试从连接池中获取一个连接,带路由,不带多路复用
        // Now that we have a set of IP addresses, make another attempt at getting a connection from
        // the pool. We have a better chance of matching thanks to connection coalescing.
        if (connectionPool.callAcquirePooledConnection(address, call, routes, false)) {
            val result = call.connection!!
            eventListener.connectionAcquired(call, result)
            return result
        }

        route = localRouteSelection.next()
    }

    // 第四次,手动创建一个新连接
    // Connect. Tell the call about the connecting call so async cancels work.
    val newConnection = RealConnection(connectionPool, route)
    call.connectionToCancel = newConnection
    try {
        newConnection.connect(
            connectTimeout,
            readTimeout,
            writeTimeout,
            pingIntervalMillis,
            connectionRetryEnabled,
            call,
            eventListener
        )
    } finally {
        call.connectionToCancel = null
    }
    call.client.routeDatabase.connected(newConnection.route())

    // 第五次,再次尝试从连接池中获取一个连接,带路由,带多路复用
    // 这一步主要是为了校验一下,比如已经有了一条连接了,就可以直接复用,而不用使用手动创建的连接
    // If we raced another call connecting to this host, coalesce the connections. This makes for 3
    // different lookups in the connection pool!
    if (connectionPool.callAcquirePooledConnection(address, call, routes, true)) {
        val result = call.connection!!
        nextRouteToTry = route
        newConnection.socket().closeQuietly()
        eventListener.connectionAcquired(call, result)
        return result
    }

    synchronized(newConnection) {
        // 将手动创建的新连接放入连接池
        connectionPool.put(newConnection)
        call.acquireConnectionNoEvents(newConnection)
    }

    eventListener.connectionAcquired(call, newConnection)
    return newConnection
}
  • 第一次,尝试重连 call 中的 connection,不需要去重新获取连接。
  • 第二次,尝试从连接池中获取一个连接,不带路由,不带多路复用。
  • 第三次,再次尝试从连接池中获取一个连接,带路由,不带多路复用。
  • 第四次,手动创建一个新连接。
  • 第五次,再次尝试从连接池中获取一个连接,带路由,带多路复用。

到这里,就算建立了连接

CallServerInterceptor

将请求头和请求体发送给服务器,并解析服务器返回的response

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

    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val realChain = chain as RealInterceptorChain
        val exchange = realChain.exchange!!
        val request = realChain.request
        val requestBody = request.body
        val sentRequestMillis = System.currentTimeMillis()

        var invokeStartEvent = true
        var responseBuilder: Response.Builder? = null
        var sendRequestException: IOException? = null
        try {
            // 写入请求头
            exchange.writeRequestHeaders(request)

            if (HttpMethod.permitsRequestBody(request.method) && requestBody != null) {
                // 当请求头为"Expect: 100-continue"时,在发送请求体之前需要等待服务器返回"HTTP/1.1 100 Continue" 的response,如果没有等到该response,就不发送请求体。
                // POST请求,先发送请求头,在获取到100继续状态后继续发送请求体

                // 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.
                if ("100-continue".equals(request.header("Expect"), ignoreCase = true)) {
                    // 刷新请求,即发送请求头
                    exchange.flushRequest()
                    // 解析响应头
                    responseBuilder = exchange.readResponseHeaders(expectContinue = true)
                    exchange.responseHeadersStart()
                    invokeStartEvent = false
                }
                // 写入请求体
                if (responseBuilder == null) {
                    if (requestBody.isDuplex()) {
                        // 准备一个双工体,以便应用程序稍后可以发送请求体。
                        // Prepare a duplex body so that the application can send a request body later.
                        exchange.flushRequest()
                        val bufferedRequestBody = exchange.createRequestBody(request, true).buffer()
                        // 写入请求体
                        requestBody.writeTo(bufferedRequestBody)
                    } else {
                        // 如果获取到了"Expect: 100-continue"响应,写入请求体
                        // Write the request body if the "Expect: 100-continue" expectation was met.
                        val bufferedRequestBody = exchange.createRequestBody(request, false).buffer()
                        requestBody.writeTo(bufferedRequestBody)
                        bufferedRequestBody.close()
                    }
                } else {
                    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 {
                exchange.noRequestBody()
            }

            if (requestBody == null || !requestBody.isDuplex()) {
                // 请求结束,发送请求体
                exchange.finishRequest()
            }
        } catch (e: IOException) {
            if (e is ConnectionShutdownException) {
                throw e // No request was sent so there's no response to read.
            }
            if (!exchange.hasFailure) {
                throw e // Don't attempt to read the response; we failed to send the request.
            }
            sendRequestException = e
        }

        try {
            if (responseBuilder == null) {
                // 读取相应头
                responseBuilder = exchange.readResponseHeaders(expectContinue = false)!!
                if (invokeStartEvent) {
                    exchange.responseHeadersStart()
                    invokeStartEvent = false
                }
            }
            // 构建一个response
            var response = responseBuilder
                .request(request)
                .handshake(exchange.connection.handshake())
                .sentRequestAtMillis(sentRequestMillis)
                .receivedResponseAtMillis(System.currentTimeMillis())
                .build()
            var code = response.code

            if (shouldIgnoreAndWaitForRealResponse(code)) {
                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)

            response = if (forWebSocket && code == 101) {
                // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
                response.newBuilder()
                    .body(EMPTY_RESPONSE)
                    .build()
            } else {
                response.newBuilder()
                    .body(exchange.openResponseBody(response))
                    .build()
            }
            if ("close".equals(response.request.header("Connection"), ignoreCase = true) ||
                    "close".equals(response.header("Connection"), ignoreCase = true)) {
                exchange.noNewExchangesOnConnection()
            }
            if ((code == 204 || code == 205) && response.body?.contentLength() ?: -1L > 0L) {
                throw ProtocolException(
                    "HTTP $code had non-zero Content-Length: ${response.body?.contentLength()}")
            }
            return response
        } catch (e: IOException) {
            if (sendRequestException != null) {
                sendRequestException.addSuppressed(e)
                throw sendRequestException
            }
            throw e
        }
    }

    private fun shouldIgnoreAndWaitForRealResponse(code: Int): Boolean = when {
        // Server sent a 100-continue even though we did not request one. Try again to read the
        // actual response status.
        code == 100 -> true

        // Handle Processing (102) & Early Hints (103) and any new codes without failing
        // 100 and 101 are the exceptions with different meanings
        // But Early Hints not currently exposed
        code in (102 until 200) -> true

        else -> false
    }
}

写入请求头,然后根据条件是否写入发送请求体,请求结束 解析服务器返回的响应头,然后构建一个新的Response,并返回 这里是拦截器责任链的最后一个拦截器,所以不会再调用chain.proceed 方法,而是直接将这个response往上传递。

以上就是所有的拦截器的源码解析。