Soulesidibe     About     Feed

OkHttp interceptors

Today, I’ll talk about an issue you probably encountered if you’re an android dev and deal with an API. Imagine that you have a huge app, fully connected where you fetch data from the server all over the place. The app is working quite nicely. The backend developer comes to you and tell you that you have to re-implement the new version of the API. Every endpoints of that app you have implemented for months should be updated. WTH!
Fortunatly you were using, from the begenning, this awesome rest client called Retrofit. And being a good programmer, you hear somewhere about okhttp interceptors.

Retro what?

Retrofit turns your HTTP API into a Java interface. This is exactly the main purpose of the library. With some “magic” (code generation at compile time I guess), you can have your app ready to talk to your server just by creating an java interface and within it, the definition of your endpoints.

public interface GitHubService {
 	@GET("users/{user}/repos")
 	Call<List<Repo>> listRepos(@Path("user") String user);
}  

In this example above, we tell retrofit to request an http GET to http://URL/users/{user}/repos. {user} wil be replaced by the listRepos() method parameter user. I don’t want to dive into retrofit mechanism but this is just awesome and a very concise way to decribe the server api. Retrofit use OkHttp as the default http client. As mentionned, retrofit is not an http client. It just eases the creation of an rest client for java based apps.

Interceptors

Interceptors is a feature provided by OkHttp. Before explaining what it does, check this picture below.

interceptors

As you can see it, interceptors allow you to add behaviors just before sending your request to the network and before handling the server response. We are talking about network interceptors.
This is very handy if you want to add header parameters or enhance your request with some common informations such as an api key, a token and so forth.

How it works?

First, you have to implement the Interceptor interface.

public interface Interceptor {
	Response intercept(Chain chain) throws IOException;

	interface Chain {
		Request request();

		Response proceed(Request request) throws IOException;

		Connection connection();
	}
}  

All your transformations will live in the intercept method. It takes a Chain object as a parameter. This Chain object contains your request. You should take care of it. Never forget to call chain.proceed(request);. The IO call will only happen after calling that method.
request() give you the current request. You can use it to modify, observe you request going out.

So your teammate tells you that you have to add an Authorization header to all your requests. With interceptors you don’t need to change all your retrofit interfaces. If you want to know how to add an header to a rest endpoint, check the retrofit doc.

...
 new OkHttpClient.Builder()
    .addInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request original = chain.request(); //1
            Request request = original.newBuilder() //2
                    .header("Authorization", token)//3
                    .build();//4
            return chain.proceed(request);//5
        }
    })
...

Ok What is going on here:

  1. First of all, you must get the original request with chain.request() so that you can edit it.
  2. The Request class provide a Builder that help you build a new request. You can’t modify the original request because it’s immutable. The newBuilder() method create a copy with all the parameter initialized.
  3. For our new header, we call .header("Authorization", token) and all our request that will use this http client will have this header. The pretty handy.
  4. You can chain method calls on the Request.Builder class and at the end call build() to build a new request.
comments powered by Disqus