From be67189a54de422b1567110c54d7fcfefea5ae3e Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Mon, 24 Oct 2022 12:51:45 -0700 Subject: [PATCH] fix(fetch): throw on unexpected end of file brotli requests (#18223) https://github.com/microsoft/playwright/issues/18190 --- packages/playwright-core/src/server/fetch.ts | 1 + tests/library/browsercontext-fetch.spec.ts | 23 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/packages/playwright-core/src/server/fetch.ts b/packages/playwright-core/src/server/fetch.ts index d9130a9a9f..44df8f6a5d 100644 --- a/packages/playwright-core/src/server/fetch.ts +++ b/packages/playwright-core/src/server/fetch.ts @@ -360,6 +360,7 @@ export abstract class APIRequestContext extends SdkObject { if (e) reject(new Error(`failed to decompress '${encoding}' encoding: ${e}`)); }); + body.on('error', e => reject(new Error(`failed to decompress '${encoding}' encoding: ${e}`))); } else { body.on('error', reject); } diff --git a/tests/library/browsercontext-fetch.spec.ts b/tests/library/browsercontext-fetch.spec.ts index d5c89ae5b6..cb2fb335c0 100644 --- a/tests/library/browsercontext-fetch.spec.ts +++ b/tests/library/browsercontext-fetch.spec.ts @@ -758,6 +758,29 @@ it('should respect timeout after redirects', async function({ context, server }) expect(error.message).toContain(`Request timed out after 100ms`); }); +it('should not hang on a brotli encoded Range request', async ({ context, server }) => { + it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/18190' }); + it.skip(+process.versions.node.split('.')[0] < 18); + + const encodedRequestPayload = zlib.brotliCompressSync(Buffer.from('A')); + server.setRoute('/brotli', (req, res) => { + res.writeHead(206, { + 'Content-Type': 'text/plain', + 'content-length': 1, + 'Content-Encoding': 'br', + 'content-range': `bytes 0-2/${encodedRequestPayload.byteLength}`, + 'Accept-Ranges': 'bytes', + }); + res.write(encodedRequestPayload.slice(0, 2)); + }); + + await expect(context.request.get(server.PREFIX + '/brotli', { + headers: { + range: 'bytes=0-2', + }, + })).rejects.toThrow(`failed to decompress 'br' encoding: Error: unexpected end of file`); +}); + it('should dispose', async function({ context, server }) { const response = await context.request.get(server.PREFIX + '/simple.json'); expect(await response.json()).toEqual({ foo: 'bar' });