Chuck – In-app HTTP inspector for HTTP OkHttp clients

By -

During development many time it happens we have to debug API calls to check what request we are making and what response we are getting. Either we put debug point in android studio or we check using Postman like tools.

But Jeff Gilfelt has made our work easier by creating an awesome library “Chuck” https://github.com/jgilfelt/chuck. Thanks and kudos to him!

Chuck

Chuck is a simple in-app HTTP inspector for Android OkHttp clients. What it does is it intercepts and persists all HTTP requests and responses inside your application, and provides a UI for inspecting content of each requests/responses.

chuck-inapp http inspector

Setup

Include dependencies in build.gradle file:

// chuck library - inapp http inspector
debugCompile 'com.readystatesoftware.chuck:library:1.0.3'
releaseCompile 'com.readystatesoftware.chuck:library-no-op:1.0.3' 

Library-no-op is for isolating Chuck from release build.

Add ChuckInterceptor to your OkHttpClient which will listen to all the API calls:

OkHttpClient okHttpClient = new OkHttpClient.Builder().
       addInterceptor(new ChuckInterceptor(app.getApplicationContext()))
       .build();

How it works?

Once you have done setup, launch your app and it will show you notification intercepting API calls, clicking on it will launch MainActivity given in Chuck library.

What it does at back door?

ChuckInterceptor is an interceptor class created by implementing Interceptor interface of OkHttp3 library. If you want to understand how it works then I would suggest you to check and understand HttpLoggingInterceptor of OkHttp library.

In overrided intercept method, you get a parameter called Chain interface which has 3 methods:

public interface Chain {
   Request request();

   Response proceed(Request var1) throws IOException;

   Connection connection();
}

Now showing you initial part of intercept method which would give you more idea what does in background:

public Response intercept(Chain chain) throws IOException {
   Request request = chain.request();
   RequestBody requestBody = request.body();
   boolean hasRequestBody = requestBody != null;
   HttpTransaction transaction = new HttpTransaction();
   transaction.setRequestDate(new Date());
   transaction.setMethod(request.method());
   transaction.setUrl(request.url().toString());
   transaction.setRequestHeaders(request.headers());
   …..
   …..
}

Through chain it gets access to request, response and connection objects. And then it prepares object of HttpTransaction class which is a POJO class to prepare a complete object of http request and response data.

Once Object is prepared with Request details, it calls create(HttpTransaction transaction) method to store data in local database, yes it uses LocalCupboard library developed by Hugo Visser (my friend) at Little Robots.

private Uri create(HttpTransaction transaction) {
   ContentValues values = LocalCupboard.getInstance().withEntity(HttpTransaction.class).toContentValues(transaction);
   Uri uri = this.context.getContentResolver().insert(ChuckContentProvider.TRANSACTION_URI, values);
   transaction.setId(Long.valueOf(uri.getLastPathSegment()).longValue());
   if(this.showNotification) {
       this.notificationHelper.show(transaction);
   }

   this.retentionManager.doMaintenance();
   return uri;
}

As soon Response comes, it updates HttpTransaction object with response details and then it calls update(HttpTransaction transaction, Uri uri) to update the same transaction log in database.

private int update(HttpTransaction transaction, Uri uri) {
   ContentValues values = LocalCupboard.getInstance().withEntity(HttpTransaction.class).toContentValues(transaction);
   int updated = this.context.getContentResolver().update(uri, values, (String)null, (String[])null);
   if(this.showNotification && updated > 0) {
       this.notificationHelper.show(transaction);
   }

   return updated;
}

Some more options

Disable notification

If you want to disable notification then call showNotification(false).

OkHttpClient okHttpClient = new OkHttpClient.Builder().
       addInterceptor(new ChuckInterceptor(app.getApplicationContext()))
        .showNotification(false)
       .build();

Data retention

By default it’s retaining data for a week in shared preference ChuckInterceptor.Period.ONE_WEEK, but given there are 4 different options available: ONE_HOUR, ONE_DAY, ONE_WEEK, FOREVER

Change in max content length

By default max content length is 250000L, but if you want to change then call maxContentLength(long max)

OkHttpClient okHttpClient = new OkHttpClient.Builder().
       addInterceptor(new ChuckInterceptor(app.getApplicationContext())
        .showNotification(false)
        .maxContentLength(200000))
       .build();

In Summary

It has already helped me today in debugging one issue in one app where we need to test app outside and mostly don’t have access to laptop and so Postman is not possible. Earlier we were logging request and response in text file and then checking that file to see. Thanks to Jeff for making it more easier and helpful.

Paresh Mayani

Lazy android developer, exploring the horizon of android development since 7 years, currently working as a Technical Lead - Android at Simform Solutions, India. Former Application Architect at KarConnect. He is the Head/Organizer of Google Developers Group (GDG), Ahmedabad

Loading Facebook Comments ...
Loading Disqus Comments ...