问题定位-03-Charles在App抓包中的实战经验

做 App 测试时,最常见的一种现场混乱是这样的:

  • App 明明发了请求,但测试说自己没抓到
  • 抓到了部分接口,但关键接口就是没有
  • 页面报错了,但研发说后台没看到请求
  • 同一个接口在浏览器里能通,在 App 里不通

这时候如果没有一个稳定的抓包工具,现场经常会变成纯口头对线。
Charles 的价值,恰恰是把这些分散现象拉回到同一条链路里:

  • 设备到底有没有把请求走到代理
  • HTTPS 到底有没有被正确解开
  • 请求是没发、没到,还是回来的东西不对
  • 同一条请求改参数、重放之后会发生什么

所以这篇文章不写安装流程,而是按现场实战来讲:

  • Charles 在 App 抓包里最常见的用法
  • 为什么很多“抓不到包”根因并不在工具
  • 抓到之后怎么让它真正变成排障证据

一、Charles 在 App 抓包里最有价值的,不是“看见请求”,而是“确认链路是否真实经过代理”

一提 App 抓包,默认目标往往是:

  • 抓到某个接口

但现场更核心的问题往往是:

  • 设备流量有没有真的经过代理
  • 是所有流量都走代理,还是只有一部分
  • HTTPS 是否可解
  • App 是否做了额外证书校验

如果这些前置问题不先搞清楚,后面很容易误判:

  • 以为后端没收到
  • 其实是代理没生效

或者:

  • 以为 App 没发请求
  • 其实是 HTTPS 没解开,只看到 CONNECT

二、最常用的 5 类 Charles 场景

1. 确认 App 是否真正发出请求

这是最基础的一层。

当页面报错、按钮无响应、列表转圈时,先想确认的通常不是接口细节,而是:

  • 有没有请求出去
  • 请求打到了哪个域名
  • 是不是打错环境了

这时 Charles 的价值非常直接:

  • 能先把“发没发”这个问题钉住

2. 确认 HTTPS 链路是否打通

App 抓包最常见的问题之一,不是请求没有,而是:

  • 只看到 CONNECT
  • 看不到明文请求

这通常说明:

  • HTTPS 代理证书没正确安装
  • 设备信任链没打通
  • App 做了证书校验或 SSL Pinning

3. 对比不同环境、不同设备、不同版本的请求差异

例如:

  • Android 正常,iOS 异常
  • 老版本正常,新版本异常
  • 测试环境正常,预发环境异常

这类问题特别适合用 Charles 看差异,因为你能直接对比:

  • 域名
  • Header
  • Body
  • 返回码
  • 返回结构

4. 复放和改包验证

当我怀疑问题不只是前端展示,而是接口本身存在边界问题时,常见动作包括:

  • 重放请求
  • 改 Header
  • 改请求体
  • 换参数再发

这对排查下面几类问题很有用:

  • 参数问题
  • 鉴权问题
  • 环境问题
  • 服务端返回不一致

5. 现场留证

很多 App 问题难推进,不是因为现象复杂,而是因为没有留下可复查证据。

Charles 很适合留这些内容:

  • 原始请求
  • 原始响应
  • Header
  • 请求时序
  • 域名与路由去向

这对后续提单和协作非常重要。

三、App 抓包现场最常见的几个根因,不是“Charles 不好用”

很多“抓不到”的问题,根因其实很固定。

1. 代理根本没生效

例如:

  • 手机没连对 Wi-Fi
  • 没填对代理地址和端口
  • 电脑和手机不在同一网段
  • 代理设置被系统或 App 覆盖

这种时候你看到的不是异常请求,而是根本没有流量进来。

2. HTTPS 没解开

常见表现:

  • 能看到连接,但看不到请求详情
  • 只有隧道、没有明文内容

这通常意味着:

  • 证书没装好
  • 设备没信任
  • App 自己做了更严格的证书校验

3. App 走了特殊网络链路

例如:

  • 某些 SDK 走了系统外链路
  • 某些请求绕过了系统代理
  • 某些域名策略和普通接口不一样

这时候不能简单下结论说“App 没发请求”,而要先确认这类流量是否本来就不会经过代理。

4. 环境混了

例如:

  • 同时连着测试、预发、生产域名
  • 接口走了灰度域名
  • CDN、网关、BFF 层返回结构不一样

不先把目标环境收窄,现场很容易把问题看乱。

四、一套更实用的最小抓包骨架

如果我现在要现场抓一个 App 问题,通常按这个顺序来。

1. 先确认代理路径

先问清楚:

  • 手机连的是哪张网
  • 电脑的 IP 是什么
  • 代理端口是什么
  • 设备是否已经配置代理

如果这一步没确认,后面都是空抓。

2. 先抓一个最简单的请求确认链路

