Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Handle multiple/duplicate Fetch.requestPaused events #7802

Merged
merged 11 commits into from Dec 3, 2021
10 changes: 9 additions & 1 deletion src/common/NetworkManager.ts
Expand Up @@ -368,6 +368,15 @@ export class NetworkManager extends EventEmitter {
.catch(debugError);
}

/**
* CDP may send a Fetch.requestPaused without or before a
* Network.requestWillBeSent
*
* CDP may send multiple Fetch.requestPaused
* for the same Network.requestWillBeSent.
benallfree marked this conversation as resolved.
Show resolved Hide resolved
*
*
*/
_onRequestPaused(event: Protocol.Fetch.RequestPausedEvent): void {
if (
!this._userRequestInterceptionEnabled &&
Expand Down Expand Up @@ -402,7 +411,6 @@ export class NetworkManager extends EventEmitter {

if (requestWillBeSentEvent) {
this._onRequest(requestWillBeSentEvent, interceptionId);
this._requestIdToRequestWillBeSentEvent.delete(requestId);
benallfree marked this conversation as resolved.
Show resolved Hide resolved
} else {
this._requestIdToRequestPausedEvent.set(requestId, event);
}
Expand Down
97 changes: 92 additions & 5 deletions test/NetworkManager.spec.ts
Expand Up @@ -16,16 +16,21 @@

import { describeChromeOnly } from './mocha-utils'; // eslint-disable-line import/extensions

import { NetworkManager } from '../lib/cjs/puppeteer/common/NetworkManager.js';
import expect from 'expect';
import {
NetworkManager,
NetworkManagerEmittedEvents,
} from '../lib/cjs/puppeteer/common/NetworkManager.js';
import { HTTPRequest } from '../lib/cjs/puppeteer/common/HTTPRequest.js';
import { EventEmitter } from '../lib/cjs/puppeteer/common/EventEmitter.js';
import { Frame } from '../lib/cjs/puppeteer/common/FrameManager.js';

class MockCDPSession extends EventEmitter {
async send(): Promise<any> {}
}

describeChromeOnly('NetworkManager', () => {
it('should process extra info on multiple redirects', async () => {
class MockCDPSession extends EventEmitter {
send(): any {}
}

const mockCDPSession = new MockCDPSession();
new NetworkManager(mockCDPSession, true, {
frame(): Frame | null {
Expand Down Expand Up @@ -456,4 +461,86 @@ describeChromeOnly('NetworkManager', () => {
frameId: '099A5216AF03AAFEC988F214B024DF08',
});
});
it(`should handle multiple Fetch.requestPaused events for the same Network.requestWillBeSent event`, async () => {
const mockCDPSession = new MockCDPSession();
const manager = new NetworkManager(mockCDPSession, true, {
frame(): Frame | null {
return null;
},
});
manager.setRequestInterception(true);

const requests: HTTPRequest[] = [];
manager.on(NetworkManagerEmittedEvents.Request, (request: HTTPRequest) => {
request.continue();
requests.push(request);
});

/**
* This sequence was taken from an actual CDP session produced by the following
* test script:
*
* const browser = await puppeteer.launch({ headless: false });
* const page = await browser.newPage();
* await page.setCacheEnabled(false);
*
* await page.setRequestInterception(true)
* page.on('request', (interceptedRequest) => {
* interceptedRequest.continue();
* });
*
* await page.goto('https://www.google.com');
* await browser.close();
*
*/
mockCDPSession.emit('Network.requestWillBeSent', {
requestId: '11ACE9783588040D644B905E8B55285B',
loaderId: '11ACE9783588040D644B905E8B55285B',
documentURL: 'https://www.google.com/',
request: {
url: 'https://www.google.com/',
method: 'GET',
headers: [Object],
mixedContentType: 'none',
initialPriority: 'VeryHigh',
referrerPolicy: 'strict-origin-when-cross-origin',
isSameSite: true,
},
timestamp: 224604.980827,
wallTime: 1637955746.786191,
initiator: { type: 'other' },
redirectHasExtraInfo: false,
type: 'Document',
frameId: '84AC261A351B86932B775B76D1DD79F8',
hasUserGesture: false,
});
mockCDPSession.emit('Fetch.requestPaused', {
requestId: 'interception-job-1.0',
request: {
url: 'https://www.google.com/',
method: 'GET',
headers: [Object],
initialPriority: 'VeryHigh',
referrerPolicy: 'strict-origin-when-cross-origin',
},
frameId: '84AC261A351B86932B775B76D1DD79F8',
resourceType: 'Document',
networkId: '11ACE9783588040D644B905E8B55285B',
});
mockCDPSession.emit('Fetch.requestPaused', {
requestId: 'interception-job-2.0',
request: {
url: 'https://www.google.com/',
method: 'GET',
headers: [Object],
initialPriority: 'VeryHigh',
referrerPolicy: 'strict-origin-when-cross-origin',
},
frameId: '84AC261A351B86932B775B76D1DD79F8',
resourceType: 'Document',
networkId: '11ACE9783588040D644B905E8B55285B',
});

expect(requests.length).toBe(2);
});
});