☰
memlab Cookies 类型详解:Cookie 数据结构、登录会话注入与 domain 自动推断
2026/10/13 2:07:14 网站建设 项目流程
  • 开发工具
  • 测试
  • CLI
  • MCP 服务

【免费下载链接】memlab

A framework for finding JavaScript memory leaks and analyzing heap snapshots

项目地址:https://gitcode.com/gh_mirrors/me/memlab
点击查看免费下载

导读

Cookies是 memlab 核心类型系统中用于承载浏览器 Cookie 列表的数据结构,它是测试场景(Scenario)登录态配置、Cookie 文件加载与浏览器注入流程的枢纽。本文将以 Cookies.md 与 Cookie.md 为骨架,结合 Types.ts、TestPlanner.ts 与 API.ts 的源码实现,完整说明 Cookie 字段语义、三种注入方式、domain 自动推断机制以及从场景定义到page.setCookie的底层调用链,帮助你为需要登录认证的页面正确配置泄漏检测环境。


一、类型概览:Cookies与Cookie的关系

Cookies是 memlab 中最简单也最常用的类型别名之一,定义在 Types.ts:

export type Cookies = Array<Cookie>;

即一个 Cookie 对象的数组,用于整体承载一次测试运行需要设置到浏览器页面的全部 Cookie。其单个元素Cookie是一个结构化对象,定义在 Types.ts:

