When using the OkHttp network framework to make network requests, we will find that there will be several additional parameters in the request header sent to the background than we added ourselves. Check the source code and you will find
private Response getResponseWithInterceptorChain() throws IOException { // Build a full stack of interceptors. List<Interceptor> interceptors = new ArrayList<>(); interceptors.addAll(client.interceptors()); interceptors.add(retryAndFollowUpInterceptor); interceptors.add(new BridgeInterceptor(client.cookieJar())); interceptors.add(new CacheInterceptor(client.internalCache())); interceptors.add(new ConnectInterceptor(client)); if (!retryAndFollowUpInterceptor.isForWebSocket()) { interceptors.addAll(client.networkInterceptors()); } interceptors.add(new CallServerInterceptor( retryAndFollowUpInterceptor.isForWebSocket())); Interceptor.Chain chain = new RealInterceptorChain( interceptors, null, null, null, 0, originalRequest); return chain.proceed(originalRequest); }
OkHttp will add a BridgeInterceptor by default, and check the source code of BridgeInterceptor
MediaType contentType = body.contentType(); if (contentType != null) { requestBuilder.header("Content-Type", contentType.toString()); } long contentLength = body.contentLength(); if (contentLength != -1) { 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"); } // If we add an "Accept-Encoding: gzip" header field we're responsible for also decompressing // the transfer stream. boolean transparentGzip = false; if (userRequest.header("Accept-Encoding") == null) { transparentGzip = true; requestBuilder.header("Accept-Encoding", "gzip"); } List<Cookie> cookies = cookieJar.loadForRequest(userRequest.url()); if (!cookies.isEmpty()) { requestBuilder.header("Cookie", cookieHeader(cookies)); } if (userRequest.header("User-Agent") == null) { requestBuilder.header("User-Agent", Version.userAgent()); }
User agent, accept encoding and other request header parameters will be added by default in BridgeInterceptor. Sometimes we don't need these added parameters by default, so how can we remove them?
Through part of the source code in the first paragraph above
interceptors.add(retryAndFollowUpInterceptor); interceptors.add(new BridgeInterceptor(client.cookieJar())); interceptors.add(new CacheInterceptor(client.internalCache())); interceptors.add(new ConnectInterceptor(client)); if (!retryAndFollowUpInterceptor.isForWebSocket()) { interceptors.addAll(client.networkInterceptors()); }
We can see that the network interceptors are added only after the bridgeinterceptors are added in OkHttp, so we need to use the network interceptor to intercept the request headers again and operate the header parameters.
First, we need to customize an interceptor to remove parameters we don't need in the interceptor.
public class NetInterceptorimplements Interceptor { private HttpClient builder; public NetInterceptor() { super(); } public NetInterceptor(HttpClient builder) { this.builder = builder; } @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); //Remove header parameters request = request.newBuilder() .removeHeader("User-Agent") .removeHeader("Accept-Encoding") .build(); Response response = chain.proceed(request); if (response.body() != null && response.body().contentType() != null) { MediaType mediaType = response.body().contentType(); String content = response.body().string(); ResponseBody responseBody = ResponseBody.create(mediaType, content); return response.newBuilder().body(responseBody).build(); } else { return response; } } }
Then set the custom interceptor as a network interceptor
mOkBuilder = new Builder() .connectTimeout(mbuilder.getConnectTimeout(), TimeUnit.SECONDS) .readTimeout(mbuilder.getReadTimeout(), TimeUnit.SECONDS) .writeTimeout(mbuilder.getWriteTimeout(), TimeUnit.SECONDS) .sslSocketFactory(createSSLSocketFactory(), new TrustAllCerts())// Trust all certificates .hostnameVerifier(new TrustAllHostnameVerifier()) .cookieJar(new CookieJar() { private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>(); @Override public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) { cookieStore.put(httpUrl.host(), list); } @Override public List<Cookie> loadForRequest(HttpUrl httpUrl) { List<Cookie> cookies = cookieStore.get(httpUrl.host()); return cookies != null ? cookies : new ArrayList<Cookie>(); } }); NetInterceptor netInterceptor = new NetInterceptor(mbuilder); //mOkBuilder.addNetworkInterceptor(netInterceptor); / / setting the application interceptor is invalid because the BridgeInterceptor was added after the interceptor was applied mOkBuilder.addNetworkInterceptor(netInterceptor);
In this way, the request header parameters automatically added by BridgeInterceptor can be removed.