前端面试题手册

梳理高频技术问题,帮助你按主题复习和查漏补缺。

前端阅读 05月30日 22:56

React、Vue、Angular 防 XSS 靠什么?哪些场景会失效?

直接回答React、Vue、Angular 都会默认把模板里的普通文本做 HTML 转义,所以把用户昵称、搜索词、评论摘要渲染成文本时,一般不会直接变成脚本执行。真正的风险通常出现在开发者主动绕过框架保护:React 的 dangerouslySetInnerHTML、Vue 的 v-html、Angular 的 bypassSecurityTrustHtml,以及把不可信数据拼到 URL、CSS、事件处理器或第三方组件配置里。框架能减少常见错误,但不能替你判断一段 HTML 是否可信,也不能保证后端、富文本编辑器、Markdown 渲染器和广告脚本都安全。防 XSS 更稳的做法是分层处理:默认用文本渲染;确实要展示富文本时先用 DOMPurify 这类白名单清洗;URL 只允许 https:、mailto: 等业务需要的协议;再用 CSP 限制脚本来源,降低漏网 payload 的执行概率。不要把“用了 React/Vue/Angular”当成免疫证书,XSS 往往就藏在为了赶需求开的那个逃生口里。必要代码import DOMPurify from 'dompurify';function SafeRichText({ html }: { html: string }) { const clean = DOMPurify.sanitize(html, { ALLOWED_TAGS: ['p', 'a', 'strong', 'em', 'ul', 'ol', 'li', 'code'], ALLOWED_ATTR: ['href', 'title', 'target', 'rel'] }); return <div dangerouslySetInnerHTML={{ __html: clean }} />;}这段代码的重点不是“用了 sanitize 就万事大吉”,而是把允许的标签和属性收窄。富文本业务经常要开放链接、图片或代码块,每多放一个标签,测试用例就要覆盖它的危险属性和协议。尤其是链接,javascript:、data:、奇怪大小写和编码绕过都要检查。追问React、Vue、Angular 的自动转义具体防住了什么?自动转义主要防住“把字符串当成 HTML 解析”的问题,例如用户输入 <img onerror=alert(1)>,框架会把尖括号转成文本显示。它适用于文本节点和大多数属性绑定,但前提是你没有主动要求框架把内容当 HTML 插入。边界在于 URL、CSS、SVG、iframe 等上下文的规则不同,单纯 HTML 转义不一定够。实际项目里最容易踩坑的是把搜索词、昵称这些看似普通的字段临时塞进富文本容器,结果绕过了默认保护。为什么 dangerouslySetInnerHTML、v-html 不能直接用?这类 API 的名字已经说得很直白:它们会跳过模板转义,把字符串交给浏览器按 HTML 解析。如果字符串来自 CMS、评论、客服消息、Markdown 或外部接口,就等于让外部数据参与页面结构生成。取舍点在于富文本确实需要这些 API,否则无法保留段落、链接和强调样式。正确做法不是完全禁用,而是把调用点集中封装,统一清洗、统一审计,避免每个业务组件各写一套临时逻辑。Angular 的安全机制是不是比 React、Vue 更强?Angular 对不同上下文有更细的安全模型,会区分 HTML、Style、URL、Resource URL,并在模板绑定时做相应处理。它的优势是默认约束更明确,团队不容易随手拼接危险模板。边界也很清楚,一旦使用 bypassSecurityTrust...,就是开发者声明“我保证这段内容可信”。踩坑常见于为了解决视频嵌入、富文本预览或老页面迁移而滥用 bypass,最后把安全责任从框架手里拿了回来。只靠前端框架防护够不够?不够,因为 XSS 的入口不一定只在当前前端项目里。后端模板、管理后台、第三方 SDK、富文本编辑器、Markdown 渲染、埋点脚本都可能把不可信数据重新带回页面。组合防护要同时有输出编码、富文本清洗、协议白名单、Cookie 的 HttpOnly/SameSite/Secure、CSP 和依赖升级。这样即使某一层漏掉,攻击者也不容易直接拿到会话或执行任意脚本。团队里怎么把这件事落地?最有效的办法是减少“自由发挥”的入口,例如只提供 SafeHtml、SafeLink、RichTextRenderer 这些经过审计的组件。代码评审重点看是否出现 innerHTML、outerHTML、document.write、字符串形式的 setTimeout、不受控的 iframe src。自动化层面可以加 ESLint 规则和 Semgrep 规则,把危险 API 变成需要解释的例外。边界是安全规则不能阻断正常业务,所以组件要给出可用替代方案,否则大家会绕过规则。
前端阅读 05月30日 22:56

whistle 代理工具适合解决哪些前端调试问题?

