概念 责任链模式(Chain of Responsibility Pattern),包含命令对象和一系列实现了相同接口的处理对象,这些处理对象相互连接成为一条责任链。每一个处理对象能决定它能处理哪些命令对象,对于它不能处理的命令对象,将会传递给该链中的下一个处理对象。负责链模式就是对这种顺序处理事件的行为的抽象,通过接口来定义处理事件的方法,顺序分发/处理事件。
class RealInterceptorChain( private val interceptors: List<Interceptor>, // 拦截器,处理对象 private val transmitter: Transmitter, // 发射机 private val exchange: Exchange?, // 交换器 请求和响应 private val index: Int, private val request: Request, // 请求 private val call: Call, // 一次请求和返回封装 private val connectTimeout: Int, private val readTimeout: Int, private val writeTimeout: Int ) : Interceptor.Chain { ...
private fun buildRedirectRequest(userResponse: Response, method: String): Request? { // 设置不需要执行重定向 if (!client.followRedirects) return null // location header 是否支持 val location = userResponse.header("Location") ?: return null // Don't follow redirects to unsupported protocols. val url = userResponse.request.url.resolve(location) ?: return null
// 如果不允许SSL和Non-SSL之间的重定向,则返回null val sameScheme = url.scheme == userResponse.request.url.scheme if (!sameScheme && !client.followSslRedirects) return null
// Most redirects don't include a request body. val requestBuilder = userResponse.request.newBuilder() if (HttpMethod.permitsRequestBody(method)) { val maintainBody = HttpMethod.redirectsWithBody(method) if (HttpMethod.redirectsToGet(method)) { requestBuilder.method("GET", null) } else { val requestBody = if (maintainBody) userResponse.request.body else null requestBuilder.method(method, requestBody) } if (!maintainBody) { requestBuilder.removeHeader("Transfer-Encoding") requestBuilder.removeHeader("Content-Length") requestBuilder.removeHeader("Content-Type") } }
// When redirecting across hosts, drop all authentication headers. This // is potentially annoying to the application layer since they have no // way to retain them. if (!userResponse.request.url.canReuseConnectionFor(url)) { requestBuilder.removeHeader("Authorization") } // 构建 新的请求 return requestBuilder.url(url).build() }
class BridgeInterceptor(private val cookieJar: CookieJar) : Interceptor {
@Throws(IOException::class) override fun intercept(chain: Interceptor.Chain): Response { val userRequest = chain.request() val requestBuilder = userRequest.newBuilder() // 将userRequest中的属性设置到request中 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") }
// 如果没有设置Accept-Encoding,则自动设置为gzip var transparentGzip = false if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) { transparentGzip = true requestBuilder.header("Accept-Encoding", "gzip") } // 将userRequest中的cookie解析出来并设置到Request中的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) } // 顺序执行处理方法 val networkResponse = chain.proceed(requestBuilder.build())