feat(fetch): set user-agent and other default headers (#8491)
This commit is contained in:
parent
16a7de5dab
commit
768a97cfdc
|
|
@ -78,6 +78,7 @@ export abstract class Browser extends SdkObject {
|
||||||
abstract contexts(): BrowserContext[];
|
abstract contexts(): BrowserContext[];
|
||||||
abstract isConnected(): boolean;
|
abstract isConnected(): boolean;
|
||||||
abstract version(): string;
|
abstract version(): string;
|
||||||
|
abstract userAgent(): string;
|
||||||
|
|
||||||
_downloadCreated(page: Page, uuid: string, url: string, suggestedFilename?: string) {
|
_downloadCreated(page: Page, uuid: string, url: string, suggestedFilename?: string) {
|
||||||
const download = new Download(page, this.options.downloadsPath || '', uuid, url, suggestedFilename);
|
const download = new Download(page, this.options.downloadsPath || '', uuid, url, suggestedFilename);
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ export class CRBrowser extends Browser {
|
||||||
private _tracingRecording = false;
|
private _tracingRecording = false;
|
||||||
private _tracingPath: string | null = '';
|
private _tracingPath: string | null = '';
|
||||||
private _tracingClient: CRSession | undefined;
|
private _tracingClient: CRSession | undefined;
|
||||||
|
private _userAgent: string = '';
|
||||||
|
|
||||||
static async connect(transport: ConnectionTransport, options: BrowserOptions, devtools?: CRDevTools): Promise<CRBrowser> {
|
static async connect(transport: ConnectionTransport, options: BrowserOptions, devtools?: CRDevTools): Promise<CRBrowser> {
|
||||||
const connection = new CRConnection(transport, options.protocolLogger, options.browserLogsCollector);
|
const connection = new CRConnection(transport, options.protocolLogger, options.browserLogsCollector);
|
||||||
|
|
@ -57,6 +58,7 @@ export class CRBrowser extends Browser {
|
||||||
const version = await session.send('Browser.getVersion');
|
const version = await session.send('Browser.getVersion');
|
||||||
browser._isMac = version.userAgent.includes('Macintosh');
|
browser._isMac = version.userAgent.includes('Macintosh');
|
||||||
browser._version = version.product.substring(version.product.indexOf('/') + 1);
|
browser._version = version.product.substring(version.product.indexOf('/') + 1);
|
||||||
|
browser._userAgent = version.userAgent;
|
||||||
if (!options.persistent) {
|
if (!options.persistent) {
|
||||||
await session.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true });
|
await session.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true });
|
||||||
return browser;
|
return browser;
|
||||||
|
|
@ -107,6 +109,10 @@ export class CRBrowser extends Browser {
|
||||||
return this._version;
|
return this._version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userAgent(): string {
|
||||||
|
return this._userAgent;
|
||||||
|
}
|
||||||
|
|
||||||
isClank(): boolean {
|
isClank(): boolean {
|
||||||
return this.options.name === 'clank';
|
return this.options.name === 'clank';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,24 @@ import * as types from './types';
|
||||||
|
|
||||||
export async function playwrightFetch(context: BrowserContext, params: types.FetchOptions): Promise<{fetchResponse?: types.FetchResponse, error?: string}> {
|
export async function playwrightFetch(context: BrowserContext, params: types.FetchOptions): Promise<{fetchResponse?: types.FetchResponse, error?: string}> {
|
||||||
try {
|
try {
|
||||||
const cookies = await context.cookies(params.url);
|
const headers: { [name: string]: string } = {};
|
||||||
const valueArray = cookies.map(c => `${c.name}=${c.value}`);
|
if (params.headers) {
|
||||||
const clientCookie = params.headers?.['cookie'];
|
for (const [name, value] of Object.entries(params.headers))
|
||||||
if (clientCookie)
|
headers[name.toLowerCase()] = value;
|
||||||
valueArray.unshift(clientCookie);
|
}
|
||||||
const cookieHeader = valueArray.join('; ');
|
if (headers['user-agent'] === undefined)
|
||||||
if (cookieHeader) {
|
headers['user-agent'] = context._options.userAgent || context._browser.userAgent();
|
||||||
if (!params.headers)
|
if (headers['accept'] === undefined)
|
||||||
params.headers = {};
|
headers['accept'] = '*/*';
|
||||||
params.headers['cookie'] = cookieHeader;
|
if (headers['accept-encoding'] === undefined)
|
||||||
|
headers['accept-encoding'] = 'gzip,deflate';
|
||||||
|
|
||||||
|
if (headers['cookie'] === undefined) {
|
||||||
|
const cookies = await context.cookies(params.url);
|
||||||
|
if (cookies.length) {
|
||||||
|
const valueArray = cookies.map(c => `${c.name}=${c.value}`);
|
||||||
|
headers['cookie'] = valueArray.join('; ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!params.method)
|
if (!params.method)
|
||||||
params.method = 'GET';
|
params.method = 'GET';
|
||||||
|
|
@ -48,7 +56,7 @@ export async function playwrightFetch(context: BrowserContext, params: types.Fet
|
||||||
// TODO(https://github.com/microsoft/playwright/issues/8381): set user agent
|
// TODO(https://github.com/microsoft/playwright/issues/8381): set user agent
|
||||||
const {fetchResponse, setCookie} = await sendRequest(new URL(params.url), {
|
const {fetchResponse, setCookie} = await sendRequest(new URL(params.url), {
|
||||||
method: params.method,
|
method: params.method,
|
||||||
headers: params.headers,
|
headers: headers,
|
||||||
agent,
|
agent,
|
||||||
maxRedirects: 20
|
maxRedirects: 20
|
||||||
}, params.postData);
|
}, params.postData);
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ export class FFBrowser extends Browser {
|
||||||
readonly _ffPages: Map<string, FFPage>;
|
readonly _ffPages: Map<string, FFPage>;
|
||||||
readonly _contexts: Map<string, FFBrowserContext>;
|
readonly _contexts: Map<string, FFBrowserContext>;
|
||||||
private _version = '';
|
private _version = '';
|
||||||
|
private _userAgent: string = '';
|
||||||
|
|
||||||
static async connect(transport: ConnectionTransport, options: BrowserOptions): Promise<FFBrowser> {
|
static async connect(transport: ConnectionTransport, options: BrowserOptions): Promise<FFBrowser> {
|
||||||
const connection = new FFConnection(transport, options.protocolLogger, options.browserLogsCollector);
|
const connection = new FFConnection(transport, options.protocolLogger, options.browserLogsCollector);
|
||||||
|
|
@ -68,6 +69,7 @@ export class FFBrowser extends Browser {
|
||||||
async _initVersion() {
|
async _initVersion() {
|
||||||
const result = await this._connection.send('Browser.getInfo');
|
const result = await this._connection.send('Browser.getInfo');
|
||||||
this._version = result.version.substring(result.version.indexOf('/') + 1);
|
this._version = result.version.substring(result.version.indexOf('/') + 1);
|
||||||
|
this._userAgent = result.userAgent;
|
||||||
}
|
}
|
||||||
|
|
||||||
isConnected(): boolean {
|
isConnected(): boolean {
|
||||||
|
|
@ -93,6 +95,10 @@ export class FFBrowser extends Browser {
|
||||||
return this._version;
|
return this._version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userAgent(): string {
|
||||||
|
return this._userAgent;
|
||||||
|
}
|
||||||
|
|
||||||
_onDetachedFromTarget(payload: Protocol.Browser.detachedFromTargetPayload) {
|
_onDetachedFromTarget(payload: Protocol.Browser.detachedFromTargetPayload) {
|
||||||
const ffPage = this._ffPages.get(payload.targetId)!;
|
const ffPage = this._ffPages.get(payload.targetId)!;
|
||||||
this._ffPages.delete(payload.targetId);
|
this._ffPages.delete(payload.targetId);
|
||||||
|
|
|
||||||
|
|
@ -371,7 +371,7 @@ export type SetStorageState = {
|
||||||
export type FetchOptions = {
|
export type FetchOptions = {
|
||||||
url: string,
|
url: string,
|
||||||
method?: string,
|
method?: string,
|
||||||
headers?: { [name: string]: string },
|
headers?: { [name: string]: string },
|
||||||
postData?: Buffer,
|
postData?: Buffer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,10 @@ export class WKBrowser extends Browser {
|
||||||
return BROWSER_VERSION;
|
return BROWSER_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userAgent(): string {
|
||||||
|
return DEFAULT_USER_AGENT;
|
||||||
|
}
|
||||||
|
|
||||||
_onDownloadCreated(payload: Protocol.Playwright.downloadCreatedPayload) {
|
_onDownloadCreated(payload: Protocol.Playwright.downloadCreatedPayload) {
|
||||||
const page = this._wkPages.get(payload.pageProxyId);
|
const page = this._wkPages.get(payload.pageProxyId);
|
||||||
if (!page)
|
if (!page)
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,29 @@ it('should add session cookies to request', async ({context, server}) => {
|
||||||
expect(req.headers.cookie).toEqual('username=John Doe');
|
expect(req.headers.cookie).toEqual('username=John Doe');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not add context cookie if cookie header passed as a parameter', async ({context, server}) => {
|
||||||
|
await context.addCookies([{
|
||||||
|
name: 'username',
|
||||||
|
value: 'John Doe',
|
||||||
|
domain: '.my.playwright.dev',
|
||||||
|
path: '/',
|
||||||
|
expires: -1,
|
||||||
|
httpOnly: false,
|
||||||
|
secure: false,
|
||||||
|
sameSite: 'Lax',
|
||||||
|
}]);
|
||||||
|
const [req] = await Promise.all([
|
||||||
|
server.waitForRequest('/empty.html'),
|
||||||
|
// @ts-expect-error
|
||||||
|
context._fetch(`http://www.my.playwright.dev:${server.PORT}/empty.html`, {
|
||||||
|
headers: {
|
||||||
|
'Cookie': 'foo=bar'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
expect(req.headers.cookie).toEqual('foo=bar');
|
||||||
|
});
|
||||||
|
|
||||||
it('should follow redirects', async ({context, server}) => {
|
it('should follow redirects', async ({context, server}) => {
|
||||||
server.setRedirect('/redirect1', '/redirect2');
|
server.setRedirect('/redirect1', '/redirect2');
|
||||||
server.setRedirect('/redirect2', '/simple.json');
|
server.setRedirect('/redirect2', '/simple.json');
|
||||||
|
|
@ -172,3 +195,32 @@ it('should support post data', async ({context, server}) => {
|
||||||
expect(response.status()).toBe(200);
|
expect(response.status()).toBe(200);
|
||||||
expect(request.url).toBe('/simple.json');
|
expect(request.url).toBe('/simple.json');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should add default headers', async ({context, server, page}) => {
|
||||||
|
const [request] = await Promise.all([
|
||||||
|
server.waitForRequest('/empty.html'),
|
||||||
|
// @ts-expect-error
|
||||||
|
context._fetch(server.EMPTY_PAGE)
|
||||||
|
]);
|
||||||
|
expect(request.headers['accept']).toBe('*/*');
|
||||||
|
const userAgent = await page.evaluate(() => navigator.userAgent);
|
||||||
|
expect(request.headers['user-agent']).toBe(userAgent);
|
||||||
|
expect(request.headers['accept-encoding']).toBe('gzip,deflate');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow to override default headers', async ({context, server, page}) => {
|
||||||
|
const [request] = await Promise.all([
|
||||||
|
server.waitForRequest('/empty.html'),
|
||||||
|
// @ts-expect-error
|
||||||
|
context._fetch(server.EMPTY_PAGE, {
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'Playwright',
|
||||||
|
'Accept': 'text/html',
|
||||||
|
'Accept-Encoding': 'br'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
expect(request.headers['accept']).toBe('text/html');
|
||||||
|
expect(request.headers['user-agent']).toBe('Playwright');
|
||||||
|
expect(request.headers['accept-encoding']).toBe('br');
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue