fix(har): do not throw on -1 status code (#29371)

Fixes https://github.com/microsoft/playwright/issues/29311
This commit is contained in:
Yury Semikhatsky 2024-02-06 10:17:29 -08:00 committed by GitHub
parent 18ce0fa370
commit 721d84f17a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 39 additions and 0 deletions

View file

@ -62,6 +62,13 @@ export class HarRouter {
} }
if (response.action === 'fulfill') { if (response.action === 'fulfill') {
// If the response status is -1, the request was canceled or stalled, so we just stall it here.
// See https://github.com/microsoft/playwright/issues/29311.
// TODO: it'd be better to abort such requests, but then we likely need to respect the timing,
// because the request might have been stalled for a long time until the very end of the
// test when HAR was recorded but we'd abort it immediately.
if (response.status === -1)
return;
await route.fulfill({ await route.fulfill({
status: response.status, status: response.status,
headers: Object.fromEntries(response.headers!.map(h => [h.name, h.value])), headers: Object.fromEntries(response.headers!.map(h => [h.name, h.value])),

View file

@ -486,3 +486,35 @@ it('context.unrouteAll should stop context.routeFromHAR', async ({ contextFactor
const response = await page1.goto(server.EMPTY_PAGE); const response = await page1.goto(server.EMPTY_PAGE);
expect(response.ok()).toBeTruthy(); expect(response.ok()).toBeTruthy();
}); });
it('should ignore aborted requests', async ({ contextFactory, server }) => {
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/29311' });
const path = it.info().outputPath('test.har');
{
server.setRoute('/x', (req, res) => { req.destroy(); });
const context1 = await contextFactory();
await context1.routeFromHAR(path, { update: true });
const page1 = await context1.newPage();
await page1.goto(server.EMPTY_PAGE);
const reqPromise = server.waitForRequest('/x');
const evalPromise = page1.evaluate(url => fetch(url).catch(e => 'cancelled'), server.PREFIX + '/x');
await reqPromise;
const req = await evalPromise;
expect(req).toBe('cancelled');
await context1.close();
}
server.reset();
{
server.setRoute('/x', (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('test');
});
const context2 = await contextFactory();
await context2.routeFromHAR(path);
const page2 = await context2.newPage();
await page2.goto(server.EMPTY_PAGE);
const evalPromise = page2.evaluate(url => fetch(url).catch(e => 'cancelled'), server.PREFIX + '/x');
const result = await Promise.race([evalPromise, page2.waitForTimeout(1000).then(() => 'timeout')]);
expect(result).toBe('timeout');
}
});