We’re pleased to announce our new, open source iOS tool for HTTP debugging – ResponseDetective.
How many times have you put an
NSLog inside a request completion callback? How many times have you used a breakpoint to check what headers and body are sent to your API service? Now, those are things of the past! We’re pleased to announce our new, open source iOS tool for HTTP debugging –
The Sherlock Holmes of The Networking Layer
Sometimes things break – it’s normal and,
when developing both a iOS mobile app and its back-end API at the same time, it happens often. In such cases, it’s important to quickly examine what’s happening in your networking layer – what headers are sent and received and what payload comes in and out. Previously, you’d have to manually inject breakpoints and logs deep inside your API client implementation. This works, but it’s neither maintainable, nor extensible. Enter ResponseDetective. All you have to do is to set up the required interceptors, with a couple of lines of code, and inject an
NSURLProtocol into your session’s
Good Ol’ Foundation
ResponseDetective uses no private APIs and is just a fancy layer on top of
NSURLProtocol, a class which has existed since iOS 2.0 and is used by
libraries. Turns out, if you’re using
NSURLSession, every time you execute an HTTP request, it asks each registered NSURLProtocol to perform it if they’re able to.
That’s where ResponseDetective comes in. It provides a subclass of
NSURLProtocol which first intercepts a request, performs it, and finally intercepts a response. And speaking of interceptors...
The New Level of Customization
ResponseDetective doesn’t do anything by default. It’s you, the user, who decides how it works and what it intercepts. Want to print all outgoing JSON requests? No problem!
Want to save all XML responses dumps in an array? Here you go!
Maybe you’d like to make use of your awesome
CocoaLumberjack installation? Nothing easier! Just implement your own output stream type and pass it as the
With a project this small, all APIs were supposed to be as simple as possible and we didn’t expect any obstacles. As you may guess, this wasn’t the case.
The first thing which caught our attention was the interface of
NSURLProtocol, which turned out to be, not instance-based, but class-based. For me, who sees
shared mutable state as The Enemy™, it was a huge letdown. We had to rethink our APIs in terms of class methods instead.
In the beginning, we decided that our library would have no dependencies and would be written in pure Swift. It was all going well until we had to implement an XML prettifier on top of libxml.
Alright, let’s create a bridging header and
#import <libxml/tree.h> there!
It was at this moment that we recalled that Swift modules don’t support any static library connections. We had no other choice than to implement the prettifier in Objective-C (in violation of our stated goals) and export the function to Swift using a bridging header, which, by the way, should be impossible in framework targets.
Another thing that makes ResponseDetective different to other open source projects is its rethought setup.
Instead of including a demo app which would serve no particular purpose and would require recompilation each time the user wants to play with the framework, we decided to include a demo playground. This opened up a way to include rich documentation along with live code examples, which is the best way to introduce a framework to potential users.
Also, ResponseDetective takes advantage of pre-built Carthage dependencies. Result? Since Carthage doesn’t build the dependencies (unlike CocoaPods), we managed to achieve an all-time record – a forty-second build on our Continuous Integration servers.
It’s Just The Beginning
ResponseDetective is a fresh project and there’s still a lot of work to do as we’re constantly coming up with new ideas and brainstorming improvements.
Last but not least, there is no open source without openness – if you have any comments, questions or ideas for improvements, feel free to open an issue and contribute to the project.