feat(fetch): fetch with request parameter (#8793)

This commit is contained in:
Yury Semikhatsky 2021-09-08 16:31:58 -07:00 коммит произвёл GitHub
Родитель b11b274b0d
Коммит 5550f58284
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 42 добавлений и 8 удалений

Просмотреть файл

@ -28,7 +28,7 @@ import { Events } from './events';
import { TimeoutSettings } from '../utils/timeoutSettings';
import { Waiter } from './waiter';
import { URLMatch, Headers, WaitForEventOptions, BrowserContextOptions, StorageState, LaunchOptions } from './types';
import { isUnderTest, headersObjectToArray, mkdirIfNeeded, isString } from '../utils/utils';
import { isUnderTest, headersObjectToArray, mkdirIfNeeded, isString, assert } from '../utils/utils';
import { isSafeCloseError } from '../utils/errors';
import * as api from '../../types/types';
import * as structs from '../../types/structs';
@ -216,14 +216,26 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel,
});
}
async _fetch(url: string, options: FetchOptions = {}): Promise<network.FetchResponse> {
async _fetch(request: network.Request, options?: { timeout?: number }): Promise<network.FetchResponse>;
async _fetch(url: string, options?: FetchOptions): Promise<network.FetchResponse>;
async _fetch(urlOrRequest: string|network.Request, options: FetchOptions = {}): Promise<network.FetchResponse> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
const postDataBuffer = isString(options.postData) ? Buffer.from(options.postData, 'utf8') : options.postData;
const request: network.Request | undefined = (urlOrRequest instanceof network.Request) ? urlOrRequest as network.Request : undefined;
assert(request || typeof urlOrRequest === 'string', 'First argument must be either URL string or Request');
const url = request ? request.url() : urlOrRequest as string;
const method = request?.method() || options.method;
// Cannot call allHeaders() here as the request may be paused inside route handler.
const headersObj = request?.headers() || options.headers;
const headers = headersObj ? headersObjectToArray(headersObj) : undefined;
let postDataBuffer = request?.postDataBuffer();
if (postDataBuffer === undefined)
postDataBuffer = (isString(options.postData) ? Buffer.from(options.postData, 'utf8') : options.postData);
const postData = (postDataBuffer ? postDataBuffer.toString('base64') : undefined);
const result = await channel.fetch({
url,
method: options.method,
headers: options.headers ? headersObjectToArray(options.headers) : undefined,
postData: postDataBuffer ? postDataBuffer.toString('base64') : undefined,
method,
headers,
postData,
timeout: options.timeout,
});
if (result.error)

Просмотреть файл

@ -438,8 +438,10 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
return this._mainFrame.evaluate(pageFunction, arg);
}
async _fetch(url: string, options: FetchOptions = {}): Promise<network.FetchResponse> {
return await this._browserContext._fetch(url, options);
async _fetch(request: network.Request, options?: { timeout?: number }): Promise<network.FetchResponse>;
async _fetch(url: string, options?: FetchOptions): Promise<network.FetchResponse>;
async _fetch(urlOrRequest: string|network.Request, options: FetchOptions = {}): Promise<network.FetchResponse> {
return await this._browserContext._fetch(urlOrRequest as any, options);
}
async addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any) {

Просмотреть файл

@ -632,3 +632,9 @@ it('should dispose when context closes', async function({context, server}) {
expect(error.message).toContain('Target page, context or browser has been closed');
});
it('should throw on invalid first argument', async function({context, server}) {
// @ts-expect-error
const error = await context._fetch({}).catch(e => e);
expect(error.message).toContain('First argument must be either URL string or Request');
});

Просмотреть файл

@ -224,3 +224,17 @@ it('should fulfill with fetch result and overrides', async ({page, server}) => {
expect((await response.allHeaders()).foo).toEqual('bar');
expect(await response.json()).toEqual({'foo': 'bar'});
});
it('should fetch original request and fulfill', async ({page, server}) => {
await page.route('**/*', async route => {
// @ts-expect-error
const response = await page._fetch(route.request());
route.fulfill({
// @ts-expect-error
response,
});
});
const response = await page.goto(server.PREFIX + '/title.html');
expect(response.status()).toBe(200);
expect(await page.title()).toEqual('Woof-Woof');
});