Skip to content

Commit 46ab37a

Browse files
committed
1 parent c018b71 commit 46ab37a

File tree

7 files changed

+125
-6
lines changed

7 files changed

+125
-6
lines changed

docs/src/api/class-route.md

+4
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ The [`option: headers`] option applies to both the routed request and any redire
106106

107107
[`method: Route.continue`] will immediately send the request to the network, other matching handlers won't be invoked. Use [`method: Route.fallback`] If you want next matching handler in the chain to be invoked.
108108

109+
:::warning
110+
The `Cookie` header cannot be overridden using this method. If a value is provided, it will be ignored, and the cookie will be loaded from the browser's cookie store. To set custom cookies, use [`method: BrowserContext.addCookies`].
111+
:::
112+
109113
### option: Route.continue.url
110114
* since: v1.8
111115
- `url` <[string]>

packages/playwright-client/types/types.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -20786,6 +20786,11 @@ export interface Route {
2078620786
* request to the network, other matching handlers won't be invoked. Use
2078720787
* [route.fallback([options])](https://playwright.dev/docs/api/class-route#route-fallback) If you want next matching
2078820788
* handler in the chain to be invoked.
20789+
*
20790+
* **NOTE** The `Cookie` header cannot be overridden using this method. If a value is provided, it will be ignored,
20791+
* and the cookie will be loaded from the browser's cookie store. To set custom cookies, use
20792+
* [browserContext.addCookies(cookies)](https://playwright.dev/docs/api/class-browsercontext#browser-context-add-cookies).
20793+
*
2078920794
* @param options
2079020795
*/
2079120796
continue(options?: {

packages/playwright-core/src/server/chromium/crNetworkManager.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,8 @@ export class CRNetworkManager {
339339
// We do not support intercepting redirects.
340340
if (redirectedFrom || (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled)) {
341341
// Chromium does not preserve header overrides between redirects, so we have to do it ourselves.
342-
headersOverride = redirectedFrom?._originalRequestRoute?._alreadyContinuedParams?.headers;
342+
headersOverride = redirectedFrom?._originalRequestRoute?._alreadyContinuedParams?.headers?.
343+
filter(header => header.name.toLowerCase() !== 'cookie');
343344
requestPausedSessionInfo!.session._sendMayFail('Fetch.continueRequest', { requestId: requestPausedEvent.requestId, headers: headersOverride });
344345
} else {
345346
route = new RouteImpl(requestPausedSessionInfo!.session, requestPausedEvent.requestId);

packages/playwright-core/src/server/network.ts

+5
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,11 @@ export class Route extends SdkObject {
329329
if (oldUrl.protocol !== newUrl.protocol)
330330
throw new Error('New URL must have same protocol as overridden URL');
331331
}
332+
if (overrides.headers) {
333+
overrides.headers = overrides.headers?.filter(header => header.name.toLowerCase() !== 'cookie');
334+
const originalCookie = this._request.headers().filter(header => header.name.toLowerCase() === 'cookie');
335+
overrides.headers.push(...originalCookie);
336+
}
332337
this._request._setOverrides(overrides);
333338
if (!overrides.isFallback)
334339
this._request._context.emit(BrowserContext.Events.RequestContinued, this._request);

packages/playwright-core/types/types.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -20786,6 +20786,11 @@ export interface Route {
2078620786
* request to the network, other matching handlers won't be invoked. Use
2078720787
* [route.fallback([options])](https://playwright.dev/docs/api/class-route#route-fallback) If you want next matching
2078820788
* handler in the chain to be invoked.
20789+
*
20790+
* **NOTE** The `Cookie` header cannot be overridden using this method. If a value is provided, it will be ignored,
20791+
* and the cookie will be loaded from the browser's cookie store. To set custom cookies, use
20792+
* [browserContext.addCookies(cookies)](https://playwright.dev/docs/api/class-browsercontext#browser-context-add-cookies).
20793+
*
2078920794
* @param options
2079020795
*/
2079120796
continue(options?: {

tests/library/har.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ it('should record request overrides', async ({ contextFactory, server }, testInf
295295
expect(request.url).toBe(server.EMPTY_PAGE);
296296
expect(request.method).toBe('POST');
297297
expect(request.headers).toContainEqual({ name: 'custom', value: 'value' });
298-
expect(request.cookies).toContainEqual({ name: 'foo', value: 'bar' });
298+
expect(request.cookies).toEqual([]);
299299
expect(request.postData).toEqual({ 'mimeType': 'text/plain', 'params': [], 'text': 'Hi!' });
300300
});
301301

@@ -508,7 +508,7 @@ it('should record failed request overrides', async ({ contextFactory, server },
508508
expect(request.url).toBe(server.EMPTY_PAGE);
509509
expect(request.method).toBe('POST');
510510
expect(request.headers).toContainEqual({ name: 'custom', value: 'value' });
511-
expect(request.cookies).toContainEqual({ name: 'foo', value: 'bar' });
511+
expect(request.cookies).toEqual([]);
512512
expect(request.postData).toEqual({ 'mimeType': 'text/plain', 'params': [], 'text': 'Hi!' });
513513
});
514514

tests/page/page-request-continue.spec.ts

+102-3
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,94 @@ it('should respect set-cookie in redirect response', {
452452
expect.soft(await page.evaluate(() => document.cookie)).toBe('foo=bar');
453453
});
454454

455+
it('continue should not propagate cookie override to redirects', {
456+
annotation: [
457+
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/35168' },
458+
]
459+
}, async ({ page, server }) => {
460+
server.setRoute('/set-cookie', (request, response) => {
461+
response.writeHead(200, { 'Set-Cookie': 'foo=bar;' });
462+
response.end();
463+
});
464+
await page.goto(server.PREFIX + '/set-cookie');
465+
expect(await page.evaluate(() => document.cookie)).toBe('foo=bar');
466+
server.setRedirect('/redirect', server.PREFIX + '/empty.html');
467+
await page.route('**/redirect', route => {
468+
void route.continue({
469+
headers: {
470+
...route.request().headers(),
471+
cookie: 'override'
472+
}
473+
});
474+
});
475+
const [serverRequest] = await Promise.all([
476+
server.waitForRequest('/empty.html'),
477+
page.goto(server.PREFIX + '/redirect')
478+
]);
479+
expect(serverRequest.headers['cookie']).toBe('foo=bar');
480+
});
481+
482+
it('continue should not override cookie', {
483+
annotation: [
484+
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/35168' },
485+
]
486+
}, async ({ page, server }) => {
487+
server.setRoute('/set-cookie', (request, response) => {
488+
response.writeHead(200, { 'Set-Cookie': 'foo=bar;' });
489+
response.end();
490+
});
491+
await page.goto(server.PREFIX + '/set-cookie');
492+
expect(await page.evaluate(() => document.cookie)).toBe('foo=bar');
493+
await page.route('**', route => {
494+
void route.continue({
495+
headers: {
496+
...route.request().headers(),
497+
cookie: 'override',
498+
custom: 'value'
499+
}
500+
});
501+
});
502+
const [serverRequest] = await Promise.all([
503+
server.waitForRequest('/empty.html'),
504+
page.goto(server.EMPTY_PAGE)
505+
]);
506+
// Original cookie from the browser's cookie jar should be sent.
507+
expect(serverRequest.headers['cookie']).toBe('foo=bar');
508+
expect(serverRequest.headers['custom']).toBe('value');
509+
});
510+
511+
it('redirect after continue should be able to delete cookie', {
512+
annotation: [
513+
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/35168' },
514+
]
515+
}, async ({ page, server }) => {
516+
server.setRoute('/set-cookie', (request, response) => {
517+
response.writeHead(200, { 'Set-Cookie': 'foo=bar;' });
518+
response.end();
519+
});
520+
await page.goto(server.PREFIX + '/set-cookie');
521+
expect(await page.evaluate(() => document.cookie)).toBe('foo=bar');
522+
523+
server.setRoute('/delete-cookie', (request, response) => {
524+
response.writeHead(200, { 'Set-Cookie': 'foo=bar; expires=Thu, 01 Jan 1970 00:00:00 GMT' });
525+
response.end();
526+
});
527+
server.setRedirect('/redirect', '/delete-cookie');
528+
await page.route('**/redirect', route => {
529+
void route.continue({
530+
headers: {
531+
...route.request().headers(),
532+
}
533+
});
534+
});
535+
await page.goto(server.PREFIX + '/redirect');
536+
const [serverRequest] = await Promise.all([
537+
server.waitForRequest('/empty.html'),
538+
page.goto(server.EMPTY_PAGE)
539+
]);
540+
expect(serverRequest.headers['cookie']).toBeFalsy();
541+
});
542+
455543
it('continue should propagate headers to redirects', {
456544
annotation: [
457545
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/28758' },
@@ -536,6 +624,7 @@ it('propagate headers same origin redirect', {
536624
annotation: [
537625
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/13106' },
538626
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32045' },
627+
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/35154' },
539628
]
540629
}, async ({ page, server }) => {
541630
await page.goto(server.PREFIX + '/empty.html');
@@ -547,7 +636,7 @@ it('propagate headers same origin redirect', {
547636
'Access-Control-Allow-Origin': server.PREFIX,
548637
'Access-Control-Allow-Credentials': 'true',
549638
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, DELETE',
550-
'Access-Control-Allow-Headers': 'authorization,custom',
639+
'Access-Control-Allow-Headers': 'authorization,cookie,custom',
551640
});
552641
response.end();
553642
return;
@@ -557,6 +646,7 @@ it('propagate headers same origin redirect', {
557646
response.end('done');
558647
});
559648
await server.setRedirect('/redirect', '/something');
649+
await page.evaluate(() => document.cookie = 'a=b');
560650
const text = await page.evaluate(async url => {
561651
const data = await fetch(url, {
562652
headers: {
@@ -570,6 +660,7 @@ it('propagate headers same origin redirect', {
570660
expect(text).toBe('done');
571661
const serverRequest = await serverRequestPromise;
572662
expect.soft(serverRequest.headers['authorization']).toBe('credentials');
663+
expect.soft(serverRequest.headers['cookie']).toBe('a=b');
573664
expect.soft(serverRequest.headers['custom']).toBe('foo');
574665
});
575666

@@ -620,6 +711,7 @@ it('propagate headers cross origin redirect', {
620711
annotation: [
621712
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/13106' },
622713
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32045' },
714+
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/35154' },
623715
]
624716
}, async ({ page, server, isAndroid }) => {
625717
it.fixme(isAndroid, 'receives authorization:credentials header');
@@ -633,7 +725,7 @@ it('propagate headers cross origin redirect', {
633725
'Access-Control-Allow-Origin': server.PREFIX,
634726
'Access-Control-Allow-Credentials': 'true',
635727
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, DELETE',
636-
'Access-Control-Allow-Headers': 'authorization,custom',
728+
'Access-Control-Allow-Headers': 'authorization,cookie,custom',
637729
});
638730
response.end();
639731
return;
@@ -649,6 +741,7 @@ it('propagate headers cross origin redirect', {
649741
response.writeHead(301, { location: `${server.CROSS_PROCESS_PREFIX}/something` });
650742
response.end();
651743
});
744+
await page.evaluate(() => document.cookie = 'a=b');
652745
const text = await page.evaluate(async url => {
653746
const data = await fetch(url, {
654747
headers: {
@@ -663,13 +756,15 @@ it('propagate headers cross origin redirect', {
663756
const serverRequest = await serverRequestPromise;
664757
// Authorization header not propagated to cross-origin redirect.
665758
expect.soft(serverRequest.headers['authorization']).toBeFalsy();
759+
expect.soft(serverRequest.headers['cookie']).toBeFalsy();
666760
expect.soft(serverRequest.headers['custom']).toBe('foo');
667761
});
668762

669763
it('propagate headers cross origin redirect after interception', {
670764
annotation: [
671765
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/13106' },
672766
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32045' },
767+
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/35154' },
673768
]
674769
}, async ({ page, server, browserName }) => {
675770
await page.goto(server.PREFIX + '/empty.html');
@@ -681,7 +776,7 @@ it('propagate headers cross origin redirect after interception', {
681776
'Access-Control-Allow-Origin': server.PREFIX,
682777
'Access-Control-Allow-Credentials': 'true',
683778
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, DELETE',
684-
'Access-Control-Allow-Headers': 'authorization,custom',
779+
'Access-Control-Allow-Headers': 'authorization,cookie,custom',
685780
});
686781
response.end();
687782
return;
@@ -697,6 +792,7 @@ it('propagate headers cross origin redirect after interception', {
697792
response.writeHead(301, { location: `${server.CROSS_PROCESS_PREFIX}/something` });
698793
response.end();
699794
});
795+
await page.evaluate(() => document.cookie = 'a=b');
700796
await page.route('**/redirect', async route => {
701797
await route.continue({
702798
headers: {
@@ -721,6 +817,9 @@ it('propagate headers cross origin redirect after interception', {
721817
expect.soft(serverRequest.headers['authorization']).toBeFalsy();
722818
else
723819
expect.soft(serverRequest.headers['authorization']).toBe('credentials');
820+
// TODO: fix this in juggler.
821+
if (browserName !== 'firefox')
822+
expect.soft(serverRequest.headers['cookie']).toBeFalsy();
724823
expect.soft(serverRequest.headers['custom']).toBe('foo');
725824
});
726825

0 commit comments

Comments
 (0)