OkHttp源码分析,基于OKHttp4.0版本

基本使用

okhttp是Square公司开源的一个非常便捷的轻量级第三方网络访问框架。它支持同步请求和异步请求。
Gradle依赖如下:

implementation 'com.squareup.okhttp3:okhttp:4.0.1'

异步请求

val url = "http://wwww.baidu.com"
val okHttpClient = OkHttpClient()
val request = Request.Builder()
    .url(url)
    .get()//默认就是GET请求
    .build()
val call = okHttpClient.newCall(request)
call.enqueue(object : Callback {
    override fun onFailure(call: Call, e: IOException) {
        Log.d(TAG, "onFailure: ");
    }

    override fun onResponse(call: Call, response: Response) {
        Log.d(TAG, "onResponse: " + response.body?.string())
    }
})

同步请求

val url = "http://wwww.baidu.com"
val okHttpClient = OkHttpClient()
val request = Request.Builder()
    .url(url)
    .get()
    .build()
val call = okHttpClient.newCall(request)
val result = call.execute()//会阻塞

源码分析

OkHttpClient的创建,调用的是Builder,我们看下Builder的初始化

internal var dispatcher: Dispatcher = Dispatcher()// 分发器
internal var connectionPool: ConnectionPool = ConnectionPool()//连接池
internal val interceptors: MutableList<Interceptor> = mutableListOf()// 拦截器
internal val networkInterceptors: MutableList<Interceptor> = mutableListOf()// 网络拦截器
internal var eventListenerFactory: EventListener.Factory = EventListener.NONE.asFactory()//监听器工厂
internal var retryOnConnectionFailure = true//连接失败是否重试
internal var authenticator: Authenticator = Authenticator.NONE//本地身份验证
internal var followRedirects = true//http是否重定向
internal var followSslRedirects = true//ssl是否支持重定向
internal var cookieJar: CookieJar = CookieJar.NO_COOKIES //Cookie
internal var cache: Cache? = null // 缓存
internal var dns: Dns = Dns.SYSTEM //域名解析
internal var proxy: Proxy? = null //代理
internal var proxySelector: ProxySelector = ProxySelector.getDefault() ?: NullProxySelector()// 代理选择器
internal var proxyAuthenticator: Authenticator = Authenticator.NONE //代理身份验证
internal var socketFactory: SocketFactory = SocketFactory.getDefault() //socket 工厂
internal var sslSocketFactoryOrNull: SSLSocketFactory? = null // sslsocket工厂 用于https
internal var connectionSpecs: List<ConnectionSpec> = DEFAULT_CONNECTION_SPECS// 传输层版本和连接协议 TLS等
internal var protocols: List<Protocol> = DEFAULT_PROTOCOLS// 支持的协议
internal var hostnameVerifier: HostnameVerifier = OkHostnameVerifier //用于确认主机名
internal var certificatePinner: CertificatePinner = CertificatePinner.DEFAULT //证书链
internal var certificateChainCleaner: CertificateChainCleaner? = null //证书确认
internal var callTimeout = 0 //调用超时时间
internal var connectTimeout = 10_000//连接超时时间
internal var readTimeout = 10_000 //读取超时时间
internal var writeTimeout = 10_000//写入超时时间
internal var pingInterval = 0 //// 长连接时命令间隔

Request的创建

open fun build(): Request {
  return Request(
      checkNotNull(url) { "url == null" },//请求地址
      method,//请求方法
      headers.build(),//请求头
      body,//请求体
      tags.toImmutableMap()
  )
}

Request的创建用了构造者模式来创建,Request主要是对请求参数的封装
Call的创建,通过okHttpClient#newCall创建call

override fun newCall(request: Request): Call {
  return RealCall.newRealCall(this, request, forWebSocket = false)
}
RealCall.kt
companion object {
  fun newRealCall(
    client: OkHttpClient,
    originalRequest: Request,
    forWebSocket: Boolean
  ): RealCall {
    // Safely publish the Call instance to the EventListener.
    return RealCall(client, originalRequest, forWebSocket).apply {
      transmitter = Transmitter(client, this)
    }
  }
}

