Skip to content

Commit d946ab3

Browse files
committed
fix: use cdp fetch
1 parent 4e889c2 commit d946ab3

File tree

1 file changed

+37
-20
lines changed

1 file changed

+37
-20
lines changed

lighthouse-setup.cjs

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,20 @@
88
* The color mode is determined by the LIGHTHOUSE_COLOR_MODE environment variable.
99
* If not set, defaults to 'dark'.
1010
*
11-
* Request interception uses CDP (Chrome DevTools Protocol) at the browser level
12-
* so it applies to all pages Lighthouse opens, not just the setup page.
11+
* Request interception uses CDP (Chrome DevTools Protocol) Fetch domain
12+
* at the browser level, which avoids conflicts with Lighthouse's own
13+
* Puppeteer-level request interception.
1314
*/
1415

1516
const mockRoutes = require('./test/fixtures/mock-routes.cjs')
1617

1718
module.exports = async function setup(browser, { url }) {
1819
const colorMode = process.env.LIGHTHOUSE_COLOR_MODE || 'dark'
1920

20-
// Set up browser-level request interception via CDP.
21-
// This ensures mocking applies to pages Lighthouse creates after setup.
22-
setupBrowserRequestInterception(browser)
21+
// Set up browser-level request interception via CDP Fetch domain.
22+
// This operates below Puppeteer's request interception layer so it
23+
// doesn't conflict with Lighthouse's own setRequestInterception usage.
24+
await setupCdpRequestInterception(browser)
2325

2426
const page = await browser.newPage()
2527

@@ -36,37 +38,52 @@ module.exports = async function setup(browser, { url }) {
3638
}
3739

3840
/**
39-
* Set up request interception on every new page target the browser creates.
40-
* Uses Puppeteer's page-level request interception, applied automatically
41-
* to each new page via the 'targetcreated' event.
41+
* Set up request interception using CDP's Fetch domain on the browser's
42+
* default context. This intercepts requests at a lower level than Puppeteer's
43+
* page.setRequestInterception(), avoiding "Request is already handled!" errors
44+
* when Lighthouse sets up its own interception.
4245
*
4346
* @param {import('puppeteer').Browser} browser
4447
*/
45-
function setupBrowserRequestInterception(browser) {
48+
async function setupCdpRequestInterception(browser) {
49+
// Build URL pattern list for CDP Fetch.enable from our route definitions
50+
const cdpPatterns = mockRoutes.routes.map(route => ({
51+
urlPattern: route.pattern.replace('/**', '/*'),
52+
requestStage: 'Request',
53+
}))
54+
55+
// Listen for new targets so we can attach CDP interception to each page
4656
browser.on('targetcreated', async target => {
4757
if (target.type() !== 'page') return
4858

4959
try {
50-
const page = await target.page()
51-
if (!page) return
60+
const cdp = await target.createCDPSession()
5261

53-
await page.setRequestInterception(true)
54-
page.on('request', request => {
55-
const requestUrl = request.url()
62+
cdp.on('Fetch.requestPaused', async event => {
63+
const requestUrl = event.request.url
5664
const result = mockRoutes.matchRoute(requestUrl)
5765

5866
if (result) {
59-
request.respond({
60-
status: result.response.status,
61-
contentType: result.response.contentType,
62-
body: result.response.body,
67+
const body = Buffer.from(result.response.body).toString('base64')
68+
await cdp.send('Fetch.fulfillRequest', {
69+
requestId: event.requestId,
70+
responseCode: result.response.status,
71+
responseHeaders: [
72+
{ name: 'Content-Type', value: result.response.contentType },
73+
{ name: 'Access-Control-Allow-Origin', value: '*' },
74+
],
75+
body,
6376
})
6477
} else {
65-
request.continue()
78+
await cdp.send('Fetch.continueRequest', {
79+
requestId: event.requestId,
80+
})
6681
}
6782
})
83+
84+
await cdp.send('Fetch.enable', { patterns: cdpPatterns })
6885
} catch {
69-
// Target may have been closed before we could set up interception.
86+
// Target may have been closed before we could attach.
7087
// This is expected for transient targets like service workers.
7188
}
7289
})

0 commit comments

Comments
 (0)