whistle 是基于 Node.js 的本地代理调试工具,常用来抓包、改请求、改响应、做接口 Mock、切换测试环境和调试移动端流量。它不像 Charles、Fiddler 那样主要依赖图形化操作,而是把很多能力放进规则文本里,适合前端团队沉淀一套可复制的调试方案。这个取舍很现实:规则可共享、可复用,但第一次配置代理、证书和规则时更容易出错。安装一般只需要 Node 环境:npm install -g whistlew2 startw2 status启动后默认控制台是 http://127.0.0.1:8899。浏览器或手机把 HTTP/HTTPS 代理指向运行 whistle 的机器和 8899 端口,就能看到请求列表。HTTPS 调试必须安装并信任根证书,否则只能看到 CONNECT 隧道,看不到明文请求和响应。常见规则可以这样写:api.example.com 127.0.0.1:3000https://api.example.com/user file:///Users/me/mock/user.jsonwww.example.com resHeaders://{cors}第一行适合把接口转到本地服务,第二行适合固定 Mock 响应,第三行常用于临时验证跨域响应头。whistle 适合快速定位和验证问题,但不适合替代正式网关、灰度平台或线上流量治理。规则越多,越要按项目和场景分组,否则后来的人很难判断异常响应来自后端,还是被本地代理改过。追问whistle 和 Charles、Fiddler 怎么选?如果只是偶尔看请求、导出 HAR 或给测试复现问题,Charles 这类图形化工具更容易上手。whistle 更适合开发团队,因为规则可以复制到文档,也方便做 Mock 和转发。它的边界是本地环境依赖更强,Node、系统代理、证书任一环节错了都会影响结果。实际项目里可以开发用 whistle,非技术同学继续用图形化抓包工具。HTTPS 抓包为什么经常看不到响应内容?最常见原因是没有安装或信任 whistle 的 HTTPS 根证书,浏览器只把请求当作加密隧道转发。第二个坑是 App 做了证书锁定,即使系统信任根证书也会拒绝中间人证书。还有一种情况是代理只配到浏览器,没有配到手机、模拟器或命令行进程。排查时先用普通 HTTPS 页面验证证书链,再调试目标 App。用 whistle Mock 接口有什么边界?Mock 适合验证前端分支、异常态和字段兼容,比如空列表、权限不足、接口超时。它不能证明真实接口契约完全正确,因为 Mock 数据很容易落后于后端变化。踩坑最多的是只 Mock 成功响应,结果上线后 401、429、500 分支没人处理。比较稳的做法是把常见错误码也做成规则,联调结束后再回真实环境验证一次。移动端调试时需要注意什么?手机代理地址要填电脑局域网 IP,不能填 127.0.0.1。如果公司网络有隔离策略,手机可能连不到电脑的 8899 端口,这时要换热点或确认防火墙放行。HTTPS 调试还要在手机上安装并信任证书,iOS 需要额外开启完全信任。调完后记得关闭手机代理,否则离开办公网络后会出现网页都打不开的假故障,也会误导后续排查。
前端阅读 05月30日 22:48

Whistle 如何做接口数据模拟,resBody 和 resScript 怎么选?

Whistle 做数据模拟,最常见的目标不是“造一份假数据”这么简单,而是让前端在后端未完成、接口异常、网络慢、登录态变化时都能继续开发。选方法时可以先问一句:这个响应是固定的,还是要根据参数、请求头、登录状态动态变化?固定数据用 resBody 和 Values 更省事,动态逻辑再上 resScript 或插件。固定响应用 resBody如果只是让某个接口返回一段稳定 JSON,resBody 是成本最低的方式。它适合登录信息、配置开关、列表空态、错误码等场景。为了可维护,不建议把很长的 JSON 直接写在规则行里,最好放到 Values 文件中。# 简短响应可以直接写api.example.com/api/ping resBody://{"code":0,"data":"pong"}# 复杂响应引用 Valuesapi.example.com/api/user resBody://{mock-user.json}{ "code": 0, "data": { "id": 1001, "name": "测试用户", "roles": ["admin"], "vip": true }}动态响应用 resScript当响应需要读取 query、body、cookie,或者要模拟分页、随机失败、延迟时,resScript 更合适。脚本里应该显式设置 Content-Type,并处理缺省参数,否则前端拿到的响应可能和真实接口差异太大。module.exports = function(req, res) { const page = Number(req.query.page || 1); const size = Number(req.query.size || 10); res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ code: 0, data: { list: Array.from({ length: size }, (_, i) => ({ id: (page - 1) * size + i + 1, title: `mock item ${i + 1}` })), page, total: 86 } }));};api.example.com/api/list resScript://{mock-list.js}异常和慢接口也要模拟只模拟成功态是不够的,真实联调里更容易出问题的是超时、空列表、权限失败、字段缺失。可以准备几套 mock:success、empty、error、timeout,让前端页面在这些状态下都跑一遍。这样做比等后端临时改数据稳定,也更容易在评审前发现边界问题。module.exports = function(req, res) { const type = req.query.type || 'success'; res.setHeader('Content-Type', 'application/json'); if (type === 'timeout') { return setTimeout(() => res.end(JSON.stringify({ code: 0, data: [] })), 3000); } if (type === 'error') { res.statusCode = 500; return res.end(JSON.stringify({ code: 500, message: 'mock server error' })); } res.end(JSON.stringify({ code: 0, data: [{ id: 1, name: 'ok' }] }));};多人协作时怎么放 mock 数据?团队共用 mock 不要散落在每个人的 Whistle 面板里,建议放进仓库并按业务目录组织。规则文件可以只写入口,mock 文件按接口域名或业务模块归档,例如 mock/user/profile.json、mock/order/list.js。这样评审时能直接看到字段变化,也方便后端一起确认返回结构。公共 mock 还可以配一份变更记录,说明字段新增、删除和默认值变化,避免旧页面继续依赖已经废弃的字段。规则文件只保留入口,具体 JSON 和脚本放在 mock/user、mock/order 之类的目录。每个 mock 文件最好说明对应接口、字段含义和适用场景,避免后端字段变了而 mock 还在误导前端。对于登录、权限、金额这类敏感链路,还要保留一份失败态样例,否则页面只在成功路径上好看,真实联调时很容易暴露遗漏。追问resBody 和 Values 应该怎么选?短小、一次性的响应可以直接写 resBody,超过几行的 JSON 建议放 Values。取舍是内联写法最快,但可读性和复用性很差。边界是包含数组、嵌套对象或多人复用的数据,基本都应该拆成文件。踩坑是 JSON 里引号转义写错,规则看似保存成功,实际响应格式已经坏了。什么时候必须用 resScript?只要响应依赖请求参数、分页、登录态、时间或随机异常,就应该考虑 resScript。取舍是脚本更灵活,但也更像一段小服务,需要处理异常和维护逻辑。边界是不要在脚本里实现完整后端业务,否则 mock 会变成另一套难维护系统。踩坑是脚本返回字段和真实接口越来越不一致,前端在 mock 下正常,上测试环境马上报错。要不要模拟失败和超时?要,尤其是移动端弱网、权限过期、空数据这些用户很容易遇到的状态。取舍是多准备几套 mock 会增加工作量,但能提前发现 loading、重试、错误提示是否合理。边界是不要为了覆盖所有理论错误码而无限膨胀,优先模拟产品真的会展示差异的状态。踩坑是只测成功响应,结果接口 500 时页面白屏,直到上线前才发现。mock 数据应该由前端还是后端维护?初期可以由前端维护,因为前端最需要快速推进页面;接口稳定后最好和后端一起确认字段。取舍是前端维护速度快,后端确认准确性高。边界是涉及金额、权限、状态机的字段不能凭感觉编,必须和接口文档对齐。踩坑是 mock 里的枚举值写成了前端自创格式,后端真实返回后所有判断都失效。复杂模拟要不要做成插件?如果只是几个接口,resScript 已经够用;如果要统一管理大量场景、提供 UI 切换、记录请求,插件会更合适。取舍是插件体验更完整,但开发和发布成本更高。边界是团队复用、长期维护、需要状态管理时才值得插件化。踩坑是把简单 mock 过早做成插件,最后每次改一个字段都要发版,反而拖慢联调。
前端阅读 05月30日 22:48

