OkHttp源码解析(三)请求响应转换
BridgeInterceptor-> intercept
@Override public Response intercept(Chain chain) throws IOException {
Request userRequest = chain.request();
// 构建一个新的Builder
Request.Builder requestBuilder = userRequest.newBuilder();
RequestBody body = userRequest.body();
if (body != null) {
MediaType contentType = body.contentType();
if (contentType != null) {
// 把ContentType这个枚举转换为String
requestBuilder.header("Content-Type", contentType.toString());
}
long contentLength = body.contentLength();
if (contentLength != -1) {
// ContentLength转换为String
requestBuilder.header("Content-Length", Long.toString(contentLength));
requestBuilder.removeHeader("Transfer-Encoding");
} else {
requestBuilder.header("Transfer-Encoding", "chunked");
requestBuilder.removeHeader("Content-Length");
}
}
if (userRequest.header("Host") == null) {
requestBuilder.header("Host", hostHeader(userRequest.url(), false));
}
if (userRequest.header("Connection") == null) {
requestBuilder.header("Connection", "Keep-Alive");
}
// 如果还没设置Accept-Encoding,自动设置gzip
boolean transparentGzip = false;
if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
transparentGzip = true;
requestBuilder.header("Accept-Encoding", "gzip");
}
// 把原请求中的cookie设置到新的builder中
List<Cookie> cookies = cookieJar.loadForRequest(userRequest.url());
if (!cookies.isEmpty()) {
// 把Cookie转换成String
requestBuilder.header("Cookie", cookieHeader(cookies));
}
if (userRequest.header("User-Agent") == null) {
requestBuilder.header("User-Agent", Version.userAgent());
}
// 从下层拿到Response
Response networkResponse = chain.proceed(requestBuilder.build());
HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());
// 构建一个新的Response用做转换,理所当然的把request设置为转换前的Request
Response.Builder responseBuilder = networkResponse.newBuilder()
.request(userRequest);
// 如果设置了Gzip压缩,则要进行Gzip解压
if (transparentGzip
&& "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
&& HttpHeaders.hasBody(networkResponse)) {
GzipSource responseBody = new GzipSource(networkResponse.body().source());
Headers strippedHeaders = networkResponse.headers().newBuilder()
.removeAll("Content-Encoding")
.removeAll("Content-Length")
.build();
responseBuilder.headers(strippedHeaders);
String contentType = networkResponse.header("Content-Type");
responseBuilder.body(new RealResponseBody(contentType, -1L, Okio.buffer(responseBody)));
}
return responseBuilder.build();
}
将用户构建的Request请求转化为一个能够进行网络传输的请求,所以这里需要枚举、long向String的转换
将Request交给下一个拦截器,然后拿到一个Response
然后最后就是将网络请求可用的Response转换为用户可用的Response
这是因为调用的时候构建一个Request,只是简单把url、参数设置进来,但是实际上,实际做网络传输还需要其他的一些请求头:
- Content-Type:网络请求类型
- Content-Length:请求体内容的长度,与 Transfer-Encoding互斥
- Transfer-Encoding: 值为 chunked 表示请求体的内容大小是未知的,与 Content-Length 互斥
- Host: 请求的 url 的主机
- Connection: 默认就是 Keep-Alive,就是一个 TCP 连接之后不会关闭,保持连接状态
- Accept-Encoding: 默认是 gzip,告诉服务器客户端支持 gzip 编码的响应
- Cookie: 当请求设置了 Cookie 那么就是添加 Cookie 这个请求头
- User-Agent: 根据 OkHTTP 的版本来返回