PUBLIC OBJECT

Sneaking Data into an OkHttp Interceptor

OkHttp Interceptors are a fun & powerful way to implement cross-cutting behavior in your app. You can use ’em for authentication, performance, monitoring, and more. There’s even open source interceptors for OAuth signing and curl logging!

Suppose we want to write an interceptor that tracks which activities use the network the most. For each HTTP call we’ll measure how big it is, how long it took, and which activity triggered it:

public final class CallMeasurement {
  long requestSize;
  long responseSize;
  long requestDurationMillis;
  long responseDurationMillis;
  String activityName;
}

Our interceptor watches all calls & measures them:

public final class MeasuringInterceptor implements Interceptor {
  final List<CallMeasurement> measurements = new ArrayList<>();

  @Override public Response intercept(Chain chain) {
    ...
  }
}

We have a problem: there’s no obvious way for the interceptor to find out which activity triggered the call. We could cheat by doing pattern matching on the URLs, or by looking at which activity is in the foreground, but both are clumsy and could be unreliable.

It turns out that we can sneak data into an interceptor with a request header! When initiating each request, include a header that contains the data of interest:

Request request = new Request.Builder()
    .url("...")
    .header("Activity-Name", HomeActivity.class.getName())
    .build();

Then in the interceptor remove this header before it’s transmitted over the network:

public final class MeasuringInterceptor implements Interceptor {
  final List<CallMeasurement> measurements = new ArrayList<>();

  @Override public Response intercept(Chain chain) {
    Request request = chain.request();

    // Read the activity name request header.
    String activityName = request.header("Activity-Name");

    // Remove it so we don’t send it over the network.
    request = request.newBuilder()
        .removeHeader("Activity-Name")
        .build();

    ...
  }
}

This is almost what HTTP headers are designed for, but typically the consumer of the headers is a faraway proxy server or webserver instead of a nearby OkHttp interceptor.

If you work closely with the team that runs your HTTP application servers, you can do a similar trick with headers in the HTTP response. The server might add a response header to warn when the session will expire, or how long it spent computing the response, or whether the request included any unexpected fields. Your interceptors can act on that data.

When you do add custom headers, be careful to make sure they don’t collide with the standard ones, otherwise you might have trouble.

Interceptors are a powerful feature in OkHttp. You might be surprised what they’re capable of!