开发iOS的过程中,有一件非常令人头疼的事,那就是网络请求的调试,无论是后端接口的问题,或是参数结构问题,你总需要一个网络调试的工具来简化调试步骤。
现状App外调试早先很多的网络调试都是通过App外的调试来进行的,这种的好处是可以完全不影响App内的任何逻辑,并且也不用去考虑对网络层可能造成的影响。
Charles[1]确实是网络调试的首选,他支持模拟器、真机调试,并且附带有mapremote和maplocal的功能,可以说是iOS开发中的主流调试工具,但是缺点也很明显,使用时必须保证iPhone和Mac在同一Wi-Fi下,并且使用的时候还需要设置Wi-Fi对应的Proxy,而一旦电脑上的Charles关掉,手机就会连不上网络。在办公室可谓神器,可一旦离开了办公室,就没法使用了。Surge[2]也是近几年的一款不错的网络调试工具,iOS版设置好证书后,就可以直接看到所有app的请求,而Mac版提供的remotedashboard可以增加网络请求查看的效率,新的TF版本还增加了rewrite以及script的功能,基本能达到Charles的大部分常用需求,并且可以独立于Mac来进行。不过这种方式也有一定的问题,那就是每次查看网络请求都需要切换App,并且请求是所有应用发出的,而很难只看一个应用的请求(其实也是Filter做的不够细导致的问题)。App内调试目前GitHub上已经有非常多的网络调试框架,提供了简单的应用内收集网络请求的功能。
GodEye[3]提供了一套完整的网络请求监控的功能,然而后面一直没有更新,并且会对应用内发出的请求有所影响(这点会在下文具体讲解),仅能作为调试使用,而不适合在线上继续调试。Bagel[4]这个的实现基本不会对应用内的请求有影响,不过这个必须要有Mac的应用才可以使用,而且因为实现的原因,如果应用内使用了自定义的URLProtocol,会使得网络请求的抓取重复。以上的两大类调试方式,各有优劣,App外调试往往因为并不针对某个应用,导致查询的体验非常一般,现在Github上的大部分网络调试框架也基本都和这两个的原理类似,而这些调试工具的实现,由于多是用于Debug环境,对很多网络监控的要求也就非常的低,比如GodEye这种,就明显会影响到现有的网络请求,虽然影响很小,在调试环境下也能够接受,基本能够完成目的,但是一旦我们希望在线上(包括testflight)环境下进行调试,也就会让所有网络请求都有受到影响的风险(具体的风险后面会讲到)。网络调试的原理为了解决上面的问题,我们决定从现有的App内调试方案入手,着手优化一些细节的部分,来达到即使在线上进行调试也不影响网络请求的目的。下面我先介绍一下目前主流的几个网络调试方案的原理。
URLLoadingSystem中的URLProtocol很多人在入门iOS的时候,都会通过Alamofire等第三方网络请求库来发送网络请求,但大部分的网络请求库都是基于标准库中URLConnection或者URLSession的封装,其中URLConnection是旧的封装,而URLSession则是较新的也是现在被推荐使用的封装,它们本身对URL的加载、响应等一系列的事件进行了处理,其中就包含了所谓的传输协议的修改,标准库中提供了基础的URL传输协议,包括