如何开发 Whistle 插件,基本目录和入口逻辑怎么设计?

开发 Whistle 插件时,先别急着写复杂的拦截逻辑。一个好插件至少要回答三件事:它提供什么协议或规则能力,配置从哪里来,出错时怎样不影响正常代理。插件适合做团队可复用的能力,比如统一鉴权头、动态 mock、请求审计、环境面板;如果只是临时改一个接口,用普通 rules 和 values 更轻。插件项目应该长什么样?Whistle 插件本质上是一个 npm 包,包名通常使用 whistle.xxx 或团队约定的插件名。最小结构包括 package.json、入口文件、可选的 rules、values、README。入口文件负责注册服务逻辑,配置文件负责描述插件名称、菜单、规则等元信息。mkdir whistle.demo-helpercd whistle.demo-helpernpm init -ymkdir lib testtouch index.js README.md{ "name": "whistle.demo-helper", "version": "0.1.0", "main": "index.js", "whistleConfig": { "name": "demo-helper", "description": "team debug helper" }}入口逻辑怎么写?插件入口不要把所有事情都塞进一个巨大函数。建议把路由、配置读取、数据生成、错误处理拆开,入口只做组装。请求处理时要注意异步错误,任何未捕获异常都可能让调试体验变得很差。module.exports = function(server, options) { server.get('/cgi-bin/ping', function(req, res) { res.json({ ok: true, name: 'demo-helper' }); }); server.on('request', function(req) { req.headers['x-debug-from'] = 'whistle-plugin'; });};这个例子只演示结构,真实项目里还应该把 header 名称、开关和目标域名做成配置,而不是写死。插件越通用,越要减少默认侵入性,让使用者通过规则明确启用。在规则里如何启用插件?安装本地插件可以用 npm link 或 Whistle 的安装命令。这里要先约定插件名称和规则写法,否则同一个插件在不同同学机器上可能出现“装了但没命中”的情况。建议 README 里放一条最小可验证规则,再配一个 /cgi-bin/ping 检查入口,避免把安装问题误判成业务代理问题。调试阶段推荐本地链接,发给团队使用前再发布到私有 npm 或写清楚安装方式。规则里通过 plugin:// 或插件提供的协议启用,具体取决于插件能力设计。npm linkw2 install demo-helperw2 restart# 只对指定接口启用插件,避免全局污染api.example.com/api/order plugin://demo-helper插件里常见能力怎么拆?如果是动态 mock,建议把数据模板、参数解析、延迟和错误比例拆成独立模块。目录上可以保留 lib/mock、lib/config、lib/routes 这类清晰边界,让入口文件只负责装配。这样后续增加新接口时,不会把所有逻辑都堆进 index.js。如果是请求审计,建议只记录必要字段,例如 URL、方法、状态码、耗时,不要默认落敏感 header 和 body。如果是团队面板,可以提供 /cgi-bin/* 接口给前端页面读取配置,但要避免无鉴权暴露内部信息。追问什么时候该写插件,什么时候只写规则?一次性的 host、mock、header 修改用规则更合适,写插件反而增加维护成本。取舍在于插件能复用、可封装复杂逻辑,但发布、版本和兼容性都要有人负责。边界可以这样定:需要参数化、多人复用、包含 UI 或复杂状态时再考虑插件。踩坑是为了一个临时接口写插件,最后没人维护,Whistle 升级后还会拖累团队环境。插件默认要不要全局生效?通常不要,默认全局生效很容易误伤无关请求。取舍是全局生效配置简单,但排查问题时很难判断某个 header 或响应是不是插件改的。边界是审计、日志类插件可以全局观察,但修改请求或响应的逻辑最好通过规则显式启用。踩坑是插件给所有请求加了测试 header,结果第三方接口因为非法 header 拒绝访问。插件配置应该放在哪里?稳定默认值可以放 package.json 或代码常量,团队可变配置建议放 rules、values 或单独配置文件。取舍是代码内置最可靠,但每次调整都要发版;外部配置灵活,但需要校验和文档。边界是密钥、token、生产 Cookie 不应该进入插件包。踩坑是插件读取不到配置时静默使用默认生产域名,调试请求被转到了错误环境。插件如何处理错误才安全?插件内部要捕获异步错误,并给出可观察的日志或降级响应。取舍是直接抛错能尽快暴露问题,但会影响代理链路;降级更稳,但不能把错误吞得毫无痕迹。边界是 mock 类插件可以返回明确错误,审计类插件失败时应尽量不阻塞原请求。踩坑是读文件、查数据库这类操作用同步阻塞方式写在请求路径里,流量一大 Whistle 控制台也会变卡。本地插件怎么给团队使用?开发阶段用 npm link 最快,团队使用建议发布到私有 npm,并固定版本号。取舍是本地链接便于调试,但每个人机器状态不同;包管理方式更稳定,但需要发版流程。边界是不要让团队依赖某个同学电脑上的本地路径。踩坑是 README 只写了安装命令,没有写规则示例和验证方法,新同学装完也不知道插件是否生效。
前端阅读 05月30日 22:48

