fix: correctly report overridden headers on redirected requests (#31409)

Fixes https://github.com/microsoft/playwright/issues/31351
This commit is contained in:
Yury Semikhatsky 2024-06-21 17:44:58 -07:00 committed by GitHub
parent 2285bcd55d
commit d74ddaebe7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 6 deletions

View file

@ -332,12 +332,13 @@ export class CRNetworkManager {
} }
let route = null; let route = null;
let headersOverride: types.HeadersArray | undefined;
if (requestPausedEvent) { if (requestPausedEvent) {
// We do not support intercepting redirects. // We do not support intercepting redirects.
if (redirectedFrom || (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled)) { if (redirectedFrom || (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled)) {
// Chromium does not preserve header overrides between redirects, so we have to do it ourselves. // Chromium does not preserve header overrides between redirects, so we have to do it ourselves.
const headers = redirectedFrom?._originalRequestRoute?._alreadyContinuedParams?.headers; headersOverride = redirectedFrom?._originalRequestRoute?._alreadyContinuedParams?.headers;
requestPausedSessionInfo!.session._sendMayFail('Fetch.continueRequest', { requestId: requestPausedEvent.requestId, headers }); requestPausedSessionInfo!.session._sendMayFail('Fetch.continueRequest', { requestId: requestPausedEvent.requestId, headers: headersOverride });
} else { } else {
route = new RouteImpl(requestPausedSessionInfo!.session, requestPausedEvent.requestId); route = new RouteImpl(requestPausedSessionInfo!.session, requestPausedEvent.requestId);
} }
@ -353,7 +354,8 @@ export class CRNetworkManager {
route, route,
requestWillBeSentEvent, requestWillBeSentEvent,
requestPausedEvent, requestPausedEvent,
redirectedFrom redirectedFrom,
headersOverride: headersOverride || null,
}); });
this._requestIdToRequest.set(requestWillBeSentEvent.requestId, request); this._requestIdToRequest.set(requestWillBeSentEvent.requestId, request);
@ -361,7 +363,7 @@ export class CRNetworkManager {
// We will not receive extra info when intercepting the request. // We will not receive extra info when intercepting the request.
// Use the headers from the Fetch.requestPausedPayload and release the allHeaders() // Use the headers from the Fetch.requestPausedPayload and release the allHeaders()
// right away, so that client can call it from the route handler. // right away, so that client can call it from the route handler.
request.request.setRawRequestHeaders(headersObjectToArray(requestPausedEvent.request.headers, '\n')); request.request.setRawRequestHeaders(headersOverride ?? headersObjectToArray(requestPausedEvent.request.headers, '\n'));
} }
(this._page?._frameManager || this._serviceWorker)!.requestStarted(request.request, route || undefined); (this._page?._frameManager || this._serviceWorker)!.requestStarted(request.request, route || undefined);
} }
@ -568,8 +570,9 @@ class InterceptableRequest {
requestWillBeSentEvent: Protocol.Network.requestWillBeSentPayload; requestWillBeSentEvent: Protocol.Network.requestWillBeSentPayload;
requestPausedEvent: Protocol.Fetch.requestPausedPayload | undefined; requestPausedEvent: Protocol.Fetch.requestPausedPayload | undefined;
redirectedFrom: InterceptableRequest | null; redirectedFrom: InterceptableRequest | null;
headersOverride: types.HeadersArray | null;
}) { }) {
const { session, context, frame, documentId, route, requestWillBeSentEvent, requestPausedEvent, redirectedFrom, serviceWorker } = options; const { session, context, frame, documentId, route, requestWillBeSentEvent, requestPausedEvent, redirectedFrom, serviceWorker, headersOverride } = options;
this.session = session; this.session = session;
this._timestamp = requestWillBeSentEvent.timestamp; this._timestamp = requestWillBeSentEvent.timestamp;
this._wallTime = requestWillBeSentEvent.wallTime; this._wallTime = requestWillBeSentEvent.wallTime;
@ -591,7 +594,7 @@ class InterceptableRequest {
if (entries && entries.length) if (entries && entries.length)
postDataBuffer = Buffer.concat(entries.map(entry => Buffer.from(entry.bytes!, 'base64'))); postDataBuffer = Buffer.concat(entries.map(entry => Buffer.from(entry.bytes!, 'base64')));
this.request = new network.Request(context, frame, serviceWorker, redirectedFrom?.request || null, documentId, url, type, method, postDataBuffer, headersObjectToArray(headers)); this.request = new network.Request(context, frame, serviceWorker, redirectedFrom?.request || null, documentId, url, type, method, postDataBuffer, headersOverride || headersObjectToArray(headers));
} }
} }

View file

@ -412,6 +412,27 @@ it('continue should propagate headers to redirects', async ({ page, server, brow
expect(serverRequest.headers['custom']).toBe('value'); expect(serverRequest.headers['custom']).toBe('value');
}); });
it('redirected requests should report overridden headers', {
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31351' }
}, async ({ page, server, browserName }) => {
it.fixme(browserName === 'firefox');
await server.setRedirect('/redirect', '/empty.html');
await page.route('**/redirect', route => {
const headers = route.request().headers();
headers['custom'] = 'value';
void route.fallback({ headers });
});
const [serverRequest, response] = await Promise.all([
server.waitForRequest('/empty.html'),
page.goto(server.PREFIX + '/redirect')
]);
expect(serverRequest.headers['custom']).toBe('value');
expect(response.request().url()).toBe(server.EMPTY_PAGE);
expect(response.request().headers()['custom']).toBe('value');
expect((await response.request().allHeaders())['custom']).toBe('value');
});
it('continue should delete headers on redirects', async ({ page, server, browserName }) => { it('continue should delete headers on redirects', async ({ page, server, browserName }) => {
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/13106' }); it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/13106' });
it.fixme(browserName === 'firefox'); it.fixme(browserName === 'firefox');