埋点返回 success:true,任务却没计数:一次跨子域会话的排查
现象
有个「每日体验 AI DevSpace」的任务,点一下按钮就触发埋点上报,任务转完成、+30 分。脚本化之后跑了几天都正常,今天突然不计数了。
日志长这样:
POST https://hands-on-agent.developer.huaweicloud.com/api/track/aishell_click
HTTP 200
{"success":true}
接口返回成功,任务状态却是未完成。服务端明确说了 success,但业务上什么都没发生。
第一反应是错的
看到 success:true 很容易往这几个方向想:
• 是不是今天已经做过了(幂等跳过)?→ 查了,没有
• 是不是积分结算延迟?→ 等了 3 分钟,还是没有
• 是不是接口改了、埋点字段变了?→ 抓包对比,请求体和以前一模一样
三条都排除了。问题不在请求本身。
真正的线索:一个被我忽略的接口
回头看这次会话里所有请求,发现页面加载时还调了一个东西:
GET https://hands-on-agent.developer.huaweicloud.com/api/islogin?callback=checklogin
→ checklogin({"flag":0})
flag:0 —— 这个子域认为我没登录。
对比正常情况下的返回:
checklogin({"userId":"01a1477342cb7aafbd80c5f92c1e8a09",
"username":"hw036720952",
"domainId":"01a1477342cb7aafbd80c5f92c1e8a09", ...})
有 userId、有 username,是完全不同的结构。
为什么会这样
主域 devdata.huaweicloud.com 的登录态是正常的——我拿 csrf、查积分、发博客全都通。但埋点走的是 hands-on-agent.developer.huaweicloud.com,另一个子域。
关键在这里:会话建立需要一个"落地"动作。主域那套是靠访问业务页(developer.huaweicloud.com/grow)让 cookie 落全,子域同理。如果直接拿主域的会话去打子域接口,子域自己那套 cookie 还没建立,islogin 就返回 flag:0。
于是整条链路变成:
埋点请求发出 → 服务端收到 → 查不到是谁发的 → 记一条匿名事件 → 返回 {"success":true}
接口没撒谎,它确实成功接收并存储了这次点击。只是这条记录没有关联到任何账号,自然不可能触发任务计数。
这是典型的"技术成功 ≠ 业务成功":HTTP 200 和业务码都正常,但语义上这次调用是无效的。
修法
在打开子域之前,先把主域会话激活一次:
b.refresh_csrf() # 内部会访问 grow 页,建立业务会话
p.goto("https://hands-on-agent.developer.huaweicloud.com/#tasks")
然后再验证子域登录态,确认 flag=1 才继续:
r = ctx.request.get(HOA + "/api/islogin?callback=checklogin")
if "userId" not in r.text():
log("⚠️ 子域未登录,埋点会匿名上报,先别点")
改完重跑:
子域 islogin: flag=1? True | 含 userId? True
点击 a[data-task=devspace] …
200 POST /api/track/aishell_click → {"success":true}
第1次(20秒): DevSpace 完成=True 积分=550
20 秒后任务转完成,+30 到账。
一个附带的坑:同一个页面的"未绑定"也是假的
排查过程中还撞见一个更隐蔽的。页面上有个「绑定 GitCode 账号」区块,我第一次抓 DOM 时看到的是:
#unboundView display=block w=545 h=58 ← 未绑定视图可见
#unbindBtn w=0 h=0 ← 解绑按钮尺寸 0
input value = "" ← 用户名输入框空的
三个信号一致指向"没绑定过"。于是我怀疑是绑定关系丢了,准备去重建绑定。
但按上面的方法先激活会话再看,同一个页面变成:
#unboundView display=none w=0 h=0
#boundView display=block w=545 h=96
已绑定 GitCode 账号:gcw_8kuR9mW1
关联华为云账号:hw036720952
bound_at: 2026-10-20 02:00:57
早就绑好了,绑了 8 天。 之前看到的"未绑定"是因为页面在 flag:0 状态下渲染,拿不到用户信息,就默认显示了未绑定分支。
如果我当时照着这个 DOM 去调 /api/binding/create 重建绑定,就会把一个正常状态改成未知状态——UI 状态也是会话的函数,不能当独立事实来读。
排查清单
以后再遇到"接口成功但业务没生效",按这个顺序:
1. 别只看目标接口的返回值,把这次会话里所有请求都列出来,找有没有别的接口在报异常状态
2. 特别留意 islogin / whoami / userinfo 这类身份接口,它们的返回结构变了(flag:0 vs 完整用户对象)就是信号
3. 跨子域调用前,先确认目标子域自己的会话建立了,主域登录不等于子域登录
4. DOM 状态要和身份接口交叉验证,页面在匿名态下渲染出来的东西不可信
5. 写操作前先回读状态;写操作后也回读——success:true 只证明请求被接收,不证明业务生效
第 5 条是这个仓库里反复踩的老坑了:code=0、errno=0、success:true 都不等于业务成功,必须回读状态或看余额差值。这次的特殊之处在于,连"回读业务状态"都可能读到假象(那个未绑定视图),所以回读也要在正确的会话状态下做。
- 点赞
- 收藏
- 关注作者
评论(0)