Appetizer APP 精细化 HTTP 分析 (一):别再只是代理抓个包了

AppetizerIO for AppetizerIO · July 07, 2017 · Last by 佳佳 replied at July 07, 2017 · 3047 hits

HTTP/REST 是目前最主流的前后端接口设计,在测试、线上环境里截获 HTTP 请求可以有效诊断接口请求错误、响应性能、网络环境对页面响应的影响、用户路径分析等。本文从截获 APP HTTP 请求开始讲起,介绍如何分析错误的 HTTP 响应,以及分析响应的性能,穿插实战中找到的问题案例。系列文章将一步步介绍精细化分析。

截获 APP HTTP 请求响应

从代理抓包到插桩截获

APP 端和服务器端的交互是非常重要的一个环节,能够获取交互信息可以有效提高测试分析的效率,找到服务端的问题、定位 APP 代码问题,甚至用来分析用户路径、流量等,是提高产品质量的重要工具。

说到 HTTP 抓包,第一个想到的肯定是代理软件,例如 Charles 和 Fiddler,搜一下,教程很多,用过之后缺点非常多:

  • 架设代理需要修改设备系统配置(还考虑到 https 伪造证书),自动化起来很麻烦,尤其考虑到设备多样性
  • 代理装在开发机上是全流量(电脑上的各种,设备的系统,推送等),还要过滤出 APP 的
  • 代理很多场景不适应,例如测试网络切换,用户那边也不可能挂代理
  • 代理软件天生是给人看的,导出数据做进一步分析也很人工费事

理想的情况应该是在 APP 内部有一个机制截获 APP 的 HTTP 请求响应,log 下来,然后能够方便获取做进一步分析。这样一来 APP 自然就会 log 自己的流量;同时因为是 APP 内部,所以 https 不再是问题;数据可以灵活获取、分析;而且可以根据不同配置(测试环境、用户环境)采取不同的 log 策略,用来不同的分析(测试时全 log,分析错误、性能、稳定性等;用户环境打点、报告问题请求响应)。

然而只有有些 HTTP 库,比如 okhttp,提供了比较方便的 log 接口(Interceptor),很多 http 请求都没有这样的 log 接口。另外 APP 自己会用很多三方库里也会发出请求,三方库代码不好改。最后,监控点如果需要人工维护,成本也很高。

Appetizer 通过插桩技术解决这以上所有问题,插桩是对 APK 的字节码(Dex 文件)进行修改,根据规则截获 APP 以及三方库内发送的 HTTP 请求,并 log HTTP 请求和响应,相比系统代理,插桩截获有以下优势:

  • 一键插桩 APK 即具备 http log 功能,不需要修改设备配置,插桩可以脚本操作,接入 Jenkins 等
  • 插桩截获 APK 本身流量,不用过滤
  • 插桩截获灵活度高,可以进行配置选择性截获,可以广泛应用于测试以及线上环境
  • 插桩截获的数据完整,可以用来进行高级的分析

APP 常用 HTTP 库

APP 中常用的 HTTP 请求库有 HttpURLConnection(HUC), Apache HTTP Client, OkHttp, Retrofit, Volley,还有一些 “快速开发框架”(实际内部封装了这些库)。HUC 是java.net.HttpURLConnection提供的功能,是 Java 自带的标准库,通常是第三方库用来请求 HTTP 的(这样就可以只依赖标准库)。Apache 是曾经 Android 推荐的 HTTP 库,从 5.0 开始已经不再推荐,不过有一些老的三方库、控件库依然使用着 Apache。OkHttp 是 Square 公司开发的方便好用的现代的 HTTP 请求库,目前使用非常流行,Retrofit 也是依赖于 OkHttp,OkHttp 有 2.x(包名com.squareup.okhttp), 3.x(包名okhttp3.*)两个版本,从 5.0+ 开始,标准库的 HUC 实际内部实现是 okhttp。最后 Volley 是 Google 官方出的一套小而巧的异步请求库,
其实是个框架,底层可以对接其他 HTTP 库,官方提供了 Apache 和 HttpURLConnection 的支持。此外国内外有很多 “所谓的 HTTP 库” 其实都是对这几个库的封装。

下图总结了一下常见的库的依赖关系,还有一些比较上层的封装库和开发框架:

Appetizer 截获原理

Appetizer 本身通过字节码插桩的方式来截获 APP 调用 HTTP 库的 API。Appetizer 截获最底层的 HUC, Apache 和 okhttp 2.x 和 3.x,从而支持所有依赖于这几个底层库的框架,如果有我们没有提到的 HTTP 库,请在评论区告知。
对于 okhttp 截获比较简单,因为 okhttp 提供了天然的Interceptor接口,Appetizer 如果探测到 APP 使用了 okhttp,则在程序开头注册一个自己的 interceptor。而 Apache HTTP Client 和 HUC 就没有这么方便的机制,于是 Appetizer 会扫描整个 APP 的代码,为每处调用加上 log 代码,例如:

