How to debug HTTP(S) traffic on Android
A friendly tip.
There are times in life where you need to deal with APIs. You probably don’t want to, but you have to (but you don’t want to). For the major part of you, this is everyday life. And most of the times, debugging what happens when you issue the network request and when you receive the response is a pain that you likely would leave to your colleagues.
Yes, because how many times you struggled to figure out that the API call was not working because the encoding was wrong? Or because an HTTP header was missing? And if you have a backend guy to deal with, he surely goes like “Are you sure you are doing [random_stuff]?”
And no, you simply can’t answer “Yes, b*tch!” because you’re not that sure. It’s not easy to see what the final request looks like, and the same goes for the response.
When in doubt, use a proxy
There is a boatload of different solutions and approaches to this problem, but what I’m about to suggest is the fastest, easiest and most feasible way I could find to do it.
Since debugging the HTTP requests and responses is quite cumbersome (even more cumbersome for HTTPS), the best tool you can use in this case is a proxy. Of course, you already know what a proxy is, so I won’t be dwelling into its definition.
Among hundreds of proxies that vary in use, features, OS compatibility, how to choose the right one? I’d say, go simple. Meet mitmproxy.
I can’t even begin to tell you how handy and amazing this little tool is. mitmproxy is “an interactive, SSL-capable man-in-the-middle proxy for HTTP with a console interface”. Yes, you operate it via console. Yes, it supports HTTPS. Yes, it allows “traffic flows to be intercepted, inspected, modified and replayed”. And yes, it is cross platform, since it is written in Python. Did I mention it is completely free?
Using it is utterly simple, too. Once you install it, fire it up by typing the following command in your console:
$ mitmproxy [-b IP_ADDR] [-p PORT]
The proxy is now running, allowing you to intercept the network traffic. The next step involves configuring your device to redirect all the traffic to that proxy address (IP_ADDR + PORT).
The “Proxy Settings” app
Configuring the proxy settings on your Android device is, guess what, not so straightforward as you might want. You need to 1) go to the device’s Wi-Fi settings, then 2) long-press on the currently connected network, 3) choose to modify its settings, 4) show the advanced options, 5) enable the proxy settings and manually 6) type in the IP address and the port. The same goes for disabling it. This is nuts!
Thanks to Proxy Settings, the hassle of all this almost goes away. This lightweight application allows you to enable/disable the proxy settings for your network connection, all in the blink of a click.
You can create as many proxy configurations as you want. When you want to enable one, simply tap on the currently connected network, enable the proxy and select the configuration you need. To disable the proxy, tap on the connection and disable it.
Simple, as it should be. Need I to say more? How about no root privileges required?
What about HTTPS?
I mentioned earlier that mitmproxy supports HTTPS interception. This is extremely handy when you need to debug some production API calls without switching endpoint, for instance. However, due to how HTTPS works, we need to install a custom SSL certificate that allows mitmproxy to decrypt the traffic.
While this may sound like a lot of work, it’s a really simple procedure. By following this guide from the official mitmproxy website, you should be good to go in virtually no time. Be sure to add an extra parameter when launching mitmproxy, so that it looks like this:
$ mitmproxy -a IP_ADDR -p PORT —-no-upstream-cert
There’s a catch, unfortunately. Android saves the SSL certificates in an encrypted form, using the unlock information set by the user. What this means is that, before you can install any SSL certificate, you will be prompted to set a way of unlocking the device, either by a PIN code, a password, a pattern, and so on.
This is not a big deal if you’re working on a development phone, but it may be an inconvenience if you use your personal device. On a personal note, with Lollipop’s Smart Lock feature, no one should go without a locked phone. You need to stay safe!
This one is a bit harder. There is no system setting that is able to set a proxy for 3G/4G connections. BUT! You still can use your nifty hotspot feature! What you need is:
- a device with a 3G/4G connection
- the development device
- your laptop
Real simple: 1) activate the hotspot feature on the first device, 2) connect both the dev phone and the laptop to the hotspot, 3) run mitmproxy on the IP address assigned by the hotspot (typically 192.168.43.xxx) and 4) use Proxy Settings to set the proxy on the dev device.
Not the easiest, but still, could be worse!
I tried two other proxies so far, but mitmproxy manages to beat the crap out of each one of them. Charles is probably the closest one in terms of features, flexibility and OS support, but it is not free and it is not open-source. Fiddler, on the other hand, comes short in availability, since it’s Windows-only.
The mitmproxy + Proxy Settings combination has saved me quite a lot of time and headaches, so I hope it will do some good to you too.
Feel free to tell me what you think and if you have a better solution! ☺