RealCall是针对OkHttpClient和Request的封装。Call的具体实现就是在RealCall。
RealCall中还定义了OkHttp的拦截器链,具体的作用后面会讲到。
发起异步请求,调用call#enqueue。实际调用的是Call的实现类RealCall的enqueue。

override fun enqueue(responseCallback: Callback) {
  synchronized(this) {
    check(!executed) { "Already Executed" }
    executed = true
  }
  transmitter.callStart()
  client.dispatcher.enqueue(AsyncCall(responseCallback))//分发器进行分发
}

client.dispatcher就是Dispatcher分发器,异步调用它的enqueue。

internal fun enqueue(call: AsyncCall) {
  synchronized(this) {
    readyAsyncCalls.add(call)//将Call添加到异步准备队列
    ...
    if (!call.get().forWebSocket) {
      val existingCall = findExistingCallWithHost(call.host())
      if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
    }
  }
  promoteAndExecute()//发起请求
}

发起同步请求,调用call#executed。实际调用的是Call的实现类RealCall的executed。

  override fun execute(): Response {
    synchronized(this) {
      check(!executed) { "Already Executed" }
      executed = true
    }
    transmitter.timeoutEnter()
    transmitter.callStart()
    try {
      client.dispatcher.executed(this)
      return getResponseWithInterceptorChain()//进行同步请求。会block线程
    } finally {
      client.dispatcher.finished(this)
    }
  }

Dispatcher分析

//支持的最大并发请求数量
@get:Synchronized var maxRequests = 64
  set(maxRequests) {
    require(maxRequests >= 1) { "max < 1: $maxRequests" }
    synchronized(this) {
      field = maxRequests
    }
    promoteAndExecute()
  }
//每个主机的最大请求数量
@get:Synchronized var maxRequestsPerHost = 5
  set(maxRequestsPerHost) {
    require(maxRequestsPerHost >= 1) { "max < 1: $maxRequestsPerHost" }
    synchronized(this) {
      field = maxRequestsPerHost
    }
    promoteAndExecute()
  }
//请求线程池
@get:Synchronized
@get:JvmName("executorService") val executorService: ExecutorService
  get() {
    if (executorServiceOrNull == null) {
      executorServiceOrNull = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS,
          SynchronousQueue(), threadFactory("OkHttp Dispatcher", false))
    }
    return executorServiceOrNull!!
  }
//将要运行的异步请求队列
private val readyAsyncCalls = ArrayDeque<AsyncCall>()
//正在运行的异步请求队列
private val runningAsyncCalls = ArrayDeque<AsyncCall>()
//正在运行的同步请求队列
private val runningSyncCalls = ArrayDeque<RealCall>()

Dispatcher#promoteAndExecute

  private fun promoteAndExecute(): Boolean {
    assert(!Thread.holdsLock(this))
    val executableCalls = mutableListOf<AsyncCall>()
    val isRunning: Boolean
    synchronized(this) {
      val i = readyAsyncCalls.iterator()//将要运行的异步请求队列
      while (i.hasNext()) {//遍历
        val asyncCall = i.next()
        if (runningAsyncCalls.size >= this.maxRequests) break //超过了最大并发请求数则结束
        if (asyncCall.callsPerHost().get() >= this.maxRequestsPerHost) continue //找过了这个主机最大的连接数,遍历下一个
        i.remove()//将asyncCall从准备队列中移除
        asyncCall.callsPerHost().incrementAndGet()//主机连接数+1
        executableCalls.add(asyncCall)//执行请求的集合
        runningAsyncCalls.add(asyncCall)//将asyncCall添加到正在运行的队列
      }
      isRunning = runningCallsCount() > 0
    }

    for (i in 0 until executableCalls.size) {//遍历执行请求的集合
      val asyncCall = executableCalls[i]
      asyncCall.executeOn(executorService)//执行请求
    }
    return isRunning
  }

异步请求执行完之后会回调Dispatcher#finished,处理队列中的任务,如果没有任务可以处理那么空闲callback会回调

private fun <T> finished(calls: Deque<T>, call: T) {
  val idleCallback: Runnable?
  //省略部分代码
  val isRunning = promoteAndExecute()//进行任务处理
  if (!isRunning && idleCallback != null) {
    idleCallback.run()//回调空闲CalBack
  }
}

我们分析下AsyncCall,AsyncCall实现了Runnable接口。我们看下run方法

override fun run() {
  threadName("OkHttp ${redactedUrl()}") {
    var signalledCallback = false
    transmitter.timeoutEnter()
    try {
      val response = getResponseWithInterceptorChain()//得到拦截器链
      signalledCallback = true
      responseCallback.onResponse(this@RealCall, response)//返回结果回调
    } catch (e: IOException) {
      if (signalledCallback) {
        //省略部分代码
      } else {
        responseCallback.onFailure(this@RealCall, e)//异常回调
      }
    } finally {
      client.dispatcher.finished(this)//这里会调用Dispatcher的finished,继续处理队列其他的任务
    }
  }
}

Dispatcher中具体的开始任务是通过AsyncCall#executeOn,代码的核心是调用ExecutorService#execute,通过线程池发起异步请求

fun executeOn(executorService: ExecutorService) {
  //省略部分代码
  try {
    executorService.execute(this)//发起异步请求
    success = true
  } catch (e: RejectedExecutionException) {
    //省略部分代码
    responseCallback.onFailure(this@RealCall, ioException)
  } finally {
    if (!success) {
      client.dispatcher.finished(this) // 异常情况,回调finished
    }
  }
}

下面我们分析RealCall#getResponseWithInterceptorChain

fun getResponseWithInterceptorChain(): Response {
  // Build a full stack of interceptors.
  val interceptors = mutableListOf<Interceptor>()
  interceptors += client.interceptors//自定义的拦截器
  interceptors += RetryAndFollowUpInterceptor(client)//重定向拦截器
  interceptors += BridgeInterceptor(client.cookieJar)//桥拦截器
  interceptors += CacheInterceptor(client.cache)//缓存连接器
  interceptors += ConnectInterceptor//连接拦截器
  if (!forWebSocket) {
    interceptors += client.networkInterceptors//自定义的网络拦截器
  }
  interceptors += CallServerInterceptor(forWebSocket)//请求服务器拦截器
  val chain = RealInterceptorChain(interceptors, transmitter, null, 0, originalRequest, this,
      client.connectTimeoutMillis, client.readTimeoutMillis, client.writeTimeoutMillis)//得到拦截器链
  var calledNoMoreExchanges = false
  try {
    val response = chain.proceed(originalRequest)//进行任务处理,开始链式调用
    if (transmitter.isCanceled) {
      response.closeQuietly()
      throw IOException("Canceled")
    }
    return response
  } catch (e: IOException) {
    calledNoMoreExchanges = true
    throw transmitter.noMoreExchanges(e) as Throwable
  } finally {
    if (!calledNoMoreExchanges) {
      transmitter.noMoreExchanges(null)
    }
  }
}

RealInterceptorChain实现了Interceptor.Chain

  interface Chain {
    fun request(): Request
    @Throws(IOException::class)
    fun proceed(request: Request): Response
    fun connection(): Connection?
    fun call(): Call
    fun connectTimeoutMillis(): Int
    fun withConnectTimeout(timeout: Int, unit: TimeUnit): Chain
    fun readTimeoutMillis(): Int
    fun withReadTimeout(timeout: Int, unit: TimeUnit): Chain
    fun writeTimeoutMillis(): Int
    fun withWriteTimeout(timeout: Int, unit: TimeUnit): Chain
  }

