Interceptors
Interceptors (interceptors) are a powerful way to monitor, overwrite, and retry HTTP access. Below is a simple interceptor that logs a log of requests and incoming responses to outflows.
Class Logginginterceptor implements Interceptor {
@Override public Response intercept (Chain Chain) throws IOException {
Request request = Chain.request ();
Long T1 = System.nanotime ();
Logger.info (String.Format ("Sending request%s on%s%n%s", Request.url (), Chain.connection (), Request.headers ())
;
Response Response = chain.proceed (request);
Long t2 = System.nanotime ();
Logger.info (String.Format ("Received response for%s in%.1fms%n%s",
response.request (). URL (), (T2-T1)/1e6d, RESPO Nse.headers ()));
return response
}
}
In the interceptor implementation, a call to Chain.proceed (request) is a critical step. This seemingly simple approach is where HTTP work actually happens, producing a response that satisfies the request.
Multiple interceptors can be linked together. If you have a compression interceptor and a sum checker: you will need to decide whether the data is compressed and then summed, or you can sum the checksum and then compress it first. Okhttp uses lists to track interceptors, and multiple interceptors are ordered calls.
Application Interceptors
Interceptors are registered as application (application) interceptors or network (network) interceptors. We will use the Logginginterceptor defined above to show the difference between the two.
To register the application interceptor, call the Add () method on the list returned by the Okhttpclient.interceptors () method:
Okhttpclient client = new Okhttpclient ();
Client.interceptors (). Add (New Logginginterceptor ());
Request Request = new Request.builder ()
. URL ("Http://www.publicobject.com/helloworld.txt")
. Header (" User-agent "," Okhttp Example ")
. Build ();
Response Response = client.newcall (Request). Execute ();
Response.body (). Close ();
Urlhttp://www.publicobject.com/helloworld.txt redirects to Https://publicobject.com/helloworld.txt in the code, Okhttp automatically follows this redirection. Our application interceptor is invoked once, and the response returned by Method Chain.proceed () is the response after redirection:
info:sending request http://www.publicobject.com/helloworld.txt on null
user-agent:okhttp Example
INFO: Received response for Https://publicobject.com/helloworld.txt in 1179.7ms
server:nginx/1.4.6 (Ubuntu)
Content-type:text/plain
content-length:1759
connection:keep-alive
We can see that access is redirected by Response.request (). URL () and Request.url (). The two log statements record two different URLs. Network Interceptors
The method for registering a network interceptor is similar. Add interceptors to the networkinterceptors () list, replacing the interceptors () list:
Okhttpclient client = new Okhttpclient ();
Client.networkinterceptors (). Add (New Logginginterceptor ());
Request Request = new Request.builder ()
. URL ("Http://www.publicobject.com/helloworld.txt")
. Header (" User-agent "," Okhttp Example ")
. Build ();
Response Response = client.newcall (Request). Execute ();
Response.body (). Close ();
When we run this piece of code, the interceptor executes two times. One is the initial to Http://www.publicobject.com/helloworld.txt request, and the other is the request redirected to Https://publicobject.com/helloworld.txt.
info:sending request Http://www.publicobject.com/helloworld.txt on connection{www.publicobject.com:80, proxy= DIRECT hostaddress=54.187.32.157 ciphersuite=none protocol=http/1.1} user-agent:okhttp Example Host: www.publicobject.com connection:keep-alive accept-encoding:gzip info:received response for http://
Www.publicobject.com/helloworld.txt in 115.6ms server:nginx/1.4.6 (Ubuntu) content-type:text/html content-length:193 Connection:keep-alive location:https://publicobject.com/helloworld.txt info:sending Request https:// Publicobject.com/helloworld.txt on connection{publicobject.com:443, Proxy=direct hostaddress=54.187.32.157
Ciphersuite=tls_ecdhe_rsa_with_aes_256_cbc_sha protocol=http/1.1} user-agent:okhttp Example Host:publicobject.com Connection:keep-alive accept-encoding:gzip info:received response for Https://publicobject.com/helloworld.txt in 80.9 Ms server:nginx/1.4.6 (Ubuntu) content-type:text/plain content-length:1759 connection:keep-alive
The above network request also contains more data, such as the request header Accept-encoding:gzip added by Okhttp, which supports compression of the response. The network interceptor chain has a non-empty connection that asks us for the IP address and TLS configuration used to connect to the Web server. Select Application Interceptor or Network interceptor
The two interceptor chains have their own comparative advantages.
application interceptors do not have to worry about the response of the intermediate process, such as redirection and retry. Always call once, even if the HTTP response comes from the cache. Observe the application of the original intention. Do not focus on the header information injected by okhttp, such as If-none-match. Allow short circuit, do not call Chain.proceed (). Allow Retry, call Chain.proceed () multiple times.
Network interceptors can manipulate intermediate responses, such as redirection and retry. When a network short-circuit cache response occurs, it is not invoked. Observe the data that will be transmitted over the network. Connection can be obtained to carry the request. Overwrite Request
Interceptors can be added, removed, or replaced with a request header. They can also change the request body. For example, if you are connected to a Web server that supports, you can compress the request body with an application interceptor.
/** This interceptor compresses is the HTTP request body. Many webservers can ' t handle this! * Final class Gziprequestinterceptor implements interceptor {@Override public Response intercept (Chain Chain) throws I
oexception {Request originalrequest = Chain.request (); if (originalrequest.body () = null | | Originalrequest.header ("content-encoding")!= null) {return chain.proceed (ori
Ginalrequest); Request compressedrequest = Originalrequest.newbuilder (). Header ("content-encoding", "gzip"). Metho
D (Originalrequest.method (), Gzip (Originalrequest.body ()). build ();
Return Chain.proceed (compressedrequest); Private Requestbody gzip (final requestbody body) {return new Requestbody () {@Override Public mediatype Co
Ntenttype () {return body.contenttype ();
@Override public Long ContentLength () {return-1;//We don ' t know the compressed length in advance! @Override public void Writeto (Bufferedsink sink) throws IOException {Bufferedsink Gzipsink = Okio.buffer (new Gzipsink (sink));
Body.writeto (Gzipsink);
Gzipsink.close ();
}
}; }
}
Overwrite Response
Accordingly, the interceptor can also overwrite the response head and change the response body. This is generally more dangerous than overwriting a request header because it may violate the expectations of the Web server.
If you are in a delicate situation and are ready to deal with the consequences, rewriting the response header is a powerful way to solve the problem. For example, you can fix a server incorrectly configured cache control response header to optimize the caching of responses.
/** Dangerous interceptor that rewrites the server ' s Cache-control header. *
private static final Interceptor Rewrite_cache_control_interceptor = new Interceptor () {
@Override public Response Intercept (Chain Chain) throws IOException {Response Originalresponse
= Chain.proceed (Chain.request ());
Return Originalresponse.newbuilder ()
. Header ("Cache-control", "max-age=60")
. Build ();
}
;
In general, this approach is most useful when updating the appropriate server problem fixes. Availability of
The Okhttp interceptor requires more than 2.2 versions. Unfortunately, interceptors are invalid for okurlfactory, and any libraries that rely on okurlfactory, contain retrofit 1.8 below and Picasso version 2.4 below.