Skip to content

Commit 962814b

Browse files
committed
chore(bidi): add support for fetching request bodies
1 parent 34a09f3 commit 962814b

File tree

15 files changed

+69
-47
lines changed

15 files changed

+69
-47
lines changed

packages/playwright-core/src/client/fetch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ export class APIRequestContext extends ChannelOwner<channels.APIRequestContextCh
239239
}
240240
}
241241
if (postDataBuffer === undefined && jsonData === undefined && formData === undefined && multipartData === undefined)
242-
postDataBuffer = options.request?.postDataBuffer() || undefined;
242+
postDataBuffer = (await options.request?.bodyBuffer()) || undefined;
243243
const fixtures = {
244244
__testHookLookup: (options as any).__testHookLookup
245245
};

packages/playwright-core/src/client/harRouter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export class HarRouter {
5050
url: request.url(),
5151
method: request.method(),
5252
headers: (await request.headersArray()),
53-
postData: request.postDataBuffer() || undefined,
53+
postData: (await request.bodyBuffer()) || undefined,
5454
isNavigationRequest: request.isNavigationRequest()
5555
});
5656

packages/playwright-core/src/server/bidi/bidiBrowser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export class BidiBrowser extends Browser {
7474
});
7575

7676
await browser._browserSession.send('network.addDataCollector', {
77-
dataTypes: [bidi.Network.DataType.Response],
77+
dataTypes: [bidi.Network.DataType.Request, bidi.Network.DataType.Response],
7878
maxEncodedDataSize: 20_000_000, // same default as in CDP: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/inspector/inspector_network_agent.cc;l=134;drc=4128411589187a396829a827f59a655bed876aa7
7979
});
8080

