mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(fetch): allow UTF-8 in Location header (#30904)
This commit is contained in:
parent
042896472b
commit
a93ad3dade
@ -336,12 +336,15 @@ export abstract class APIRequestContext extends SdkObject {
|
||||
redirectOptions.rejectUnauthorized = false;
|
||||
|
||||
// HTTP-redirect fetch step 4: If locationURL is null, then return response.
|
||||
if (response.headers.location) {
|
||||
// Best-effort UTF-8 decoding, per spec it's US-ASCII only, but browsers are more lenient.
|
||||
// Node.js parses it as Latin1 via std::v8::String, so we convert it to UTF-8.
|
||||
const locationHeaderValue = Buffer.from(response.headers.location ?? '', 'latin1').toString('utf8');
|
||||
if (locationHeaderValue) {
|
||||
let locationURL;
|
||||
try {
|
||||
locationURL = new URL(response.headers.location, url);
|
||||
locationURL = new URL(locationHeaderValue, url);
|
||||
} catch (error) {
|
||||
reject(new Error(`uri requested responds with an invalid redirect URL: ${response.headers.location}`));
|
||||
reject(new Error(`uri requested responds with an invalid redirect URL: ${locationHeaderValue}`));
|
||||
request.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -198,6 +198,20 @@ it('should follow redirects', async ({ context, server }) => {
|
||||
expect(await response.json()).toEqual({ foo: 'bar' });
|
||||
});
|
||||
|
||||
it('should follow redirects correctly when Location header contains UTF-8 characters', async ({ context, server }) => {
|
||||
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/30903' });
|
||||
server.setRoute('/redirect', (req, res) => {
|
||||
// Node.js only allows US-ASCII, so we can't send invalid headers directly. Sending it as a raw response instead.
|
||||
res.socket.write('HTTP/1.1 301 Moved Permanently\r\n');
|
||||
res.socket.write(`Location: ${server.PREFIX}/empty.html?message=マスクПривет\r\n`);
|
||||
res.socket.write('\r\n');
|
||||
res.socket.uncork();
|
||||
res.socket.end();
|
||||
});
|
||||
const response = await context.request.get(server.PREFIX + '/redirect');
|
||||
expect(response.url()).toBe(server.PREFIX + '/empty.html?' + new URLSearchParams({ message: 'マスクПривет' }));
|
||||
});
|
||||
|
||||
it('should add cookies from Set-Cookie header', async ({ context, page, server }) => {
|
||||
server.setRoute('/setcookie.html', (req, res) => {
|
||||
res.setHeader('Set-Cookie', ['session=value', 'foo=bar; max-age=3600']);
|
||||
@ -794,21 +808,6 @@ it('should respect timeout after redirects', async function({ context, server })
|
||||
expect(error.message).toContain(`Request timed out after 100ms`);
|
||||
});
|
||||
|
||||
it('should throw on a redirect with an invalid URL', async ({ context, server }) => {
|
||||
server.setRedirect('/redirect', '/test');
|
||||
server.setRoute('/test', (req, res) => {
|
||||
// Node.js prevents us from responding with an invalid header, therefore we manually write the response.
|
||||
const conn = res.connection!;
|
||||
conn.write('HTTP/1.1 302\r\n');
|
||||
conn.write('Location: https://здравствуйте/\r\n');
|
||||
conn.write('\r\n');
|
||||
conn.uncork();
|
||||
conn.end();
|
||||
});
|
||||
const error = await context.request.get(server.PREFIX + '/redirect').catch(e => e);
|
||||
expect(error.message).toContain('apiRequestContext.get: uri requested responds with an invalid redirect URL');
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user