继续上一篇文章,我们看BridgeInterceptor这个拦截器的具体工作内容
目录
BridgeInterceptor类的注释
/**
* Bridges from application code to network code. First it builds a network request from a user
* request. Then it proceeds to call the network. Finally it builds a user response from the network
* response.
*/
翻译过来,大意是说:这个BridgeInterceptor是从应用程序代码到网络代码的桥梁。首先它构建一个来自用户的网络请求,然后它继续调用网络。最后,它从网络构建用户响应
这样就清楚了,他的核心就是构建网络请求
BridgeInterceptor的代码解析
@Throws(IOException::class)
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())
}
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())
}
//默认是Keep-Alive
if (userRequest.header("Connection") == null) {
requestBuilder.header("Connection", "Keep-Alive")
}
// If we add an "Accept-Encoding: gzip" header field we're responsible for also decompressing
// the transfer stream.
var transparentGzip = false
//默认支持gzip编码压缩
if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
//支持gzip的标识位
transparentGzip = true
requestBuilder.header("Accept-Encoding", "gzip")
}
//添加cookie
val cookies = cookieJar.loadForRequest(userRequest.url)
if (cookies.isNotEmpty()) {
requestBuilder.header("Cookie", cookieHeader(cookies))
}
if (userRequest.header("User-Agent") == null) {
requestBuilder.header("User-Agent", userAgent)
}
//发送请求,获得服务响应
val networkResponse = chain.proceed(requestBuilder.build())
//接受服务端返回cookie
cookieJar.receiveHeaders(userRequest.url, networkResponse.headers)
val responseBuilder = networkResponse.newBuilder()
.request(userRequest)
//如果服务返回Content-Encoding带有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()))
}
}
//构建response
return responseBuilder.build()
}
核心部分已经注释,可以看出BridgeInterceptor核心做了三件事,
- 首先,通过requestBuilder构建请求,添加各种请求头信息
- 之后,将构建的请求发送出去,获得响应
- 最后,将获得到的响应数据做转换用户可以用的response
至于里面的涉及到的请求头“Content-Type”,"Content-Length","Transfer-Encoding"等等自行了解即可
关于Cookie的设置
这里面多提一下Cookie,它是添加到请求头里面,主要作用是客户端存储访问服务器的一些信息,这些信息的作用,可以根据具体业务来设置。OkHttp默认是不保存cookie的,需要做单独设置
private final HashMap<String, List<Cookie>> cookieMap = new HashMap<>();
OkHttpClient okHttpClient = new OkHttpClient.Builder().cookieJar(new CookieJar() {
@Override
public void saveFromResponse(@NotNull HttpUrl httpUrl, @NotNull List<Cookie> list) {
cookieMap.put(httpUrl.host(), list);
}
@Override
public List<Cookie> loadForRequest(@NotNull HttpUrl httpUrl) {
List<Cookie> cookies = cookieMap.get(httpUrl.host());
return cookies != null ? cookies : new ArrayList<>();
}
}).build();
整体来看BridgeInterceptor做的事情比较简单,就分析到这里