packages/playwright-core/src/server/bidi/bidiNetworkManager.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ export class BidiNetworkManager {
7979
route = new BidiRouteImpl(this._session, param.request.request);
8080
}
8181
}
82-
const request = new BidiRequest(frame, redirectedFrom, param, route);
82+
const getRequestBody = param.request.bodySize ? () => getNetworkData(this._session, param.request, bidi.Network.DataType.Request) : null;
83+
const request = new BidiRequest(frame, redirectedFrom, param, getRequestBody, route);
8384
this._requests.set(request._id, request);
8485
this._page.frameManager.requestStarted(request.request, route);
8586
}
@@ -88,11 +89,7 @@ export class BidiNetworkManager {
8889
const request = this._requests.get(params.request.request);
8990
if (!request)
9091
return;
91-
const getResponseBody = async () => {
92-
const { bytes } = await this._session.send('network.getData', { request: params.request.request, dataType: bidi.Network.DataType.Response });
93-
const encoding = bytes.type === 'base64' ? 'base64' : 'utf8';
94-
return Buffer.from(bytes.value, encoding);
95-
};
92+
const getResponseBody = () => getNetworkData(this._session, params.request, bidi.Network.DataType.Response);
9693
const timings = params.request.timings;
9794
const startTime = timings.requestTime;
9895
function relativeToStart(time: number): number {
@@ -236,14 +233,12 @@ class BidiRequest {
236233
// store the first and only Route in the chain (if any).
237234
_originalRequestRoute: BidiRouteImpl | undefined;
238235

239-
constructor(frame: frames.Frame, redirectedFrom: BidiRequest | null, payload: bidi.Network.BeforeRequestSentParameters, route: BidiRouteImpl | undefined) {
236+
constructor(frame: frames.Frame, redirectedFrom: BidiRequest | null, payload: bidi.Network.BeforeRequestSentParameters, getRequestBody: (() => Promise<Buffer>) | null, route: BidiRouteImpl | undefined) {
240237
this._id = payload.request.request;
241238
if (redirectedFrom)
242239
redirectedFrom._redirectedTo = this;
243-
// TODO: missing in the spec?
244-
const postDataBuffer = null;
245240
this.request = new network.Request(frame._page.browserContext, frame, null, redirectedFrom ? redirectedFrom.request : null, payload.navigation ?? undefined, payload.request.url,
246-
resourceTypeFromBidi(payload.request.destination, payload.request.initiatorType, payload.initiator?.type), payload.request.method, postDataBuffer, fromBidiHeaders(payload.request.headers));
241+
resourceTypeFromBidi(payload.request.destination, payload.request.initiatorType, payload.initiator?.type), payload.request.method, getRequestBody, fromBidiHeaders(payload.request.headers));
247242
// "raw" headers are the same as "provisional" headers in Bidi.
248243
this.request.setRawRequestHeaders(null);
249244
this.request._setBodySize(payload.request.bodySize || 0);
@@ -390,3 +385,9 @@ function resourceTypeFromBidi(requestDestination: string, requestInitiatorType:
390385
default: return 'other';
391386
}
392387
}
388+
389+
async function getNetworkData(session: BidiSession, request: bidi.Network.RequestData, dataType: bidi.Network.DataType) {
390+
const { bytes } = await session.send('network.getData', { request: request.request, dataType });
391+
const encoding = bytes.type === 'base64' ? 'base64' : 'utf8';
392+
return Buffer.from(bytes.value, encoding);
393+
}

packages/playwright-core/src/server/bidi/third_party/bidiProtocolCore.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,7 @@ export namespace Network {
13831383
}
13841384
export namespace Network {
13851385
export const enum DataType {
1386+
Request = 'request',
13861387
Response = 'response',
13871388
}
13881389
}

packages/playwright-core/src/server/dispatchers/networkDispatchers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export class RequestDispatcher extends Dispatcher<Request, channels.RequestChann
6767
}
6868

6969
async body(params: channels.RequestBodyParams, progress: Progress): Promise<channels.RequestBodyResult> {
70-
const postData = this._object.postDataBuffer();
70+
const postData = await this._object.body();
7171
return { body: postData === null ? undefined : postData };
7272
}
7373

packages/playwright-core/src/server/network.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export class Request extends SdkObject {
104104
private _url: string;
105105
private _resourceType: string;
106106
private _method: string;
107-
private _postData: Buffer | null;
107+
private _postData: Buffer | null | (() => Promise<Buffer>);
108108
readonly _headers: HeadersArray;
109109
private _headersMap = new Map<string, string>();
110110
readonly _frame: frames.Frame | null = null;
@@ -122,7 +122,7 @@ export class Request extends SdkObject {
122122
};
123123

124124
constructor(context: contexts.BrowserContext, frame: frames.Frame | null, serviceWorker: pages.Worker | null, redirectedFrom: Request | null, documentId: string | undefined,
125-
url: string, resourceType: string, method: string, postData: Buffer | null, headers: HeadersArray) {
125+
url: string, resourceType: string, method: string, postData: Buffer | null | (() => Promise<Buffer>), headers: HeadersArray) {
126126
super(frame || context, 'request');
127127
assert(!url.startsWith('data:'), 'Data urls should not fire requests');
128128
this._context = context;
@@ -173,8 +173,22 @@ export class Request extends SdkObject {
173173
return this._overrides?.method || this._method;
174174
}
175175

176+
async body(): Promise<Buffer | null> {
177+
if (this._overrides?.postData)
178+
return this._overrides?.postData;
179+
if (typeof this._postData === 'function')
180+
return await this._postData();
181+
else
182+
return this._postData;
183+
}
184+
176185
postDataBuffer(): Buffer | null {
177-
return this._overrides?.postData || this._postData;
186+
if (this._overrides?.postData)
187+
return this._overrides?.postData;
188+
if (typeof this._postData === 'function')
189+
return null;
190+
else
191+
return this._postData;
178192
}
179193

180194
headers(): HeadersArray {

packages/playwright-ct-core/src/router.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export class Router {
104104
for (const { name, value } of headersArray)
105105
headers.append(name, value);
106106

107-
const buffer = request.postDataBuffer();
107+
const buffer = await request.bodyBuffer();
108108
const body = buffer?.byteLength ? new Int8Array(buffer.buffer as ArrayBuffer, buffer.byteOffset, buffer.length) : undefined;
109109

110110
const newRequest = new Request(request.url(), {

tests/library/browsercontext-har.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ it('should record overridden requests to har', async ({ contextFactory, server }
342342
await page1.route('**/echo_redir', async route => {
343343
await route.fallback({
344344
url: server.PREFIX + '/echo',
345-
postData: +route.request().postData() + 10,
345+
postData: +(await route.request().body()) + 10,
346346
});
347347
});
348348
expect(await page1.evaluate(fetchFunction, { path: '/echo_redir', body: '1' })).toBe('11');

tests/library/browsercontext-route.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ import type { Route } from '@playwright/test';
2121
it('should intercept', async ({ browser, server }) => {
2222
const context = await browser.newContext();
2323
let intercepted = false;
24-
await context.route('**/empty.html', route => {
24+
await context.route('**/empty.html', async route => {
2525
intercepted = true;
2626
const request = route.request();
2727
expect(request.url()).toContain('empty.html');
2828
expect(request.headers()['user-agent']).toBeTruthy();
2929
expect(request.method()).toBe('GET');
30-
expect(request.postData()).toBe(null);
30+
expect(await request.body()).toBe(null);
3131
expect(request.isNavigationRequest()).toBe(true);
3232
expect(request.resourceType()).toBe('document');
3333
expect(request.frame() === page.mainFrame()).toBe(true);

0 commit comments

Comments
 (0)