URLConnection conn = new URL("https://appetizer.io").openConnection();
// Appetizer搜索到openConnection 的调用,在这里插入log代码,记录conn的内容(请求头、响应内容等)
conn.getResponseCode();

精细化 HTTP 分析(一):后端接口错误分析

插桩技术相比较于需要接入 SDK 的方式(比如 Facebook Stetho 和一些监控库)有以下优点:

  • 基于插桩规则,完全自动,没有接入和后期维护监控点的成本
  • 全面,不仅覆盖是 App 代码,而且覆盖所有的库代码,即使这些三方库用了老的 API
  • 测量逻辑和 APP 业务逻辑解耦和,一键插桩加测量,一键关闭

有了截获的 HTTP 数据后,我们可以开始分析,精细化 HTTP 分析对于开发、测试以至于产品分析都有非常重要的用处。我们会分几期介绍基于 HTTP 数据的各种分析。

最常见的是对错误返回码系列的分析,4xx 是 client 端的问题,5xx 是 server 端的问题。

对于 4xx 的返回码(如下图),Appetizer 会给出完整的请求 URL(包括请求参数),以及请求 Header(见折叠),通常这类情况是由于构造的的 URL 有问题,例如参数问题,或者是一些字符串转码方面的问题。Appetizer 1.2.0 推出后,报告页面右上角会多一个按钮,用于导出这个问题请求的 cURL 命令行,可以轻松导入 postman 进行进一步测试


如果返回码是 5xx,那就是后端同学的锅了,同样,可以产生了 cURL 命令行发给后端同学去反复测试这个接口。

常见问答

  • 如何接入 Appetizer 插桩服务?

    使用我们的图形化界面客户端,参考:https://testerhome.com/topics/8162
    使用 Python 客户端(考虑使用脚本插桩或者接入 Jenkins): https://github.com/appetizerio/insights.py

  • 除了 GET,POST,其他 HTTP 方法,比如 PUT 支持吗?

    我们支持 HTTP 协议支持的所有 HTTP 方法,包括更为小众的 PATCH (例如 zhihu 用了),HEAD 等。所以只要是 REST API 都可以用 Appetizer 来截获分析。

  • APP 可以加固么?

    不可以,加固后的 APP 不能修改,开发包可以考虑只混淆

  • APP 可以混淆么?

    插桩本身支持混淆后的 APP,但是有些截获功能是通过寻找目标库的 API 实现的,混淆后有些库的 API 被去除或者改名会导致部分库无法识别,无法截获。目前如果使用了 okhttp,最好保证库不会被混淆,可以在 proguard 规则中增加:

    -keepattributes Signature
    -keepattributes Annotation
    -keep class okhttp3.** { *; }
    -keep interface okhttp3.** { *; }
    -dontwarn okhttp3.**
    -dontwarn okio.**
    
  • ReactNative/Weex 等 H5 技术开发的 APP 支持么?

    经测试是完全支持的。ReactNative 的 HTTP 库用的是 OkHttp,在我们支持范围内。

  • Kotlin 开发的 APP 支持么?

    经测试是完全支持的。

  • webview 控件里的页面请求能截获吗?

    正在开发中

  • 插桩截获功能对性能的影响怎样?

    插桩代码的运行代价是记录 HTTP 请求,Appetizer 只记录请求响应的 header 内容,并不记录 body,从而性能影响很小,记录单个请求耗时最多 1ms。同时,因为 HTTP 请求都是在 APP 的子线程上完成的,所以不会造成任何主线程卡顿

  • 使用了一些会发出 HTTP 请求的 C++ 库 (.so) 能截获吗?

    目前不支持,插桩仅限 Java 代码。例如使用了 Lua 解释器、C++ 的视频/音频播放器目前都暂不支持,如果希望支持,请在评论区留言

  • 支持手游吗?

    同上。手游的 HTTP 是从 C++ 库里发出的

  • 支持非 HTTP 协议,例如 RTP 之类的

    暂不支持

  • iOS 呢?

    参考光哥的文

预告

  • 精细化 HTTP 分析(二):响应性能分析与优化
  • 精细化 HTTP 分析(三):流量分析
  • 精细化 HTTP 分析(四):弱网响应下接口稳定性分析
  • 精细化 HTTP 分析(五):通过复杂 Query 定制 HTTP 分析报告
  • 更多需求,请在评论区提议
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 1 条回复 时间 点赞

期待弱网响应下接口稳定性分析👍

AppetizerIO [Topic was deleted] 中提及了此贴 03 Jan 14:51
AppetizerIO 优化 APP 网络流量 中提及了此贴 03 Jan 15:04
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up