核心的处理逻辑是process,简化后的代码如下

  @Throws(IOException::class)
  fun proceed(request: Request, transmitter: Transmitter, exchange: Exchange?): Response {
    if (index >= interceptors.size) throw AssertionError()
    calls++
    val next = RealInterceptorChain(interceptors, transmitter, exchange,
        index + 1, request, call, connectTimeout, readTimeout, writeTimeout)//创建新的拦截链,链中的拦截器集合index+1
    val interceptor = interceptors[index]得到下一个拦截器
    @Suppress("USELESS_ELVIS")
    val response = interceptor.intercept(next) ?: throw NullPointerException(//执行Interceptor#intercept
        "interceptor $interceptor returned null")
    return response
  }

每当我们调用process的时候都会调用拦截链的下一个Interceptor。这里用的是责任链模式。
下面我们分析下具体的拦截器
RetryAndFollowUpInterceptor的作用进行连接失败重新连接,以及重定向

  override fun intercept(chain: Interceptor.Chain): Response {
    var request = chain.request()
    val realChain = chain as RealInterceptorChain
    val transmitter = realChain.transmitter()
    var followUpCount = 0
    var priorResponse: Response? = null
    while (true) {
      transmitter.prepareToConnect(request)
      if (transmitter.isCanceled) {
        throw IOException("Canceled")
      }
      var response: Response
      var success = false
      try {
        response = realChain.proceed(request, transmitter, null)//处理下一个Intercepter
        success = true
      } catch (e: RouteException) {
        //尝试通过路由进行连接失败。该请求不会被发送
        if (!recover(e.lastConnectException, transmitter, false, request)) {
          throw e.firstConnectException
        }
        continue
      } catch (e: IOException) {
       //尝试与服务器通信失败。 该请求可能已发送
        val requestSendStarted = e !is ConnectionShutdownException
        if (!recover(e, transmitter, requestSendStarted, request)) throw e
        continue
      } finally {
      }
      if (priorResponse != null) {
        response = response.newBuilder()//创建一个响应体为空的Response
            .priorResponse(priorResponse.newBuilder()
                .body(null)
                .build())
            .build()
      }

      val exchange = response.exchange
      val route = exchange?.connection()?.route()
      val followUp = followUpRequest(response, route)//重定向,如果不为空则返回重定向的Request

      if (followUp == null) {//不需要重定向,直接返回response
        if (exchange != null && exchange.isDuplex) {
          transmitter.timeoutEarlyExit()
        }
        return response
      }

      val followUpBody = followUp.body
      if (followUpBody != null && followUpBody.isOneShot()) {
        return response
      }

      response.body?.closeQuietly()
      if (transmitter.hasExchange()) {
        exchange?.detachWithViolence()
      }

      if (++followUpCount > MAX_FOLLOW_UPS) {//超过了最大的重定向次数会抛出异常,这里MAX_FOLLOW_UPS是20
        throw ProtocolException("Too many follow-up requests: $followUpCount")
      }

      request = followUp//把重定向的请求赋值给request,以便再次进入循环执行
      priorResponse = response
    }
  }