例如:

  • 打开首页
  • 下拉刷新一个列表
  • 点一个确定会发请求的按钮

目的是先确认:

  • 流量能不能进入 Charles
  • 是否能看到目标域名

3. 再确认 HTTPS 是否可读

这一步要回答:

  • 只能看到 CONNECT 还是能看到明文
  • 哪些域名可读,哪些域名不可读

4. 最后再去做问题场景复现

例如:

  • 登录失败
  • 支付下单失败
  • 页面白屏
  • 某个按钮无响应

此时抓到的包才真正有分析价值。

五、更常用的 4 个实战动作

1. 先按域名过滤

App 流量经常很杂,尤其带上埋点、CDN、图片、日志上报之后。
更稳的做法通常是先按目标域名收窄,只看主业务接口。

2. 对比同一接口在成功和失败场景下的差异

例如:

  • 成功登录一次
  • 再失败登录一次

重点对比:

  • Header 差异
  • 请求体差异
  • 返回码差异
  • 服务端返回字段差异

3. 重放请求确认是不是后端稳定复现

如果页面表现异常,我经常会先把对应请求重放一遍,看:

  • 是前端问题
  • 还是后端接口本身稳定返回异常

4. 导出或截图保留证据

不要只现场看一眼。
重要问题会至少保留:

  • 请求详情截图
  • 响应详情截图
  • 时间线说明

这会直接影响后续问题单质量。

六、最容易踩的几个坑

1. 把“抓不到包”直接理解成“没有请求”

实际上更常见的是:

  • 代理没生效
  • HTTPS 没解
  • 流量没走代理

2. 抓到了大量包,但没有先过滤主业务流量

最后就会陷入:

  • 图片一堆
  • 埋点一堆
  • 静态资源一堆

却还是没看清真正的业务接口。

3. 只看一次失败,不做成功失败对照

很多问题单靠一次失败很难判断到底哪里不对。
但成功和失败一对比,差异往往会非常明显。

4. 只看接口结果,不看环境和设备差异

例如:

  • Android 某版本异常
  • iOS 正常

如果不把版本、设备、环境一起带进来,结论会很虚。

七、真实案例:为什么 App 页面报“网络异常”,但后台同学说根本没看到报错

场景

一个 App 页面在点击“提交”后频繁提示“网络异常”。
前端同学说:

  • 页面就是超时了

后台同学说:

  • 服务日志里没看到对应报错
  • 接口监控也没明显异常

现场一度怀疑是偶发前端问题。

执行

先用 Charles 抓这条提交链路,按下面顺序看:

  1. 先确认手机流量是否经过代理
  2. 再确认目标接口域名是否被正确抓到
  3. 再对比成功提交和失败提交两次请求

现象

结果并不是接口完全没发出去,而是:

  • 失败场景下,请求实际上打到了另一个环境域名
  • 这个域名对应的是旧网关
  • 旧网关返回了不同格式的错误结构
  • App 端没有兼容这个结构,统一兜成了“网络异常”

所以现场的误导点在于:

  • 前端看到的是网络异常
  • 后台主服务看到的是“没收到主域名请求”

双方都没错,但都只看到了自己那一层。

排查

继续往下看发现,问题出在新版本里一段环境配置切换逻辑没有完全生效,导致部分请求仍然走旧域名。

这个问题如果没有抓包,很容易一直在:

  • 前端超时逻辑
  • 后端错误处理

这些方向里绕圈子。

修复

最终修复动作很明确:

  1. 修正环境配置切换逻辑
  2. 再次抓包确认提交请求统一走到目标域名
  3. 增加提交流程的环境校验回归

这个案例很典型地说明:

Charles 在 App 抓包里最有价值的,不只是看到请求,而是把“到底请求打到了哪里”这件事钉死。

八、怎么把 Charles 用成稳定的测试能力

更合适的做法是把它沉淀成固定动作,而不是出了问题才临时打开。

至少固定这几条:

  • 先确认代理链路再抓问题
  • 先确认 HTTPS 是否打通再谈接口内容
  • 先做成功失败对照再下结论
  • 关键问题必须留请求、响应和时间线证据

这样 Charles 才不会只是一个“会抓包的人偶尔打开一下”的工具,而会真正成为 App 测试里的现场证据工具。

九、写在最后

Charles 在 App 抓包里的价值,不是让你多看几个请求,而是让你把设备、环境、代理、证书、接口和页面现象放回一条完整链路里。

很多看起来像“网络异常”的问题,最后根因并不在网络本身,而是在:

  • 请求到底去了哪里
  • HTTPS 到底有没有被正确解开
  • App 到底拿到了什么返回

只要这几件事能被抓清楚,很多 App 现场问题就不会再停留在互相猜。