Puppeteer CookieParam 深入解析:Cookie 参数对象、字段语义与 CDP/BiDi 实现细节 Puppeteer CookieParam 深入解析Cookie 参数对象、字段语义与 CDP/BiDi 实现细节【免费下载链接】puppeteerJavaScript API for Chrome and Firefox项目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer本篇基于 Puppeteer 官方 API 文档CookieParam条目及其在puppeteer-core中的源码实现完整讲解用于设置 Cookie 的参数对象CookieParam12 个字段的类型、语义与浏览器支持差异url字段如何影响默认 domain/path、sameSite与partitionKey的底层转换逻辑以及Page.setCookie在 CDP 与 BiDi 两种协议下的真实调用链。读完后可准确构造任意场景含分区 Cookie、优先级、过期时间的 Cookie 写入代码并理解 Puppeteer 为何采用“先删后写”的落库策略。CookieParam 的定位页面级 Cookie 写入的参数对象CookieParam是 Puppeteer 页面级 Cookie API 的参数对象文档中的定义非常明确Cookie parameter object used to set cookies in the page-level cookies API.其源码定义位于 Cookie.ts是一个纯 TypeScript interfaceexport interface CookieParam { name: string; value: string; url?: string; domain?: string; path?: string; secure?: boolean; httpOnly?: boolean; sameSite?: CookieSameSite; expires?: number; priority?: CookiePriority; sourceScheme?: CookieSourceScheme; partitionKey?: CookiePartitionKey | string; }它是Page.setCookie方法的入参类型。从 api/Page.ts 可以看到方法签名与废弃声明/** * example * *ts * await page.setCookie(cookieObject1, cookieObject2); * * * deprecated Page-level cookie API is deprecated. Use * {link Browser.setCookie} or {link BrowserContext.setCookie} * instead. */ abstract setCookie(...cookies: CookieParam[]): Promisevoid;两点关键事实需要注意setCookie是变长参数一次调用可以传入任意多个CookieParam对象无需逐个调用页面级 Cookie API 已标记deprecated。源码注释建议改用Browser.setCookie或BrowserContext.setCookie后两者使用的是 CookieData 接口同样是 Cookie.ts 中定义的兄弟接口。CookieParam与CookieData的核心差异在于浏览器级的CookieData必须显式提供domain因为不依赖某个页面 URL 来推断归属而页面级的CookieParam中domain、path均为可选可以借助url字段或当前页面 URL 由浏览器自动推导。完整字段说明继承自官方 API 文档以下表格完整覆盖 官方文档 中列出的全部 12 个属性属性修饰符类型说明name必填stringCookie 名称value必填stringCookie 值url可选string与设置该 Cookie 相关联的请求 URI。该值会影响所创建 Cookie 的默认 domain、path 与 source schemedomain可选stringCookie 的域path可选stringCookie 的路径secure可选boolean是否为 Secure Cookie仅 HTTPS 传输httpOnly可选boolean是否为 HttpOnly CookieJS 不可读sameSite可选CookieSameSiteCookie 的 SameSite 类型expires可选number过期时间不设置则为会话 Cookiepriority可选CookiePriorityCookie 优先级仅 Chrome 支持sourceScheme可选CookieSourceScheme源协议类型仅 Chrome 支持partitionKey可选CookiePartitionKey |stringCookie 分区键。在 Chrome 中匹配该分区 Cookie 可被访问的顶级站点在 Firefox 中匹配 WebDriver BiDi 协议 PartitionKey 类型中的 source origin配套类型取值范围与浏览器差异CookieParam引用的四个类型全部定义在 Cookie.ts 中取值范围是固定的字符串字面量联合// packages/puppeteer-core/src/common/Cookie.ts export type CookieSameSite Strict | Lax | None | Default; // L13 export type CookiePriority Low | Medium | High; // L21 export type CookieSourceScheme Unset | NonSecure | Secure; // L30 export interface CookiePartitionKey { // L37-L52 sourceOrigin: string; // 对应 CDP 的 topLevelSite hasCrossSiteAncestor?: boolean; // 仅 Chrome 支持 }CookieSameSite文档标注其对应 SameSite 状态的 IETF 草案first-party cookies 草案四个取值中Default表示交给浏览器决定默认行为跨浏览器时不同引擎的默认值可能不同详见下文测试佐证CookiePriority对应 IETF 的 Cookie Priority 草案priority与sourceScheme两个字段源码注释均写明Supported only in ChromeCookie.tsFirefox 下传入这些字段不产生 Chrome 对应的存储行为CookiePartitionKey用于第三方分区 CookiePartitioned Cookies场景sourceOrigin在 Chrome 中映射到 CDP 的topLevelSite分区键partitionKey字段允许传入完整对象也允许直接传一个字符串表示顶层站点 originPuppeteer 在底层会自动转换。典型用法页面级写法使用 CookieParamimport puppeteer from puppeteer; const browser await puppeteer.launch(); const page await browser.newPage(); await page.goto(https://example.com/); // 单条写入仅传必填的 name/value其余属性由 url 或页面 URL 推导 await page.setCookie({name: session_id, value: abc123}); // 批量写入完整指定各可选字段 await page.setCookie( { name: theme, value: dark, url: https://example.com/, // 影响默认 domain / path / source scheme domain: .example.com, // 覆盖推导结果 path: /app, secure: true, httpOnly: true, sameSite: Lax, expires: Math.floor(Date.now() / 1000) 86400 * 30, // 30 天后过期 }, { name: ch, value: partner, partitionKey: https://top-level-site.com, // 分区 Cookie 简写字符串即顶级站点 }, );注意expires的单位是自 UNIX epoch 起的秒数与 Cookie 接口返回值的语义一致不是毫秒、也不是相对时长。推荐的浏览器级写法使用 CookieData由于页面级 API 已废弃新代码建议使用浏览器/上下文级 API此时参数换为CookieDatadomain必填没有url字段await browserContext.setCookie({ name: session_id, value: abc123, domain: .example.com, // 必填不再依赖页面 URL 推导 path: /, httpOnly: true, sameSite: Strict, });源码级实现解析一CDP 协议下的 setCookie 行为CookieParam在 ChromeCDP 通道中的落库实现位于 cdp/Page.ts这段代码揭示了文档无法体现的四个关键行为override async setCookie(...cookies: CookieParam[]): Promisevoid { const pageURL this.url(); const startsWithHTTP pageURL.startsWith(http); const items cookies.map(cookie { const item Object.assign({}, cookie); if (!item.url startsWithHTTP) { item.url pageURL; // ① 自动填充 url } assert( item.url ! about:blank, Blank page can not have cookie ${item.name}, ); // ② about:blank 断言 assert( !String.prototype.startsWith.call(item.url || , data:), Data URL page can not have cookie ${item.name}, ); // ③ data: URL 断言 return item; }); await this.deleteCookie(...items); // ④ 先删除同键 Cookie if (items.length) { await this.#primaryTargetClient.send(Network.setCookies, { cookies: items.map(cookieParam { return { ...cookieParam, partitionKey: convertCookiesPartitionKeyFromPuppeteerToCdp( cookieParam.partitionKey, ), sameSite: convertSameSiteFromPuppeteerToCdp(cookieParam.sameSite), }; }), }); } }逐条解读url的自动填充当调用方没有提供url且当前页面 URL 以http开头时Puppeteer 会把当前页面 URL作为url传给 CDP 的Network.setCookies。这就是文档所说 “This value can affect the default domain, path, and source scheme values of the created cookie” 的具体实现——省略url时Cookie 的默认 domain/path 由“当前页面在哪”决定。反过来在about:blank或file://等非 http(s) 页面上省略url时不会自动填充此时必须显式给出url或直接改用浏览器级 API 提供domain。硬性断言about:blank页面与data:URL 页面无法承载 Cookie触发时分别抛出Blank page can not have cookie xxx与Data URL page can not have cookie xxx。这是使用页面级setCookie时最常见的报错来源。“先删后写”语义setCookie会先对同一组参数调用deleteCookiecdp/Page.ts再写入。因此setCookie实际上是幂等的覆盖式写入——重复调用同一name连同 domain/path/partitionKey 匹配条件不会产生重复 Cookie。deleteCookie中还有一段值得注意的兼容逻辑若删除的是非分区 Cookie 且页面为 http 协议它会额外再删除一次该页面 origin 分区下的同名 Cookie避免分区 Cookie 残留。两个协议转换函数partitionKey与sameSite在发送到 CDP 前都会经过归一化。其中sameSite的转换规则见 convertSameSiteFromPuppeteerToCdpexport function convertSameSiteFromPuppeteerToCdp( sameSite: CookieSameSite | undefined, ): Protocol.Network.CookieSameSite | undefined { switch (sameSite) { case Strict: case Lax: case None: return sameSite; default: return undefined; // Default 或 undefined 一律交给浏览器决定 } }也就是说sameSite: Default在 CDP 通道下会被抹掉由浏览器按自身策略多数情况下为Lax决定最终属性这与测试用例 cookies.test.ts 中的断言完全对应——Default写入后读回的sameSite可能是Default、Lax或undefined因为Different browsers have different sameSite values for the Default sameSite.源码级实现解析二BiDi 协议下的双通道写入在 WebDriver BiDi 通道packages/puppeteer-core/src/bidi/Page.ts中setCookie 实现 对partitionKey的形态做了分流partitionKey为undefined或字符串时走browsingContext.setCookie在当前浏览上下文中写入partitionKey为对象时改走browserContext().userContext.setCookie(...)以用户上下文级别写入分区 Cookie。字符串形态的partitionKey在 BiDi 侧同样会被归一化从源码结构看bidi/Page.ts 中的转换函数直接返回字符串本身仅当对象形态携带hasCrossSiteAncestor时才拼接出复合分区键否则退回sourceOrigin。这意味着 Chrome 与 Firefox 对“同一个partitionKey”的解释并不完全一致——文档特意区分了 “In Chrome, it matches the top-level site … In Firefox, it matches the source origin”正是这一差异的体现。测试用例佐证仓库的 Cookie 测试套件 test/src/cookies.test.ts 大量使用了CookieParam形态的入参可作为字段行为的权威参照L82-L91写入sameSite: Default后断言浏览器返回的sameSite属于[Default, Lax, undefined]印证了上文 “Default 由浏览器决定” 的结论L93-L109验证DefaultsameSite Cookie 可以被deleteCookie正确清除与 “先删后写” 语义配套该文件后段L200 之后还覆盖了url推导、expires、partitionKey等字段场景是排查字段行为时的首选入口。浏览器级 API 的对应测试位于 test/src/browsercontext-cookies.test.ts。使用要点与常见坑位小结必填项只有两个name与value。其余字段均可省略省略domain/path时依赖url或当前页面 URL 推导优先显式传url在非 http(s) 页面about:blank、file://、data:上省略url会触发断言报错此时要么显式指定url要么改用Browser.setCookie/BrowserContext.setCookie并以CookieData提供domainexpires是 Unix 秒不设置即会话 CookiesetCookie是覆盖式写入内部先执行deleteCookie再Network.setCookies同键重复调用幂等sameSite: Default的实际取值由浏览器决定跨浏览器断言时应容忍Default/Lax/undefined三种读回值priority与sourceScheme仅 Chrome 生效Firefox 下传入不会产生对应存储语义分区 Cookie 用partitionKey传字符串表示顶级站点 origin传CookiePartitionKey对象可精确表达hasCrossSiteAncestorChrome 专有BiDi 通道下对象形态会改走用户上下文写入。新代码建议迁移到浏览器级 APIPage.setCookie已废弃CookieParam的url推导能力在浏览器级被CookieData.domain显式声明所替代。相关文档与源码入口CookieParam 文档、Cookie 接口、CookieData 接口、page.setCookie 文档、类型定义、CDP 实现。【免费下载链接】puppeteerJavaScript API for Chrome and Firefox项目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考