fix(cookies): properly filter cookies for subdomain (#36109)

This commit is contained in:
Yury Semikhatsky 2025-05-27 14:27:25 -07:00 committed by GitHub
parent 64e2b5989e
commit 9d70a305a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 38 additions and 3 deletions

View File

@ -18,7 +18,7 @@ import { kMaxCookieExpiresDateInSeconds } from './network';
import type * as channels from '@protocol/channels';
class Cookie {
export class Cookie {
private _raw: channels.NetworkCookie;
constructor(data: channels.NetworkCookie) {
this._raw = data;

View File

@ -24,7 +24,7 @@ import { assert, constructURLBasedOnBaseURL, createProxyAgent, eventsHelper, mon
import { createGuid } from './utils/crypto';
import { getUserAgent } from './utils/userAgent';
import { BrowserContext, verifyClientCertificates } from './browserContext';
import { CookieStore, domainMatches, parseRawCookie } from './cookieStore';
import { Cookie, CookieStore, domainMatches, parseRawCookie } from './cookieStore';
import { MultipartFormData } from './formData';
import { SdkObject } from './instrumentation';
import { ProgressController } from './progress';
@ -255,7 +255,11 @@ export abstract class APIRequestContext extends SdkObject {
private async _updateRequestCookieHeader(url: URL, headers: HeadersObject) {
if (getHeader(headers, 'cookie') !== undefined)
return;
const cookies = await this._cookies(url);
const contextCookies = await this._cookies(url);
// Browser context returns cookies with domain matching both .example.com and
// example.com. Those without leading dot are only sent when domain is strictly
// matching example.com, but not for sub.example.com.
const cookies = contextCookies.filter(c => new Cookie(c).matches(url));
if (cookies.length) {
const valueArray = cookies.map(c => `${c.name}=${c.value}`);
setHeader(headers, 'cookie', valueArray.join('; '));

View File

@ -121,6 +121,37 @@ it('should add session cookies to request', async ({ context, server }) => {
expect(req.headers.cookie).toEqual('username=John Doe');
});
it('should filter cookies by domain', {
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36069' }
}, async ({ context, server }) => {
await context.addCookies([{
name: 'first',
value: '1',
domain: 'playwright.dev',
path: '/',
expires: -1,
httpOnly: false,
secure: false,
sameSite: 'Lax',
}, {
name: 'second',
value: '2',
domain: '.playwright.dev',
path: '/',
expires: -1,
httpOnly: false,
secure: false,
sameSite: 'Lax',
}]);
const [req] = await Promise.all([
server.waitForRequest('/simple.json'),
context.request.get(`http://my.playwright.dev:${server.PORT}/simple.json`, {
__testHookLookup
} as any),
]);
expect(req.headers.cookie).toEqual('second=2');
});
for (const method of ['fetch', 'delete', 'get', 'head', 'patch', 'post', 'put'] as const) {
it(`${method} should support params passed as object`, async ({ context, server }) => {
const url = new URL(server.EMPTY_PAGE);