followUpRequest如果有重定向拿到重定向的request否则返回null,根据响应码分别进行处理请求

  private fun followUpRequest(userResponse: Response, route: Route?): Request? {
    val responseCode = userResponse.code

    val method = userResponse.request.method
    when (responseCode) {
      HTTP_PROXY_AUTH -> { //407 代理认证
        val selectedProxy = route!!.proxy
        if (selectedProxy.type() != Proxy.Type.HTTP) {
          throw ProtocolException("Received HTTP_PROXY_AUTH (407) code while not using proxy")
        }
        return client.proxyAuthenticator.authenticate(route, userResponse)
      }

      HTTP_UNAUTHORIZED -> return client.authenticator.authenticate(route, userResponse)//401未经过认证

      HTTP_PERM_REDIRECT//308, HTTP_TEMP_REDIRECT //307-> {
        //如果收到307或308状态代码以响应GET或HEAD以外的请求,则用户代理不得自动重定向请求
        if (method != "GET" && method != "HEAD") {
          return null
        }
        return buildRedirectRequest(userResponse, method)
      }
      HTTP_MULT_CHOICE//300, HTTP_MOVED_PERM//301, HTTP_MOVED_TEMP//302, HTTP_SEE_OTHER//303 -> {
        return buildRedirectRequest(userResponse, method)
      }
      HTTP_CLIENT_TIMEOUT -> {//408 超时
        // 408's are rare in practice, but some servers like HAProxy use this response code. The
        // spec says that we may repeat the request without modifications. Modern browsers also
        // repeat the request (even non-idempotent ones.)
        if (!client.retryOnConnectionFailure) {
          // The application layer has directed us not to retry the request.
          //应用程序层指示我们不要重试请求
          return null
        }
        val requestBody = userResponse.request.body
        if (requestBody != null && requestBody.isOneShot()) {
          return null
        }
        val priorResponse = userResponse.priorResponse
        if (priorResponse != null && priorResponse.code == HTTP_CLIENT_TIMEOUT) {
          // We attempted to retry and got another timeout. Give up.
          return null
        }

        if (retryAfter(userResponse, 0) > 0) {
          return null
        }

        return userResponse.request
      }
      HTTP_UNAVAILABLE -> {//503
        val priorResponse = userResponse.priorResponse
        if (priorResponse != null && priorResponse.code == HTTP_UNAVAILABLE) {
          // 我们试图重试并再次超时。 放弃
          return null
        }
        if (retryAfter(userResponse, Integer.MAX_VALUE) == 0) {
          // 收到指示,立即重试
          return userResponse.request
        }
        return null
      }
      else -> return null
    }
  }

BridgeInterceptor的作用是对请求头和响应头进行处理

  override fun intercept(chain: Interceptor.Chain): Response {
    val userRequest = chain.request()
    val requestBuilder = userRequest.newBuilder()
    val body = userRequest.body
    if (body != null) {
      //处理响应头
      val contentType = body.contentType()
      if (contentType != null) {
        requestBuilder.header("Content-Type", contentType.toString())//增加Content-Type
      }
      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())//增加Host
    }
    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")//添加gzip压缩支持
    }
    val cookies = cookieJar.loadForRequest(userRequest.url)//处理Cookie
    if (cookies.isNotEmpty()) {
      requestBuilder.header("Cookie", cookieHeader(cookies))
    }
    if (userRequest.header("User-Agent") == null) {
      requestBuilder.header("User-Agent", userAgent)增加User-Agent
    }
    val networkResponse = chain.proceed(requestBuilder.build())//执行下一个Intercepter
    cookieJar.receiveHeaders(userRequest.url, networkResponse.headers)//处理Cookie

    val responseBuilder = networkResponse.newBuilder()
        .request(userRequest)
    //gzip解压处理
    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()
        responseBuilder.headers(strippedHeaders)
        val contentType = networkResponse.header("Content-Type")
        responseBuilder.body(RealResponseBody(contentType, -1L, gzipSource.buffer()))
      }
    }
    return responseBuilder.build()
  }