export type Cookie = { name: string; // 必填 value: string; // 必填 domain?: string; // 建议提供 url?: Undefinable<string>; // 可选 path?: Undefinable<string>; // 可选 expires?: Undefinable<number>; // 可选 httpOnly?: Undefinable<boolean>; // 可选 session?: Undefinable<boolean>; // 可选 secure?: Undefinable<boolean>; // 可选 sameSite?: Undefinable<'Strict' | 'Lax'>; // 可选 };

字段结构遵循一个明确约定(见 Types.ts 的 JSDoc 注释):

  • name与value为必填字段,缺少任何一个都会导致 Cookie 不完整;
  • 强烈建议同时指定domain,否则 memlab 会尝试依据场景 URL 自动推断 domain(推断规则见下文第五节);
  • 其余字段均为可选,Undefinable<T>表示该字段允许显式传入undefined(其类型定义为T | undefined,可参考 Undefinable.md)。

二、Cookie字段逐项详解

依据 Cookie.md 的字段说明,并结合 Types.ts 的源码注释,各字段语义如下:

字段类型必填语义
namestring✅Cookie 的名称
valuestring✅赋予该 Cookie 的值
domainstring建议与 Cookie 关联的域名;不指定时由 memlab 自动推断
urlUndefinable<string>否与 Cookie 设置关联的请求 URI,会影响 Cookie 的默认 domain 与 path
pathUndefinable<string>否与 Cookie 关联的路径
expiresUndefinable<number>否Cookie 的过期时间,以Unix 时间(秒)表示
httpOnlyUndefinable<boolean>否是否仅允许通过 HTTP 访问(不能由 JavaScript 读取)
sessionUndefinable<boolean>否是否为会话 Cookie
secureUndefinable<boolean>否传输是否要求安全协议(如 HTTPS)
sameSiteUndefinable<'Strict' \| 'Lax'>否是否随跨站请求发送,用于抵御跨站请求伪造(CSRF)攻击

几个值得注意的细节:

  • expires的时间单位是 Unix 秒,与 HTTP Set-Cookie 头中Expires的表示一致,不是毫秒时间戳;
  • sameSite仅支持'Strict'与'Lax'两个取值,类型定义中没有'None',因此跨站 Cookie 场景需要在secure与sameSite的取值上自行斟酌;
  • url与domain/path存在联动关系:指定url时,浏览器会依据该请求 URI 推导默认的 domain 和 path,这与 Puppeteer 的page.setCookie行为一致——memlab 最终就是通过page.setCookie(...)将这些对象原样注入浏览器的(见第四节调用链)。

三、Cookies 的三种注入来源

memlab 允许通过三种途径提供Cookies数据,按优先级从高到低分别是:场景回调scenario.cookies()、RunOptions.cookiesFile指定的 Cookie 文件、Synthesizer 内置的 Cookie 文件。其加载逻辑集中在 TestPlanner.ts 的loadCookies方法中。

3.1 场景内联:IScenario.cookies()回调

在测试场景中直接声明 Cookie 列表,是最常用、也最直观的方式。Types.ts 中IScenario接口将其声明为cookies?: () => Cookies。官方文档示例(见 IScenario.md)如下:

const scenario = { url: () => 'https://www.facebook.com/', cookies: () => [ {name: 'cm_j', value: 'none', domain: '.facebook.com'}, {name: 'datr', value: 'yJvIY...', domain: '.facebook.com'}, {name: 'c_user', value: '8917...', domain: '.facebook.com'}, {name: 'xs', value: '95:9WQ...', domain: '.facebook.com'}, // ... ], }; module.exports = scenario;

该场景既可以在命令行通过memlab run --scenario test.js使用(见 CLI 文档),也可以直接传给@memlab/api的run({scenario})(见 API.ts 的RunOptions)。

3.2 文件注入:cookiesFile

当 Cookie 数量较多或需要从已有导出中复用时,可以将其序列化为 JSON 数组写入文件,再通过RunOptions.cookiesFile传入。该选项声明于 API.ts:

export type RunOptions = { /** the absolute path of cookies file */ cookiesFile?: string; // ... };

对应的类型文档见 RunOptions.md。文件内容格式即Cookies类型的 JSON 序列化:

[ {"name": "session_id", "value": "abc123", "domain": ".example.com"}, {"name": "theme", "value": "dark", "domain": ".example.com"} ]

3.3 Synthesizer 内置 Cookie 文件

当使用 memlab 内置的场景合成器(Synthesizer)时,IE2EScenarioSynthesizer接口通过getCookieFile(visitPlan)方法(见 Types.ts)返回一个相对于persistentDataDir的 Cookie 文件名;TestPlanner.ts 会将其拼接到持久化数据目录下并读取解析。默认的 DefaultScenarioSynthesizer.ts 与 TestSPAVisitSynthesizer.ts 均返回null(即不提供),此时只要未配置cookiesFile,loadCookies就会直接返回空数组:

// TestPlanner.ts if (cookieFile == null && this.config.externalCookiesFile == null) { return []; }

三种来源的优先级逻辑在源码中非常清晰:场景回调优先于文件,文件内部则cookiesFile优先于 Synthesizer 内置文件。


四、底层调用链:从场景定义到page.setCookie

Cookies 的注入并不是“声明即生效”,而是经过一条明确的调用链,理解它有助于排查“为什么 Cookie 没生效”的问题:

  1. 规划访问计划:TestPlanner.init()调用generateVisitPlan()(TestPlanner.ts),在生成visitPlan的同时调用loadCookies()得到Cookies数组,并暂存在TestPlanner实例中;
  2. 读取 Cookie:loadCookies()按第三节的优先级取出数据,随后调用populateDomainInCookiesFromScenario(场景来源)或populateDomainInCookies(文件来源)补齐 domain 字段;
  3. 设置页面:浏览器交互入口testInBrowser()(API.ts)中调用setupPage(page, options),其中关键一行是(API.ts):
// set login session await page.setCookie(...testPlanner.getCookies());

即把经过处理后的Cookies数组展开为参数,一次性写入 Puppeteer 页面对象。之后才开始interactionManager.visitAndGetSnapshots(options)的页面访问与堆快照采集流程,因此登录态在首次页面加载前就已就绪。

从IE2EScenarioSynthesizer.getCookieFile、IE2EScenarioVisitPlan到Cookies的完整接口契约都可以在 Types.ts 中找到,感兴趣可以继续追踪。


五、domain 自动推断:不写 domain 时 memlab 做了什么

这是Cookies使用中最容易踩坑、也最能体现 memlab 设计细节的一点。官方类型注释明确说明(Types.ts):最好显式提供domain,否则 memlab 会根据场景 URL 自动推断。

对于场景内联的 Cookie,推断逻辑位于populateDomainInCookiesFromScenario(TestPlanner.ts):

const url = new URL(scenario.url()); const domain = '.' + url.hostname.split('.').slice(1).join('.'); for (const cookie of cookies) { if (cookie.domain) { ret.push({...cookie}); } else { ret.push({...cookie, domain}); } }

推断规则可以概括为两步:

  1. 取场景 URL 的主机名,去掉第一段子域名,得到“根域”;
  2. 在根域前加.前缀形成 domain 值。

例如场景 URL 为https://www.facebook.com/时,hostname是www.facebook.com,去掉www后得到facebook.com,最终自动填充domain = '.facebook.com'。这也解释了为什么官方示例中的 domain 都写成.facebook.com(见 Types.ts 的 JSDoc 说明)。

两个边界行为值得注意:

  • 已有domain的 Cookie 原样保留,不会被覆盖;
  • 该推断发生在new URL(...)之上,要求场景必须提供合法的url()回调。

对于从文件加载的 Cookie,populateDomainInCookies(TestPlanner.ts)则采用另一套策略:以 Synthesizer 提供的domain为基准,并遍历domainPrefixes前缀集合(默认包含空字符串''),为每个前缀与 domain 的组合生成一份 Cookie 副本,从而覆盖多个子域。


六、测试验证:Cookie 回调的执行时机

仓库中的端到端测试对cookies回调的执行顺序有明确断言。在 E2ETestScenarioCallback.test.ts 中,测试场景同时定义了app、cookies、repeat、url等全部回调,并断言它们的调用顺序:

expect(normalizedCalls).toEqual([ // the first 4 calls (app, cookies, repeat, url) can be in any order 'url', 'repeat', 'app', 'cookies', // the following calls must be in the exact order listed 'beforeInitialPageLoad', 'isPageLoaded', 'setup', 'action', ... ]);

该测试证实了两个关键事实:

  1. cookies回调属于“规划阶段”回调,与url、repeat等并列,在浏览器加载页面前就已调用;
  2. 回调返回的Cookies数组(测试中返回[])会在beforeInitialPageLoad、页面加载与交互动作之前被消费,与第四节展示的调用链时序完全吻合。

七、实战建议与注意事项

综合类型定义与源码实现,使用Cookies时建议遵循以下实践:

  1. 登录类场景务必显式填写domain。虽然 memlab 支持自动推断,但推断规则依赖场景url()的格式;显式填写(如.example.com带点前缀)可避免因 URL 结构差异导致的推断偏差,这也是官方示例一贯的做法;
  2. Cookie 文件与场景回调不要混用。优先级规则是“场景回调 >cookiesFile> Synthesizer 内置文件”,同时配置多个来源时只有高优先级者生效,容易造成误解;
  3. 敏感字段按需声明。httpOnly、secure、sameSite等字段会直接影响浏览器对 Cookie 的接纳与发送行为,模拟生产登录态时建议与真实环境保持一致;
  4. 文件来源的 Cookie 需补全 domain。从 JSON 文件加载的 Cookie 会经过populateDomainInCookies的“前缀 × domain”展开逻辑,若 Synthesizer 未提供正确 domain,最终写入浏览器的 domain 可能与预期不符;
  5. 排查注入失败时,沿调用链检查:先确认TestPlanner.getCookies()返回的内容是否符合预期,再检查setupPage中page.setCookie(...)的执行,中间环节均可在packages/e2e/src/lib/operations/TestPlanner.ts与packages/api/src/API.ts中直接审阅。

参考资料

  • 类型别名文档:Cookies.md、Cookie.md、Undefinable.md
  • 接口文档:IScenario.md、RunOptions.md
  • 核心实现:Types.ts、TestPlanner.ts、API.ts
  • 测试用例:E2ETestScenarioCallback.test.ts
  • 开发工具
  • 测试
  • CLI
  • MCP 服务

【免费下载链接】memlab

A framework for finding JavaScript memory leaks and analyzing heap snapshots

项目地址:https://gitcode.com/gh_mirrors/me/memlab
点击查看免费下载
上一篇:从安装到精通:ClipCascade全平台使用指南(桌面+移动设备)
下一篇:3小时精通LSPosed模块开发:从零打造Android应用增强神器

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询