如何用 Whistle 调试移动端 App,代理和证书怎么配置?

用 Whistle 调试移动端应用,本质是让手机的 HTTP/HTTPS 流量先经过电脑上的 Whistle,再由 Whistle 转发到真实服务或 mock 服务。步骤不难,难点通常在三处:手机连不到电脑代理、HTTPS 证书没被系统信任、App 自己做了证书绑定。只要按顺序排查,移动端抓包和改包会稳定很多。先确认电脑端 Whistle 可访问电脑上启动 Whistle,默认端口是 8899。如果团队里端口有冲突,可以显式指定端口,但手机代理里也要填同一个端口。启动后先在电脑浏览器打开 http://127.0.0.1:8899/,确认控制台能进入。w2 start -p 8899w2 status# macOS 查看局域网 IPipconfig getifaddr en0# Windows 查看 IPv4ipconfig手机和电脑必须在同一个网络里,常见地址类似 192.168.1.23 或 10.0.0.8。如果公司 Wi-Fi 开了客户端隔离,手机即使和电脑连同一个热点,也可能访问不到电脑端口,这时可以换个人热点或使用 USB/模拟器方案。手机代理怎么配?iOS 进入当前 Wi-Fi 的详情页,在 HTTP 代理里选择“手动”,服务器填电脑局域网 IP,端口填 8899。Android 一般在 Wi-Fi 的“修改网络”或“代理”设置里填写同样的信息,不同厂商入口会有差异。配置完成后,用手机浏览器访问 http://电脑IP:8899/,能打开 Whistle 页面才说明链路通了。如果手机访问不了,先不要急着改规则。检查电脑防火墙、VPN、公司安全软件、端口是否监听在正确网卡上。也可以在电脑上临时换端口启动,例如 w2 start -p 8888,排除端口被占用的问题。HTTPS 证书怎么安装?HTTP 请求能看到不代表 HTTPS 能解密。要查看 HTTPS 内容,需要在手机上安装并信任 Whistle RootCA。手机访问 http://电脑IP:8899/,进入 HTTPS 页面下载证书;iOS 安装描述文件后,还要到“关于本机 - 证书信任设置”里开启完全信任;Android 则需要安装为用户证书,部分高版本系统对 App 信任用户证书有限制。# 移动端调试常用规则示例api.example.com/api/user resBody://{mobile-user.json}m.example.com reqHeaders://{mobile-headers.json}app.example.com/api/* host 192.168.1.23:3000如何验证规则真的生效?先用手机浏览器访问一个简单接口,看 Whistle 的 Network 面板是否出现请求。再加一条低风险的响应头或 mock 规则,确认响应确实被改写。不要一开始就调试复杂 App,否则你很难判断问题出在代理、证书、规则还是 App 网络库。{ "code": 0, "data": { "from": "whistle-mobile", "login": true }}追问手机访问不了 Whistle 控制台怎么办?先确认手机和电脑在同一网段,再检查电脑防火墙是否拦截了 8899 端口。取舍上,关闭防火墙排查最快,但长期使用应该只放行 Whistle 端口而不是全关。边界是公司网络可能禁止设备互访,这种情况下继续改 Whistle 规则没有意义。常见踩坑是电脑开着 VPN,手机填的却是局域网不可达的虚拟网卡地址。为什么 HTTPS 证书装了还是看不到内容?可能是证书没有被完全信任,也可能是 App 不信任用户安装的根证书。取舍是浏览器调试成本最低,但真实 App 尤其是金融、支付类应用更可能做证书绑定。边界是 Whistle 不能绕过所有安全策略,遇到 certificate pinning 需要换调试包、关闭 pinning 或使用专门的测试构建。踩坑是只安装了证书文件,却忘了在 iOS 里开启“完全信任”。Android 能不能不用 Wi-Fi 代理?可以在部分场景下用模拟器代理,或通过 ADB 做端口转发,但真实设备的系统代理仍然最直观。取舍是 Wi-Fi 代理配置简单,ADB 方案更适合本地开发机和模拟器联调。边界在于 adb reverse tcp:8899 tcp:8899 只能解决一部分访问方向问题,不等于所有 App 流量都会自动进 Whistle。踩坑是以为 USB 连上就能抓包,结果 App 仍然走移动网络或直连。某些 App 请求完全不出现是什么原因?可能是 App 没走系统代理、用了私有网络库、开启了 QUIC,或者请求走了 WebSocket/长连接。取舍是系统代理对 H5 和普通 HTTP 客户端很友好,但对强安全原生 App 不一定够用。边界是生产包的网络安全策略通常更严格,调试时最好使用测试包。踩坑是只盯着 HTTPS 证书,忽略了 App 可能根本没有把流量发到代理。调试结束后需要恢复哪些设置?至少要关闭手机 Wi-Fi 代理,必要时删除或停用 Whistle 证书,并停止本机 Whistle 服务。取舍是保留代理下次调试更省事,但日常使用容易导致网络变慢或访问失败。边界是公共网络和非调试场景不要长期挂代理。踩坑是下班后手机还连着电脑代理,第二天电脑没开,手机所有网页都打不开。
前端阅读 05月30日 22:48

Whistle 规则如何管理,团队协作时怎样避免配置冲突?

Whistle 的规则管理不要只理解成“谁在网页里改几行配置”。个人调试时,Web 界面足够快;团队协作时,真正麻烦的是规则来源、环境切换、命名规范和回滚机制。如果这些没有约定,今天 A 同学为了联调把接口代理到本地,明天 B 同学拉到同一份规则后就可能误连错环境。规则应该放在哪里管理?日常临时调试可以直接打开 http://127.0.0.1:8899/,在 Rules 面板里写规则并保存,适合验证某个接口、替换一个静态资源、临时 mock 一段响应。它的好处是所见即所得,Network 面板马上能看到命中情况;缺点是改动容易散落在个人机器上,别人不知道你改了什么。团队长期使用时,建议把公共规则放到 Git 仓库,个人规则留在本地。公共规则只放稳定的域名代理、公共 mock、跨域头、常用环境入口;个人规则放本地端口、临时调试、风险较高的 host 覆盖。这样既能共享经验,也不会把每个人电脑上的实验配置带给全组。# 常用启动与检查w2 start -p 8899w2 statusw2 restartw2 stop# 如果需要指定规则文件启动w2 start -f ./rules-dev规则文件怎么组织更适合协作?一份可维护的规则文件,应该先按业务或环境分组,再按命中范围从小到大排列。更具体的路径规则放在前面,宽泛的通配符和正则放在后面,否则容易出现“看起来写了规则,但一直没命中”的问题。注释不要写成流水账,最好说明这条规则解决什么问题、谁在使用、什么时候可以删除。# user-service: 本地联调用户接口,owner: frontend-userwww.example.com/api/user host 127.0.0.1:3001# mobile-h5: 移动端静态资源走测试 CDNm.example.com/static/* host test-cdn.example.com# mock: 登录态过期响应,仅用于异常状态验证www.example.com/api/session resBody://{session-expired.json}团队共享时推荐什么流程?比较稳妥的方式是建一个 whistle-rules 仓库,把 rules-dev、rules-test、values、README.md 放进去。新同学克隆仓库后,用软链接或启动参数指向对应规则文件;改公共规则时走 Pull Request,至少让相关业务同学看一眼。不要直接让所有人共用同一个可写文件,否则一次错误保存就会影响整组。git clone git@example.com:team/whistle-rules.git ~/whistle-rulesln -sf ~/whistle-rules/rules-dev ~/.whistle/rulesw2 restartValues 和环境变量怎么配合?Values 适合放可复用的 mock 数据和变量,例如本地域名、端口、通用响应体。环境差异很大的内容不要硬塞进一份文件,可以拆成 values-dev.json、values-test.json,再通过文档说明切换方式。敏感 token、Cookie、内网账号不要提交到仓库,最多提供字段模板。{ "localApi": "127.0.0.1:3001", "corsHeaders": { "access-control-allow-origin": "*", "access-control-allow-credentials": "true" }}追问公共规则和个人规则怎么划分?公共规则放团队都需要、行为稳定、风险可控的配置,个人规则放本地端口、临时 mock 和实验性代理。取舍点在于共享越多,上手越快,但误伤范围也越大。边界可以定得很明确:会影响真实登录、支付、下单、生产域名的规则,默认不进公共文件。常见踩坑是把自己本地 127.0.0.1 的代理提交上去,别人一拉规则接口就全挂。规则顺序冲突时怎么排查?先在 Network 里看请求是否命中预期规则,再把精确路径放到通配符前面,必要时临时注释掉宽泛规则验证。取舍是规则写得越通用越省事,但排查时越难判断谁覆盖了谁。边界上,不建议用一个 *.example.com * 之类的大范围规则解决所有问题。踩坑最多的是正则和通配符混用后,以为后面的精确规则会覆盖前面的宽泛规则。要不要把 whistle 规则纳入代码评审?如果规则会影响多人联调,就应该评审,至少确认域名、路径、mock 数据和删除时间。取舍是评审会增加一点流程成本,但能减少半天都查不出的代理误配。边界可以放宽在个人规则和临时验证上,这类不需要走 PR。踩坑是没有 owner 的规则越积越多,半年后没人敢删,最后变成第二套隐形环境配置。多环境切换用复制文件还是启动参数?少量环境可以复制文件后 w2 restart,但团队协作更推荐保留多个规则文件,用启动参数或软链接切换。取舍在于复制文件直观,启动参数更可追溯。边界是不要在同一份规则里同时启用 dev、test、prod 三套代理,除非你能保证域名完全隔离。踩坑是切完环境忘记重启 whistle,或者浏览器缓存让你误以为规则没生效。规则里能不能放敏感信息?不建议放,尤其是 Cookie、Authorization、内部账号和生产 token。取舍是写进去调试最快,但一旦提交仓库或截图分享,泄露成本很高。边界是公共仓库只允许放示例值和字段结构,真实值放个人本地 Values 或环境变量。踩坑是 mock 登录态时顺手贴了真实 Cookie,后来被多人复用,排查权限问题会非常混乱。
前端阅读 05月30日 22:48

whistle 如何用脚本处理请求响应并避开常见坑?

whistle 的脚本能力适合处理规则表达不了的逻辑,比如按请求参数动态改 header、根据用户身份返回不同 mock、给响应体追加字段,或者把线上接口临时改造成前端需要的数据形状。规则更像声明式配置,脚本则是命令式处理;能用规则解决的别急着写脚本,因为脚本越多,调试成本和副作用也越高。它的边界也很明确:脚本运行在代理链路里,任何慢逻辑都会拖慢请求,任何不严谨的匹配都可能影响无关流量。先准备一个本地脚本文件,例如 change-user.js:module.exports = (req, res) => { req.headers['x-debug-user'] = '10001';};在 Rules 中绑定到目标接口:https://api.example.com/user reqScript:///Users/me/whistle/change-user.js响应处理通常用于 mock 或修正字段,示例只处理 JSON,避免误伤图片、HTML 或二进制内容:module.exports = (req, res) => { const type = res.headers['content-type'] || ''; if (!type.includes('application/json')) return; const data = JSON.parse(res.body || '{}'); data.debug = true; res.body = JSON.stringify(data);};脚本最好和规则一起放进项目的调试目录,文件名说明用途,例如 mock-login-expired.js、add-debug-header.js。团队协作时要写清楚启用条件,不要让别人打开 whistle 后默认命中你的个人调试逻辑。追问reqScript 和 resScript 应该怎么选?需要在请求发出前改 URL、header、cookie 或 body,就用 reqScript;需要在服务端返回后改状态码、响应头或响应体,就用 resScript。取舍点在于问题发生的位置:鉴权参数错了通常改请求,接口字段不满足前端联调通常改响应。踩坑最多的是在 resScript 里试图修正已经发出去的请求参数,这时后端早就处理完了。判断不清时先在 Network 里看请求和响应,确认要动哪一侧。脚本里处理 JSON 响应要注意什么?第一步永远是判断 content-type,不要默认所有响应都是 JSON。边界包括空响应、压缩响应、流式响应、图片和下载文件,这些内容被强行 JSON.parse 很容易报错或损坏。更稳的写法是只匹配明确接口,并对解析失败做兜底,不要让一个异常中断整个代理处理。调试阶段可以打印 URL 和错误信息,但长期使用要减少日志,避免控制台被刷屏。为什么不建议所有 mock 都用脚本写?脚本很灵活,但灵活也意味着行为不够直观。简单固定响应用 resBody 或 Values 更容易维护,复杂条件分支、按参数返回不同数据时再上脚本。取舍标准是“别人打开规则能不能一眼看懂”,如果必须读几十行 JS 才知道接口返回什么,维护成本就偏高。常见坑是脚本越写越像小服务,最后不如直接起一个本地 mock server。脚本影响了无关请求怎么办?先收窄 Rules 匹配范围,不要用过宽的域名或通配符挂脚本。脚本内部也可以二次判断路径、方法和参数,条件不满足立刻 return。边界是代理层没有业务上下文,不能只凭一个字段就假设请求属于某个页面。排查时先禁用脚本确认问题消失,再逐步恢复匹配条件和处理逻辑。团队里怎么管理这些调试脚本?建议把通用脚本放进仓库的 debug/whistle 目录,只提交脱敏、可复用的版本,个人临时脚本放在本机不共享。配置里不要写真实 token、内网账号或客户数据,必要时用环境变量或本地 Values 注入。取舍是共享脚本能提升联调效率,但也可能把个人调试假设扩散给全团队。每个脚本顶部写两三行用途、命中接口和关闭方式,比事后在群里解释更省时间。
前端阅读 05月30日 22:48

whistle 如何捕获请求并快速过滤定位问题?

whistle 捕获请求的核心流程是:启动本地代理,让浏览器、App 或命令行流量经过它,然后在 Network 面板查看请求、响应、耗时、头信息和匹配规则。它不像浏览器 DevTools 只看当前页面,而是能统一观察多端流量,尤其适合排查 H5、客户端内嵌页、Node 服务请求和第三方 SDK 调用。使用前要明确边界:whistle 只能看到走代理的流量,系统代理没配好、App 不信任证书、命令行绕过代理时,Network 面板自然不会出现请求。先启动服务并打开管理页:npm i -g whistlew2 start -p 8899open http://127.0.0.1:8899/浏览器可以直接配置 HTTP/HTTPS 代理为 127.0.0.1:8899,命令行请求可以这样验证:export HTTP_PROXY=http://127.0.0.1:8899export HTTPS_PROXY=http://127.0.0.1:8899curl -I https://example.com如果要看 HTTPS 明文内容,需要安装并信任 whistle 根证书。证书只用于本机调试,别在公共设备或不可信网络里随便安装;调试结束后可以关闭代理,避免正常访问也继续经过 whistle。Network 面板里最常用的是域名、路径、方法、状态码和关键字过滤。排查接口失败时,先用域名缩小范围,再用 status:500、method:POST、接口路径片段继续收窄。遇到请求太多的页面,直接清空列表后复现一次,比在几千条历史记录里搜索更可靠。追问为什么已经配置代理却抓不到请求?先确认流量来源是否真的走了 127.0.0.1:8899,浏览器、系统、App 模拟器和命令行各有自己的代理设置。取舍上,浏览器调试最简单,移动端调试更接近真实场景但证书和网络环境更容易出问题。常见坑是 App 使用了证书锁定、系统代理被 VPN 覆盖,或者 Node 请求库显式禁用了代理。可以先用 curl 走代理验证 whistle 正常,再回到具体客户端排查。Network 里请求太多,怎么快速定位目标接口?不要一上来搜索很短的词,比如 api 或 user,这会把噪音也带进来。更稳的做法是按域名、路径片段、请求方法、状态码逐层过滤,最后再看请求体或响应体。边界是过滤条件越多,越可能把真正的异常请求排除掉,所以每次收窄都要确认列表数量是否合理。踩坑时可以先清屏,再触发一次具体操作,让目标请求出现在最新的几条里。HTTPS 请求显示 CONNECT 或看不到响应体怎么办?这通常是证书没有安装、没有被系统信任,或者客户端不接受用户证书。浏览器调试时安装 whistle 证书一般就够了,Android 7 之后的 App 可能还需要应用允许用户证书,部分金融或安全类 App 会做证书锁定。取舍是:普通业务调试可以信任本机证书,涉及敏感账号和生产数据时应尽量用测试环境。不要为了抓包去关闭应用安全校验并提交到正式包,这是非常典型的安全事故源头。如何用 whistle 判断问题在前端还是后端?先看请求是否发出、URL 和参数是否正确,再看后端返回的状态码、响应体和耗时。若请求没发出,多半是前端逻辑、跨域预检或网络配置问题;若请求正确但响应错误,就要看服务端日志或网关链路。一个实用取舍是临时用规则 mock 一个成功响应,如果页面恢复正常,说明前端渲染链路大概率没问题。反过来,如果 mock 成功响应页面仍异常,就要查前端数据解析或状态管理。过滤和搜索有什么踩坑点?过滤是为了缩小列表,搜索是为了在已有列表里找内容,两者不要混用。很多人只搜响应关键字,却忘了请求还没被捕获或已经被过滤条件排除,结果误以为接口没返回。另一个坑是缓存,请求可能直接走浏览器缓存,Network 里看不到你期待的接口变化。排查时可以禁用缓存、加随机参数,或者在 whistle 里观察状态码和响应头是否真的来自服务端。
前端阅读 05月30日 22:48

whistle Values 如何管理多环境配置和 mock 数据?

whistle 的 Values 可以理解成一份可复用的变量仓库,用来存放域名、端口、token、mock JSON、响应片段等配置。规则里用 {key} 引用后,同一份值可以被多条规则复用,切环境时只改 Values,不用把规则逐行改一遍。它最适合处理“规则稳定但数据经常变”的场景,比如本地、测试、预发三套接口地址,或者同一个接口在不同用例下返回不同响应。边界也要先说清楚:Values 不是数据库,不适合放大量动态数据,更不要放生产密钥;它解决的是代理调试里的配置复用问题。常见启动方式如下,先确认 whistle 正常运行,再进入 http://127.0.0.1:8899/ 管理界面。npm i -g whistlew2 start -p 8899w2 status在 Values 面板里可以创建 env.json,内容保持简单、稳定:{ "apiHost": "http://127.0.0.1:3000", "testHost": "https://test.example.com", "userId": "10001", "profileMock": { "name": "Tom", "role": "admin" }}规则中再引用这些值:^https://api.example.com/(.*) {apiHost}/$1https://api.example.com/user?id={userId} resBody://{profileMock}这个写法的好处是规则仍然表达“流量怎么转发”,Values 只负责“具体值是什么”。如果团队多人共用,建议把 key 命名成 env.apiHost、mock.profile.admin 这类层级语义,避免 host1、data2 这种几天后没人敢动的名字。追问Values 和 Rules 应该怎么分工?Rules 管流量匹配、转发、替换和注入,Values 管可复用的数据。取舍标准很简单:如果一段内容会被多条规则引用,或者经常随环境变化,就放到 Values;如果它只服务一条规则,直接写在 Rules 里反而更直观。踩坑最多的是把整套规则都“变量化”,最后打开规则只看到一堆 {xxx},排查时必须来回切面板。Values 应该降低重复,不应该降低可读性。多环境配置怎么切换最稳?建议为不同环境建独立 Values,例如 local.json、test.json、pre.json,每份保持相同 key,只替换 value。这样规则文件不用变,切换时只启用对应 Values,团队成员也容易对齐。边界是同一时间不要启用多份同名 key 的 Values,否则后加载或更高优先级的值会覆盖前面的值,表现像“规则偶尔失灵”。如果必须临时覆盖,最好在 key 名里写清楚 override,用完立刻关闭。Values 里能不能放接口 mock 响应?可以,尤其适合体积不大的 JSON 响应、错误码、空列表、权限状态等固定场景。取舍在于维护成本:几十行以内的 mock 放 Values 很方便,几百行甚至带复杂逻辑时,应该改用文件、插件或脚本处理。常见踩坑是 JSON 少了引号或多了尾逗号,规则没有明显报错,但响应内容就是不对。写 mock 时先用 JSON 校验工具检查,再用 Network 面板确认最终响应体。Values 适合保存 token 和账号信息吗?临时调试 token 可以放,但不建议长期保存真实生产凭据。whistle 是本地代理工具,团队共享配置、截图或导出时很容易把敏感值带出去。更稳的做法是只保存占位符,例如 {debugToken},真实值由个人本地单独维护,或者在脚本里从环境变量读取。边界是测试环境的低权限 token 可以接受,生产管理员 token 不应该进入 Values。Values 不生效时怎么排查?先看 key 是否拼错,再看对应 Values 是否启用,最后看规则命中是否符合预期。可以把响应临时改成固定文本验证引用是否成功,例如 resBody://{profileMock},比直接排查完整代理链更快。另一个坑是值里包含特殊字符、换行或 URL 参数时没有正确转义,导致规则解析和预期不同。排查时一次只改一个变量,并在 Network 里查看实际请求 URL、响应头和响应体。
前端阅读 05月30日 22:48

whistle 支持哪些协议?HTTP、HTTPS、WebSocket 怎么代理?

Whistle 常用于 HTTP 调试,但它能处理的并不只有普通 HTTP 请求。前端和移动端排查里,常见的是 HTTP、HTTPS、WebSocket、HTTP/2 以及 SOCKS 或上游代理。理解这些协议的差异,比背规则更重要:HTTP 明文好改,HTTPS 需要证书信任,WebSocket 建连后是长连接,HTTP/2 可能在代理链路里被降级。协议边界没弄清,规则看似正确,请求也可能不按预期走。HTTP 最直接,可以替换 host、改请求头和响应体,适合本地联调和 Mock。www.example.com host 127.0.0.1:8080http://www.example.com/api/user resBody://{"code":0}http://www.example.com/api/user reqHeaders://{"x-debug":"1"}HTTPS 多了一层证书。浏览器先和代理建立 CONNECT,再由 whistle 解密转发;没有信任根证书时,只能看到隧道,看不到路径和响应。调试前先启动服务并按页面提示安装证书:w2 start -p 8899# 浏览器访问 http://127.0.0.1:8899,下载并信任根证书HTTPS 的坑主要有三个:移动端证书信任策略不同;部分 App 做了证书固定;生产登录、支付链路不该随便关闭校验。调试时可以只匹配目标域名,不要用过宽规则影响全部流量。WebSocket 也是 whistle 很有价值的场景。它先通过 HTTP Upgrade 建立连接,之后变成双向消息流,因此排查时既要看握手,也要看消息内容。ws://socket.example.com host 127.0.0.1:7001wss://socket.example.com host 127.0.0.1:7001HTTP/2 和 SOCKS 更像链路兼容问题。很多代理工具会把 HTTP/2 在中间链路降到 HTTP/1.1,这通常不影响接口语义,但会影响多路复用、头压缩和性能判断。SOCKS 适合把流量再转给公司代理、远程调试机或特定网络出口,改包能力仍然发生在 whistle 这一层。api.example.com socks://127.0.0.1:1080api.example.com proxy://http://127.0.0.1:8888追问HTTP 和 HTTPS 代理规则写法一样吗?大部分匹配和改写规则看起来一样,但 HTTPS 能否生效取决于证书信任和解密权限。HTTP 请求是明文,whistle 可以直接看到路径、header 和 body;HTTPS 如果只建立了 CONNECT 隧道,就只能看到域名和连接信息。取舍是安全性和可调试性:本地排查可以信任证书,生产或敏感链路不要随意解密。遇到规则不生效,先确认是不是根本没拿到 HTTPS 明文。WebSocket 代理为什么有时只能看到连接,看不到消息?可能是规则只命中了握手域名,没有命中实际的 wss 地址,也可能是客户端走了不同端口或备用域名。WebSocket 建连成功后是长连接,页面刷新、重连和心跳都会影响观察结果。另一个常见坑是消息被业务层压缩或加密,代理能看到帧,但看不懂业务内容。排查时先验证 Upgrade 状态,再看消息方向和重连次数。HTTP/2 被代理后降级会不会影响测试结论?如果只是验证接口返回、Mock 数据和 header,通常影响不大。若你在排查性能、连接复用、服务端推送或 gRPC 类场景,降级就可能改变结论。whistle 更适合做功能调试和流量改写,不适合替代专门的协议性能分析工具。边界看测试目标:测业务语义可以接受,测协议特性就要谨慎。SOCKS、proxy 和 host 规则怎么选?host 适合把目标域名指到本地或测试机,最直观也最常用。proxy 适合把请求交给另一个 HTTP 代理,socks 适合走公司网络、远程环境或特定出口。不要把三者叠太多层,否则失败时很难判断是哪一层断了。建议先用 host 跑通,再按网络限制加上游代理。多协议混合项目应该怎么写规则?不要用一个大规则覆盖所有域名,应该按协议和业务域名拆开。HTTP API、HTTPS 登录、WebSocket 推送、静态资源最好分别写,必要时加注释说明用途。这样做的成本是规则文件稍长,但排查时能快速关闭某一段,不会影响其他流量。尤其是移动端项目,登录和长连接经常共享域名,规则过宽很容易制造假故障。