CacheInterceptor的作用是读取缓存和更新缓存的操作

  override fun intercept(chain: Interceptor.Chain): Response {
    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)

    if (cacheCandidate != null && cacheResponse == null) {
      // 缓存不可用,将它关闭
      cacheCandidate.body?.closeQuietly()
    }
    // 不使用网络,又没有缓存的直接报错,并创建返回的Response错误码是504
    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()
    }

    // 如果没有网络,则使用缓存
    if (networkRequest == null) {
      return cacheResponse!!.newBuilder()
          .cacheResponse(stripBody(cacheResponse))
          .build()
    }
    var networkResponse: Response? = null
    try {
      networkResponse = chain.proceed(networkRequest)//进行下一个Intercepter
    } finally {
      if (networkResponse == null && cacheCandidate != null) {
        cacheCandidate.body?.closeQuietly()
      }
    }
    if (cacheResponse != null) {
      if (networkResponse?.code == HTTP_NOT_MODIFIED) {//如果返回的是304,直接返回缓存
        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()
        cache!!.trackConditionalCacheHit()
        cache.update(cacheResponse, response)
        return response
      } else {
        cacheResponse.body?.closeQuietly()
      }
    }
    //使用网络请求
    val response = networkResponse!!.newBuilder()
        .cacheResponse(stripBody(cacheResponse))
        .networkResponse(stripBody(networkResponse))
        .build()

    if (cache != null) {
      if (response.promisesBody() && CacheStrategy.isCacheable(response, networkRequest)) {
        // Offer this request to the cache.
        val cacheRequest = cache.put(response)//更新缓存
        return cacheWritingResponse(cacheRequest, response)
      }
        //PATCH、PUT、DELETE、MOVE不需要缓存
      if (HttpMethod.invalidatesCache(networkRequest.method)) {
        try {
          cache.remove(networkRequest)
        } catch (_: IOException) {
          // The cache cannot be written.
        }
      }
    }
    return response
  }

ConnectInterceptor的作用与服务器进行连接

  override fun intercept(chain: Interceptor.Chain): Response {
    val realChain = chain as RealInterceptorChain
    val request = realChain.request() //得到Request
    val transmitter = realChain.transmitter()
    val doExtensiveHealthChecks = request.method != "GET"
    val exchange = transmitter.newExchange(chain, doExtensiveHealthChecks)//创建socket进行连接
    return realChain.proceed(request, transmitter, exchange)
  }

OkHttp创建网络连接的时序图如下:


OkHttp时序图

CallServerInterceptor的作用是发送请求和接收数据

  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()

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

    var responseHeadersStarted = false
    var responseBuilder: Response.Builder? = null
    if (HttpMethod.permitsRequestBody(request.method) && requestBody != null) {
        //如果请求中存在“Expect:100-continue”标头,请在发送请求主体之前等待“HTTP / 1.1 100 Continue”响应。
        // 如果我们没有得到,请返回我们得到的内容(例如4xx响应),而不发送请求主体。
      if ("100-continue".equals(request.header("Expect"), ignoreCase = true)) {
        exchange.flushRequest()
        responseHeadersStarted = true
        exchange.responseHeadersStart()
        responseBuilder = exchange.readResponseHeaders(true)
      }
      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 {
          // 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()
    }
    if (!responseHeadersStarted) {
      exchange.responseHeadersStart()
    }
    if (responseBuilder == null) {
      responseBuilder = exchange.readResponseHeaders(false)!!//读取响应头
    }
    var response = responseBuilder
        .request(request)
        .handshake(exchange.connection()!!.handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build()
    //读取响应体
    var code = response.code
    if (code == 100) {
      //即使我们没有请求,但是服务器发送了100-continue。
      //再次尝试读取实际的回复
      response = exchange.readResponseHeaders(false)!!
          .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
  }

总结下,OkHttp网络拦截链在Intercepter的process之前是处理Request,在process是对Response处理。
整理的流程图如下:

OkHttp拦截链

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容

  • OkHttp源码的samples的简单使用的示例: public static void main(String....
    _warren阅读 720评论 0 1
  • OkHttp源码分析 在现在的Android开发中,请求网络获取数据基本上成了我们的标配。在早期的Android开...
    BlackFlag阅读 323评论 0 5
  • 前几天在在一本书上看到这样一句话 如果仅从微观的视角关注每一个单独的点,可能会因为看不到整体而迷失方向。 所以不会...
    Utte阅读 668评论 0 0
  • 前言 用OkHttp很久了,也看了很多人写的源码分析,在这里结合自己的感悟,记录一下对OkHttp源码理解的几点心...
    Java小铺阅读 1,488评论 0 13
  • 前几日在学习的时候听到了一个故事,我想分享一下这个故事以及故事本身带给我的思考。 前些日子,乔尔的大女儿跟乔尔打电...
    语修阅读 392评论 0 1