ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Copy as fetch + Skill:让 AI 按固定套路自动分析接口 Bug

Copy as fetch + Skill:让 AI 按固定套路自动分析接口 Bug Chrome DevTools 的 Network 面板里有个Copy as fetch功能大多数人用过一两次就放那儿了。而 Skill 这个词在 Claude Code、Codex 这类 AI 编程助手的生态里已经从一个概念变成了非常具体的东西——一个写在 SKILL.md 里的能力包。这两个东西看似八竿子打不着但结合起来恰好解决了我一直在纠结的一个问题bug 复现信息怎么才能无损、低成本地喂给 AI并且让它按固定套路产出分析结果而不是每次答案都天马行空。我花了两周时间把这条链路跑通从抓请求、存下来的原始 fetch 代码到定义好一套 Skill 指令让 AI 自动解析、重放、比对响应、输出结构化报告中间踩了不少坑。这篇把完整思路和实操过程写下来适合做接口测试、前端开发、测试开发以及所有需要在日常排查问题里用上 AI 的人。1. 先说清楚这俩东西组合起来到底解决什么问题1.1 Copy as fetch 的真正价值在浏览器 DevTools 的 Network 面板里右键任意一条请求能看到三种导出方式Copy as fetch、Copy as Node fetch、Copy as cURL。它们的作用是把这条网络请求完整还原成一段可执行代码包含 method、URL、所有 headers、body 和 cookie 信息。Copy as fetch 生成的是浏览器原生 fetch 格式的代码带credentials: include附带当前请求的全部上下文。这意味着什么意味着你在页面上点了七八步操作才触发的一个接口报错可以通过 Network 面板直接拿到它的完整身份证——不需要再让人去复述我点了哪个按钮、页面弹了什么错误也不需要让前端同学一句句拷参数。我最初只是把它当复现工具用拿到请求粘贴到 Console 里跑一遍看是不是稳定复现。但后来发现真正有价值的不是复现而是把请求变成一个可以被程序处理的对象。fetch 代码本质上是一段结构化的数据URL、方法、headers、body 全部分离明确。这让它非常容易被解析、被重放、被比对。1.2 Skill 在 AI 工作流里扮演的角色Skill 是最近这一两年 AI 编程工具里火起来的能力加载方式。Claude Code、Codex 这类工具支持你用一个目录加一个 SKILL.md 来定义一套专用流程。你告诉它遇到这类任务按这几个步骤处理输出这种格式模型就会在触发相关场景时把这份指令加载到上下文里并严格按流程执行。Skill 和普通的提示词模板不同之处在于它可以把一段完整的、可复现的执行路径固化下来甚至可以附带辅助脚本、示例文件、参考文档。它不是一句闲聊式的帮我分析一下而是一套标准操作规程SOP只是这个 SOP 的执行者换成了 AI 而已。1.3 两者组合的核心场景结合这两个东西我最常用来做三件事接口问题自动复现把 Copy as fetch 得到的代码丢给绑定了 Skill 的 AI它能自动重放请求、捕获响应、对比预期结果输出一条可复现的 bug 记录。线上问题描述补全用户反馈说页面白屏或保存失败前端把最后一个失败请求的 fetch 代码抓下来AI 就能基于它还原完整调用链。回归用例快速生成一个接口改了入参把变更前后两条 fetch 请求给 AI它能自动生成差异报告和回归用例草稿。这三个场景有一个共同点都找到了痛点源头——信息传递损耗。你口头描述的接口报错和一段精确到 header、cookie 的请求代码对 AI 来说是两种完全不同的信息密度。2. 整体方案设计与思路拆解2.1 设计目标与边界做这套方案之前我列了几个明确的目标防止做着做着变成一个大而无当的自动测试平台输入必须简单只给一段 Copy as fetch 贴过来的代码不需要用户填表单、选环境。流程必须可控AI 不能自由发挥必须按 Skill 里定义的步骤走每一步产出可追踪。输出必须有固定格式以结构化的 JSON/YAML 形式返回分析报告方便继续接流程或人工快速扫一眼。边界要清晰Skill 只负责问题分析和报告生成不负责自动修 bug、不负责大规模压测。这个边界设计很重要。我之前试过让 AI 从一步到位到复现——定位——修复——验证全部自动搞定结果发现中间任何一环出错后面的流程形同虚设。把范围收敛到记录与分析这一步是最稳的起步——信息输入、流程执行、结果输出都能被约束质量可控。2.2 为什么选复制 fetch 代码走 System 层而不是用抓包代理我在搭这套东西时确实纠结过另一个方案用 mitmproxy 或 Fiddler 挂一个代理把所有流量导到本地再让 AI 去分析日志。这个方案自动化程度更高但有几个问题配置成本高需要目标环境支持改代理移动端尤其麻烦。涉及 HTTPS 证书信任部分场景下会影响业务方使用。数据量巨大一次页面操作可能产生几十条请求噪音太多。而 Copy as fetch 是浏览器帮你挑好了一条请求的结果。人看一眼 Network 面板说出来就是这条 500 的请求然后复制出来——这是一个人的判断 机器精确提取的组合信息质量远高于全量抓包后的自动筛选。简单说抓包方案适合做流量监控和全量分析而 Copy as fetch 方案适合做单点问题快速定位。两者不冲突但从我日常的 bug 反馈场景来看后者的投入产出比明显更高。2.3 Skill 的目录结构与设计要点Skill 的落地形式很简单一个目录、一个 SKILL.md外加一些辅助脚本。我的目录长这样api-bug-analysis/ ├── SKILL.md ├── scripts/ │ ├── parse_fetch.js │ ├── replay_request.js │ └── format_report.js └── examples/ ├── ok_request.js ├── error_request.js └── expected_report.yamlSKILL.md 是整个 Skill 的核心它告诉 AI 什么时候该启用这个 Skill、启用后按什么顺序执行、每一步做什么、输出什么格式。目录里的脚本是可选的加分项——如果你的 Skill 用法是对固定逻辑的重复操作比如解析 JSON挂个脚本让 AI 调用比让模型自己猜要稳定得多。我踩过的一个典型坑是早期 SKILL.md 写得太抽象比如分析请求并给出结论导致模型每次输出的格式都不一样。后来改成必须输出以下 YAML 结构字段不得缺失效果飞升。Skill 的第一要义是确定性不是创造性。3. 核心实现一条请求从粘贴到报告的全链路解析3.1 如何稳妥地解析 Copy as fetch 代码Copy as fetch 生成的代码格式大致长这样实测 Chrome 生成fetch(https://api.example.com/v1/users/1234, { headers: { accept: application/json, text/plain, */*, authorization: Bearer eyJhbGciOi..., x-request-id: 9f8be2c4-6d1e-4a87-b2f0-8e1a3d5a7b90 }, referrer: https://admin.example.com/users, referrerPolicy: strict-origin-when-cross-origin, body: {\page\:1,\limit\:20,\keyword\:\自动化\}, method: POST, mode: cors, credentials: include });注意几个容易忽视的点body是一个字符串化的 JSON不是对象。解析时要JSON.parse两次先解外层再解里层但有些请求 body 可能是 XML 或纯文本所以要做容错。headers里的authorization、cookie是敏感信息Skill 里要定义好脱敏规则报告里不要明文展示完整 token。有些请求会带priority、referrer等标注字段直接丢掉不影响重放但会干扰后续解析。建议做一次白名单过滤。我的解析脚本核心逻辑非常简单用正则提取 method、URL、headers、body再转成规范对象。实测下来不需要引入大型 AST 解析库Chrome 生成的 fetch 代码格式足够规整正则足以应对 95% 以上的场景。// parse_fetch.js —— 简化版核心逻辑 function parseFetchCode(code) { const method (code.match(/method:\s*([^])/) || [, GET])[1]; const url code.match(/fetch\(([^])/)[1]; const headersMatch code.match(/headers:\s*(\{[\s\S]*?\})/); const bodyMatch code.match(/body:\s*(.*?)(?,\s*method)/); let headers {}; if (headersMatch) { try { headers JSON.parse(headersMatch[1]); } catch(e) { /* 容错处理 */ } } let body null; if (bodyMatch) { try { body JSON.parse(JSON.parse(bodyMatch[1])); } catch(e) { body bodyMatch[1].slice(1, -1); } } return { method, url, headers, body }; }这个解析脚本更大的意义在于它把不确定的格式问题用确定性的代码解决掉了AI 只需在此基础上分析语义不需要在body 到底有没有解析对这种低级问题上浪费 token 和控制力。3.2 Skill 的 SKILL.md 该怎么设计SKILL.md 本质上是给 AI 的操作手册写得好不好直接决定这套流程稳不稳定。我的经验是要写步骤、写判断标准、写输出模板少写形容词不要写洞察问题本质这种抽象要求。下面是一个能落地的简化版参考# api-bug-analysis 用于分析用户粘贴的 fetch 请求代码自动重放并生成结构化 bug 分析报告。 ## 适用场景 - 用户提供一段从浏览器 DevTools 复制的 fetch 代码 - 用户要求检查接口返回异常、定位错误、输出可复现报告 ## 执行流程 1. 调用 parse_fetch.js 解析请求提取 method、url、headers、body。 2. 检查敏感字段并脱敏Authorization、Cookie 只保留前 8 和后 8 个字符。 3. 若环境允许调用 replay_request.js 重放请求若失败给出失败原因。 4. 将实际响应与请求意图对比标注状态码、响应耗时、异常字段。 5. 输出 YAML 报告格式必须严格遵循下方模板。 ## 输出模板 yaml request_summary: method: POST url: ... has_auth: true body_fields: [...] result: status_code: 500 duration_ms: 234 error_message: ... suspicious_fields: [...] reproduce_steps: - 粘贴以下 fetch 代码到 Console 重放 suggestions: - ...关键点在于**让 AI 明确知道每一步该做什么以及什么情况下可以跳过**。比如第 3 步若当前环境无法访问外网则跳过重放在报告中标记为未验证。没有这样的明确分支AI 会自作主张假装重放这是我在多个模型上实测发现的高频问题。 ### 3.3 辅助脚本为什么值得写 parse_fetch.js 这类脚本一定要写成可执行的 JS 文件而不是让 AI读一下然后自己处理。原因很简单**即使是同一个模型执行同一段解析逻辑输出的内容也可能有微小差异**——字段名缩写、类型判断、数字格式化这些小差异积累多了报告就会不稳定。 辅助脚本相当于给流程加了个物理护栏。脚本输出的是确定性的 JSONAI 只需要基于这个 JSON 做后续分析从自由发挥变成接力加工稳定性提升非常明显。 replay_request.js 的难点在于 Node.js 环境没有浏览器上下文很多请求带有用户的 cookie 和 CORS 上下文。我实测的解决办法是优先用不带自定义头的裸请求重放如果返回 401/403就在报告里标注为需要鉴权上下文无法无环境重放。这样做虽然牺牲了一部分自动化纯度但保证了报告的诚实性——**宁可标未验证也不要让 AI 编造一个成功的重放结果**。 ## 4. 实操过程从抓取到自动分析的一次完整演练 ### 4.1 第一步手动抓取一条失败请求 我用一个真实的项目场景来演示。假设管理后台的用户列表页点击查询时接口返回了 500页面弹了个系统繁忙请稍后重试的提示。 操作路径F12 打开 DevTools → Network 面板 → 勾选 Preserve log → 在页面上点击查询 → CtrlF 搜索那个 500 状态的请求 → 右键 → Copy → Copy as fetch。 注意如果你要复现的是某个操作触发的请求务必开着 Preserve log 提前操作否则页面一刷新请求记录就没了。这个细节看着基础但实际排查时我见过太多人因为没勾选导致丢失问题请求。 拿到的是这样一段代码敏感信息已脱敏 javascript fetch(https://api.example.com/v1/users/search, { headers: { accept: application/json, authorization: Bearer eyJhbGciOiJSUzI1NiIs...VuZCI6IjEifQ.eyJzdWIiOiIxMjM0NTY3... }, referrerPolicy: strict-origin-when-cross-origin, body: {\page\:1,\size\:10,\name\:\test\}, method: POST, mode: cors, credentials: include });4.2 第二步贴给绑定了 Skill 的 AI拿到这段代码后不需要做任何整理或标注直接粘贴给绑定了 api-bug-analysis Skill 的 AI附加一句请按 Skill 流程分析这条请求。AI 按流程跑完后会调用 parse_fetch.js 解析然后重放最后输出如下报告实测输出简化版request_summary: method: POST url: https://api.example.com/v1/users/search has_auth: true body_fields: [page, size, name] result: status_code: 500 duration_ms: 315 error_message: java.lang.NullPointerException: body.name is null suspicious_fields: - body.name 传入了字符串而非对象服务端按对象处理时 NPE reproduce_steps: - CodeSandbox/Console 中粘贴原 fetch 代码回车执行 - 观察响应体中的 exception 字段 suggestions: - 前端检查 body 参数结构name 字段疑似应为嵌套对象 - 后端给 name 增加空指针防御这份报告最有价值的点在于第二个字段body.name 传入了字符串而非对象。而这个结论是 AI 通过解析请求 重放对比 结合响应体异常信息推导出来的不是凭空猜测。如果只是把问题描述给 AI接口报错了帮我看看它大概率是给不出一致的答案的。4.3 第三步把报告接回现有工作流我现在的做法是把 AI 输出的 YAML 报告直接存成文件文件名规范是bug-{日期}-{接口名}.yaml然后通过脚本自动转换成协作工具里的一个 issue 草稿。整个过程从抓取到生成 issue熟练后大约 5 分钟而之前纯手工写一个清晰的 bug 描述加上沟通成本往往要 20 分钟以上。有人可能会问为什么不直接把原始 fetch 代码丢到 issue 里就行了我的体会是原始代码虽然无损但不可读。一份 500 行的 headers 堆叠对同事来说等于没写。结构化报告的意义在于——它保留了关键信息同时把可读性提了上来还附带 AI 的初步推断供人参考。人可以快速判断 AI 的结论靠不靠谱而不是重新梳理一遍原始请求。4.4 一个关键的实操原则环境标注重放成功和重放失败在报告里必须区分开。我见过有的方案把重放失败标成不能复现这个语义非常误导。我的习惯是在报告里多输出一个verification字段值为replayed_ok、replayed_failed或not_replayed三选一。这个字段在跨团队协作时特别重要。后端看到replayed_ok 明确的异常响应能直接进入排查看到replayed_failed第一反应是检查是不是缺少鉴权上下文而不是怀疑 bug 本身不存在。不谈验证方式就开始下结论是这类自动化分析工具最容易犯的毛病。5. 常见问题与排查技巧实录5.1 重放请求和浏览器行为不一致这是最常见的坑。浏览器里Copy as fetch生成的代码带有credentials: include在浏览器 Console 里重放会带上当前域名的 cookie所以行为基本一致。但如果在 Node.js 环境里重放cookie 就丢了接口大概率返回 401。我实测下来的解决方法是分层处理优先在浏览器 Console 中重放利用当前会话上下文。如果必须在 Node.js 重放把 cookie 手动加进 headers并注意 cookie 的有效期。如果失效了不要在报告里标注接口行为异常标注鉴权上下文缺失导致无法验证。简单说你的重放环境决定了重放结果的语义这一点一定要写进报告否则看报告的人会产生错误判断。5.2 headers 中的安全字段处理Copy as fetch 会把 Authorization、Cookie 等敏感信息完整带上。在本地自己调试没问题但一旦要把 fetch 代码或报告分享给同事、或者存进协作工具脱敏就是必须做的。我的脱敏规则保留前 8 字符和后 8 字符中间用***替换同时在报告的文件名上标注[sanitized]。这么做一方面保证信息可被识别能区分是哪个用户的 token、哪个环境另一方面避免明文敏感信息在协作系统里留存。另外一个细节不要只对报告脱敏原始 fetch 代码分享出去之前也应该脱敏。很多人直接把 Copy as fetch 结果原样发到工作群里这是安全上不必要的暴露。5.3 Skill 没被触发怎么办这是 Skill 工作流里比较恼人的问题。你定义好了 Skill但 AI 根本没加载它直接按通用套路回答了。我遇到过几次原因各不相同SKILL.md 开头没有写清触发条件模型不知道什么时候该拿这个 Skill 出来用。用户对话里没有提到和 Skill 相关的关键词模型没有关联到。AI 工具本身对 Skill 的自动加载有条件限制比如只针对某些目录或某些命令。我的应对策略在对话里显式指名请使用 api-bug-analysis Skill 来执行同时把 SKILL.md 里的触发条件写得非常具体列出哪些短语会触发加载。这套组合下来触发率稳定了很多。5.4 响应体超大或包含二进制文件有的接口返回 JSON 里有 base64 图片或大段日志直接塞给 AI 分析会浪费大量上下文窗口甚至导致后续分析质量下降。我的处理方式是在 replay_request.js 里加一个响应摘要逻辑只保留状态码、响应时长、content-type、body 的前 500 字符以及根据 error 关键字抓取到的异常片段。这样即使原响应有几百 KBAI 拿到的仍然是核心异常信息。这种做法也保证了报告的篇幅稳定不会出现一份报告把接口完整返回都贴进去的失控局面。下面整理一份排查速查表覆盖我这两周遇到的高频问题现象可能原因处理方式Node.js 重放返回 401缺少浏览器 cookie 上下文手动附加 cookie 或标注未验证重放结果和浏览器不一致请求头被 Node 环境过滤如 CORS 限制改用浏览器 Console 重放AI 分析结果不靠谱Skill 指令太抽象、没有给出判断标准在 SKILL.md 中补充明确分支和禁止事项报告里敏感信息泄露未在 Skill 流程中定义脱敏步骤增加脱敏节点分享前强制执行Skill 一直没被自动触发触发条件写得不明确显式指定使用 Skill 或修改触发关键词5.5 一个容易被忽略的坑Content-Length 头Copy as fetch 生成的代码有时候会带content-length头。如果你把这行代码原样拿去 Node.js 重放而且又手动改了 body 内容content-length 就和实际 body 长度不匹配服务端直接报 400。Chrome 生成时不带这头的请求倒是没这问题但如果有建议在解析脚本里直接过滤掉content-length和:authority这类伪头。我用 foreach 排查重放的返回结果时发现的根源是第一次用的 body 是{page:1,size:10}length 是 20后来换成了{page:1,size:20}实际长度变成 21但 headers 里还留着原来那个值不是 400 就是请求直接失败。把这个头从解析后统一删掉问题立刻消失。6. 这套方案还可以往哪些方向延伸做完Copy as fetch Skill这版之后我短期内不太会再往大了扩因为当前的价值已经很明确。不过有几个方向是我后续想尝试的也给读者一些参考批量处理一次给 AI 丢几十条来自同一次故障窗口的 fetch 代码让它做聚合分析找出共同失败模式。这比逐条提问高效得多适合排查一次发布后的批量报错。与自动化测试框架联动把 Skill 输出的结构化报告转成 pytest 或者 Playwright 的参数化测试用例。本质上报告里的reproduce_steps是半结构化的执行步骤转成用例代码需要一点胶水逻辑但可行性很高。团队级 Skill 库把项目中不同类型的常见问题登录态失效、参数错误、上游超时分别定义成独立 SkillAI 拿到 fetch 代码后自动分发到对应 Skill 去分析。这一步能有效提升分析的精准度但需要先把前置的分类逻辑设计好。我个人实际操作中最深刻的体会是这个组合里的每一半都不新鲜但把它们放在正确的位置上能产生一个很实用的偏差。Copy as fetch 负责无损提取事实Skill 负责约束 AI 的处理方式两者的共同点是去掉了人的模糊描述和 AI 的自由发挥。这大概就是我在日常排查链路里最想要的两个东西。如果你也在做类似的问题记录与自动化分析直接拿这套思路去搭一版复杂度比想象中低回报却非常快。
返回列表