(String: {%- set hs_blog_post_body -%} {%- set in_blog_post_body = true -%} <span id="hs_cos_wrapper_post_body" class="hs_cos_wrapper hs_cos_wrapper_meta_field hs_cos_wrapper_type_rich_text" style="" data-hs-cos-general-type="meta_field" data-hs-cos-type="rich_text"> <div class="blog-post__lead h2"> <p>We’re pleased to announce our new, open source iOS tool for HTTP debugging – ResponseDetective.</p> </div></span>)

HTTP Debugging in iOS Made Easier with ResponseDetective

Photo of Adrian Kashivskyy

Adrian Kashivskyy

Updated Nov 17, 2023 • 6 min read

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 – ResponseDetective.

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 NSURLSessionConfiguration.

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 many request stubbing 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 outputStream parameter.

You can even create your own interceptors and dump literally anything you want. Just implement a relevant protocol and you’re ready to go.

Technical Challenges

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.

Think Different

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.

There are more open source projects we’re working on - help yourself to what we’ve got, or join us. We'd love to meet you on Twitter, too - @netguru.

Photo of Adrian Kashivskyy

More posts by this author

Adrian Kashivskyy

Adrian is an iOS developer and designer. He designed and developed 4 App Store applications by the...
How to build products fast?  We've just answered the question in our Digital Acceleration Editorial  Sign up to get access

We're Netguru!

At Netguru we specialize in designing, building, shipping and scaling beautiful, usable products with blazing-fast efficiency
Let's talk business!

Trusted by: