ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

axios 仓库贡献规范深读:AGENTS.md 如何统一定义人与 AI Agent 的工程实践

axios 仓库贡献规范深读:AGENTS.md 如何统一定义人与 AI Agent 的工程实践 axios 仓库贡献规范深读AGENTS.md 如何统一定义人与 AI Agent 的工程实践【免费下载链接】axiosPromise based HTTP client for the browser and node.js项目地址: https://gitcode.com/GitHub_Trending/ax/axiosaxios 是一个面向浏览器与 Node.js 的 Promise 风格 HTTP 客户端。它的根目录维护了一份名为 AGENTS.md 的规范级贡献者指南同时约束人类维护者与 AI 编码代理从安装安全、构建命令、包结构、架构边界到错误码约定、拦截器执行顺序、请求生命周期和安全敏感代码的回归红线全部以可直接执行的规则形式固化在仓库中。读完本篇你将掌握在 axios 仓库中安全安装依赖、正确运行各类测试套件、按架构边界修改代码以及理解其原型污染防护等安全机制的完整方法。AGENTS.md 的定位唯一权威贡献者指南axios 自我定位是一个 Promise based HTTP client用于浏览器和 Node.js。默认实例由 index.js 从 lib/axios.js 导出浏览器构建使用 XHR 或 Fetch 适配器Node 端使用 HTTP/HTTPS 适配器而平台选择逻辑集中在lib/platform/下。AGENTS.md 明确声明自己是该仓库中人类与 AI 代理共同的唯一权威canonical贡献者指南。配套地.github/copilot-instructions.md 只是一个薄垫片thin stub其内容指向 AGENTS.md并同步了其中承重load-bearing的安全规则子集一旦两者漂移以 AGENTS.md 为准。这种单一权威 工具入口垫片的组织方式使得 Copilot、Claude Code 等 AI 工具与人类维护者遵循同一套规则。此外CLAUDE.md 仅包含一行AGENTS.md引用说明该规范已事实上成为整个仓库工程约定的单一事实来源。安装与供应链安全npm ci 与 ignore-scriptsAGENTS.md 的Setup And Safety一节把安装流程当作安全边界来对待核心规则如下统一使用npm ci安装仓库 .npmrc 中写死了ignore-scriptstrueCI 同样使用npm ci --ignore-scripts。已在仓库中确认 .npmrc 内容即为单行ignore-scriptstrue。禁止删除ignore-scriptstrue。如果新装后确实需要 git hooks只需一次性执行npm rebuild husky npx husky恢复 husky 钩子而不是放开安装脚本执行。依赖的增改属于安全敏感操作package-lock.json会经过lockfile-lint校验 npm HTTPS 主机来源与 integrity 哈希。涉及 package、lockfile、GitHub Actions 的更新 PR 仅限维护者/机器人外部协作者应直接关闭这类 PR。Dependabot 保留 7 天延迟除非出现严重漏洞需要维护者主导的手动更新。即使设置了ignore-scriptsbuild/test/lint 工具在运行阶段仍会执行依赖代码因此能用聚焦检查证明改动时就不要跑完整构建。未经讨论不得新增运行时依赖——axios 的依赖面被刻意维持得极小。从 package.json 可以印证这一极小依赖面策略运行时依赖仅有 4 个follow-redirects、form-data、https-proxy-agent、proxy-from-env其余全部是 devDependencies 中的构建与测试工具链。命令体系构建、Lint 与分层测试AGENTS.md 的Commands一节定义了仓库内的标准命令均可在 package.json 的scripts字段中得到逐条对应用途命令说明构建发布产物npm run build对应gulp clear cross-env NODE_ENVproduction rollup -c先gulp clear删除dist/再由 Rollup 产出浏览器 ESM/UMD/CJS 与 Node CJS 各 bundle仅 Lint 源码npm run lint对应eslint lib/**/*.js聚焦检查可写npx eslint lib/path/to/file.js单元测试npm run test:vitest:unit对应vitest run --project unit聚焦单文件npm run test:vitest:unit -- tests/unit/path.test.js浏览器测试先npx playwright installCI 用npx playwright install --with-deps再npm run test:vitest:browser:headless与 CI 行为对齐Smoke/模块兼容套件先npm run build、npm pack把 tarball 安装进对应的tests/smoke/*或tests/module/*包再运行该套件自己的 npm 脚本关键区别这些套件测的是打包后的产物不是源码树vitest.config.js 进一步揭示了测试项目的划分unitNode 环境匹配tests/unit/**/*.test.js、browserPlaywright 驱动 Chromium与browser-headlessChromium/Firefox/WebKit 三浏览器 headless并加载tests/setup/browser.setup.js。文档同时固化了 CI 的执行顺序install → build → Playwright 安装 → unit → browser headless → pack → CJS/ESM 模块与 smoke 测试 → Bun/Deno smoke 测试。这一顺序解释了为什么 smoke 套件必须先 build 再 pack——它们消费的是与用户实际安装一致的 tarball。包形态Package ShapeESM 源码、按环境切分的导出Package Shape一节规定了 axios 的包结构与发布契约源码是 ESMtype: module公开 ESM 入口为 index.js它把 lib/axios.js 的默认实例解包成命名导出——实际可以看到index.js将create、Axios、AxiosError、CanceledError、CancelToken、AxiosHeaders、HttpStatusCode、getAdapter、mergeConfig、toFormData等 17 个成员具名导出同时保留default从而在 ESM 与 CJS 消费侧保持静态属性一致。禁止手工编辑dist/它是被忽略的、由 Rollup 从lib/生成的产物。运行时导出按环境切分。package.json 的exports字段展示了这一设计bun与default环境分别映射./dist/node/axios.cjsrequire与./index.jsimportreact-native与browser环境则映射浏览器产物。同时browser与react-native字段把./lib/adapters/http.js、./lib/platform/node/index.js、./lib/platform/node/classes/Buffer.js、./lib/platform/node/classes/FormData.js重定向到lib/helpers/null.js或浏览器平台实现完成Node 文件 → 浏览器/null 替换。公共运行时导出、index.d.tsESM 类型与 index.d.ctsCJS 的export axios类型必须在 API 变更时保持同步。lib/env/data.js由gulp version在版本号变更时生成对应preversion: gulp version脚本日常功能开发不应直接编辑它。预发布记录规范CHANGELOG 与 PRE_RELEASE 双轨制axios 把未发布变更与已发布记录严格分轨这在很多项目里是容易混乱的角落AGENTS.md 给出了明确规则用户可见的未发布变更写入 PRE_RELEASE_CHANGELOG.md而不是 CHANGELOG.md后者是发布所有的文件只在准备真正发布时更新。推迟的 README、文档站、examples、迁移指南MIGRATION_GUIDE.md以及多语言文档更新统一记录在 PRE_RELEASE_DOCS.md 中要求提供足够的上下文以便发布时套用禁止存脆弱的 diff 或只有行号的笔记。在功能/修复工作中除非任务明确是发布准备否则不要更新 README 或文档站正确做法是把文档将来应该写什么记入 PRE_RELEASE_DOCS.md留待发布阶段统一落地。架构边界core / adapters / platform / helpers 的分工AGENTS.md 的Architecture Boundaries一节是理解 axios 源码结构的核心地图每条边界都可在源码中得到验证lib/core/——领域逻辑层。负责请求分发、配置合并、拦截器、请求头与错误。关键类包括Axioslib/core/Axios.js请求分发与拦截器链的编排AxiosErrorlib/core/AxiosError.js标准化错误码体系AxiosHeaderslib/core/AxiosHeaders.js大小写不敏感的请求头归一化InterceptorManagerlib/core/InterceptorManager.js同步/异步拦截器注册。lib/adapters/——I/O 层。执行真正的网络请求。默认适配器偏好顺序为[xhr, http, fetch]能力选择发生在 lib/adapters/adapters.js。打开该文件可以看到getAdapter(adapters, config)的完整算法把输入归一化为数组后逐项检查——若项是已解析句柄函数、null或false则直接使用否则按名称查knownAdapters表未知名称直接抛AxiosError(Unknown adapter ...)对fetch这类惰性适配器还会调用其get(config)做能力探测。全部落选时函数汇总每个适配器的拒绝原因区分is not supported by the environment与is not available in the build抛出带ERR_NOT_SUPPORT码的AxiosError。文档特别强调按能力选择适配器而不是按环境名称判断。lib/platform/——平台选择层。lib/platform/index.js 默认聚合 Node 平台实现./node/index.js与./common/utils.js浏览器构建则依靠打包期的browser字段与 Rollup alias 替换到lib/platform/browser。lib/helpers/——通用工具层。约束是应保持通用、可脱离 axios 复用不得把 axios 特有的请求生命周期逻辑放进这里。新文件风格要求lib/**/*.js必须使用显式.js扩展名的 ESM 导入、在既有文件使用use strict;的位置保持一致、axios 源自的失败一律抛AxiosError。命名约定与错误处理规范命名约定可直接作为代码评审检查单类用 PascalCaseAxios、AxiosError、InterceptorManager函数用 camelCasebuildURL、mergeConfig、dispatchRequest错误码用 UPPER_SNAKE_CASE 常量挂到AxiosError上ERR_NETWORK、ETIMEDOUT等内部类槽位使用Symbol键例如 lib/core/AxiosHeaders.js 中的const $internals Symbol(internals)而非下划线前缀属性。错误处理规则与 lib/core/AxiosError.js 的实现一一对应axios 源自的失败必须抛AxiosError而不是裸Error构造参数为(message, code, config, request, response)五元组让消费方可以做结构化内省。源码中构造函数会把config、request、response挂到错误实例上并从response.status派生status字段。第三方错误用静态方法AxiosError.from(error, code, config, request, response)包装。从源码看from还处理了 Node 双栈连接失败产生的AggregateErrormessage 为空时聚合errors[]并把原错误挂到不可枚举的cause上——注释明确说明这是为了避免包装的 socket/request 循环引用破坏 pino/winston 等结构化日志。权威错误码清单定义在 lib/core/AxiosError.js 文件末尾共 14 个ERR_BAD_OPTION_VALUE、ERR_BAD_OPTION、ECONNABORTED、ETIMEDOUT、ECONNREFUSED、ERR_NETWORK、ERR_FR_TOO_MANY_REDIRECTS、ERR_DEPRECATED、ERR_BAD_RESPONSE、ERR_BAD_REQUEST、ERR_CANCELED、ERR_NOT_SUPPORT、ERR_INVALID_URL、ERR_FORM_DATA_DEPTH_EXCEEDED。配置选项校验统一走validatorhelperlib/helpers/validator.js不得自造临时校验路径。另一个值得注意的实现细节AxiosError.toJSON()支持通过请求配置中的redact数组合做敏感键脱敏——匹配键不区分大小写、任意深度在序列化快照中被替换为[REDACTED ****]常量。这意味着把AxiosError直接JSON.stringify进日志时可以防止auth等字段意外落盘这是错误处理规范之外的又一安全设计。拦截器执行顺序与请求生命周期拦截器顺序在 axios 中既影响行为也影响测试AGENTS.md 把它写成硬性规则请求拦截器后注册先执行LIFO响应拦截器先注册先执行FIFO两者都支持synchronous: true当链中无异步 handler 时避免 Promise 包装开销与runWhen: (config) boolean条件执行新增内建拦截器时必须把顺序写入文档。由此形成的完整请求生命周期共 9 步用户调用axios()或方法别名get/post等通过mergeConfiglib/core/mergeConfig.js合并实例默认值与请求配置执行请求拦截器LIFO经 lib/adapters/adapters.js 的能力检查选定适配器依次应用transformRequest函数适配器执行 HTTP 请求依次应用transformResponse函数执行响应拦截器FIFO以AxiosResponse兑现 Promise或以AxiosError拒绝。取消机制的不变量取消Cancellation一节给出三条不变量适用于任何生命周期阶段包括响应体读取中途CancelToken旧式见 lib/cancel/CancelToken.js与AbortSignal现代 API双通道并存不得破坏任何一条路径取消必须在请求的任意阶段生效含 in-flight 的 body 读取结算或取消时必须移除 signal 监听器防止内存泄漏。常见陷阱清单四条可执行的禁止事项AGENTS.md 的Common Pitfalls是把历次修复经验固化的负空间清单禁止原地变更 config 对象——merge/transform 一律返回新对象禁止假设浏览器或 Node 特有全局变量存在——先做能力检查禁止直接使用Function.prototype.bind——必须用 lib/helpers/bind.js。查看该文件可见它只有几行fn.apply(thisArg, arguments)包装通过apply转发原始arguments这是库内其他代码依赖的行为库代码中禁止抛裸Error——一律AxiosError并附合适错误码。测试体系运行时优先的分层布局测试规则Tests一节与 tests/ 目录结构完全对应布局按运行时优先组织单元测试tests/unit/**/*.test.js、浏览器测试tests/browser/**/*.browser.test.js对应 vitest 的browser/browser-headless项目、smoke 套件tests/smoke/esm/**/*.smoke.test.js与tests/smoke/cjs/**/*.smoke.test.cjs本地 HTTP 服务统一用 tests/setup/server.js 创建并在try/finally中清理——文档特别警告泄漏的服务会导致 Vitest 挂死行为涉及打包/导入时CJS 与 ESM 的 smoke 覆盖必须保持对齐类型兼容由两个模块套件分别守护tests/module/cjs用TypeScript 4.9tests/module/esm用TypeScript 5.x改动声明文件index.d.ts/index.d.cts时须运行对应套件浏览器测试会替换 XHR 等全局对象因此必须在清理钩子中恢复全局、重置 spy。安全敏感代码原型污染防护与威胁模型联动AGENTS.md 的最后一节定义了不可回归的安全红线并且每一条都能在源码中找到落点配置读取禁止原型遍历。对于影响行为的配置读取不得使用in、解构或直接config.foo访问不可信配置必须用自有属性检查。这正对应utils.hasOwnProp与本地own()helper 的使用模式——在 lib/core/mergeConfig.js 中可以看到大量utils.hasOwnProp(config2, prop)形式的读取合并入口甚至为hasOwnProperty自身恢复了不可枚举的自有槽位。合并与对象物化必须持续过滤__proto__、constructor、prototype这里的回归就是安全 bug。源码印证mergeConfig.js的深合并循环开头即有if (prop __proto__ || prop constructor || prop prototype) return;的守卫。触及 URL 构建、重定向、代理/环境变量处理、XSRF、socket 路径、解压限制或适配器的改动应先查阅 THREATMODEL.md 并补充聚焦的回归测试。withXSRFToken的跨域行为保持显式只有true才强制跨域附加 XSRF 头不得扩大该触发条件。不得弱化beforeRedirect、代理、socketPath的防护除非有覆盖凭据泄漏与 SSRF 类场景的测试兜底。小结一份可被机器执行的工程契约AGENTS.md 的价值在于它把隐性工程共识翻译成了对人和 AI 同样生效的显式契约安装安全npm ciignore-scripts、命令语义build/lint/unit/browser/smoke 各自的适用对象与前置条件、包形态ESM 源码 按环境切分的 exports 双类型声明文件同步、架构边界core/adapters/platform/helpers 四分层与按能力选适配器、命名与错误码约定、拦截器 LIFO/FIFO 顺序、取消双通道不变量、分层测试布局以及原型污染过滤与安全敏感改动的强制威胁模型评审。对照 lib/adapters/adapters.js、lib/core/AxiosError.js、lib/core/mergeConfig.js 等源码即可逐条验证这些规则不是空泛口号而是与实现深度咬合的工程红线。对于希望深入 axios 内部机制的开发者这份文档是最快的仓库地图入口。【免费下载链接】axiosPromise based HTTP client for the browser and node.js项目地址: https://gitcode.com/GitHub_Trending/ax/axios创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进