Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita0c3f27

Browse files
committed
chore(bidi): add support for fetching request bodies
1 parent34a09f3 commita0c3f27

File tree

11 files changed

+55
-40
lines changed

11 files changed

+55
-40
lines changed

‎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
awaitbrowser._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=newBidiRouteImpl(this._session,param.request.request);
8080
}
8181
}
82-
constrequest=newBidiRequest(frame,redirectedFrom,param,route);
82+
constgetRequestBody=param.request.bodySize ?()=>getNetworkData(this._session,param.request,bidi.Network.DataType.Request) :null;
83+
constrequest=newBidiRequest(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
constrequest=this._requests.get(params.request.request);
8990
if(!request)
9091
return;
91-
constgetResponseBody=async()=>{
92-
const{ bytes}=awaitthis._session.send('network.getData',{request:params.request.request,dataType:bidi.Network.DataType.Response});
93-
constencoding=bytes.type==='base64' ?'base64' :'utf8';
94-
returnBuffer.from(bytes.value,encoding);
95-
};
92+
constgetResponseBody=()=>getNetworkData(this._session,params.request,bidi.Network.DataType.Response);
9693
consttimings=params.request.timings;
9794
conststartTime=timings.requestTime;
9895
functionrelativeToStart(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-
constpostDataBuffer=null;
245240
this.request=newnetwork.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,null,fromBidiHeaders(payload.request.headers),getRequestBody);
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+
asyncfunctiongetNetworkData(session:BidiSession,request:bidi.Network.RequestData,dataType:bidi.Network.DataType){
390+
const{ bytes}=awaitsession.send('network.getData',{request:request.request, dataType});
391+
constencoding=bytes.type==='base64' ?'base64' :'utf8';
392+
returnBuffer.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
exportnamespaceNetwork{
13851385
exportconstenumDataType{
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
asyncbody(params:channels.RequestBodyParams,progress:Progress):Promise<channels.RequestBodyResult>{
70-
constpostData=this._object.postDataBuffer();
70+
constpostData=awaitthis._object.body();
7171
return{body:postData===null ?undefined :postData};
7272
}
7373

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export class Request extends SdkObject {
105105
private_resourceType:string;
106106
private_method:string;
107107
private_postData:Buffer|null;
108+
private_bodyCallback:(()=>Promise<Buffer>)|null;
108109
readonly_headers:HeadersArray;
109110
private_headersMap=newMap<string,string>();
110111
readonly_frame:frames.Frame|null=null;
@@ -122,7 +123,7 @@ export class Request extends SdkObject {
122123
};
123124

124125
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){
126+
url:string,resourceType:string,method:string,postData:Buffer|null,headers:HeadersArray,bodyCallback:(()=>Promise<Buffer>)|null=null){
126127
super(frame||context,'request');
127128
assert(!url.startsWith('data:'),'Data urls should not fire requests');
128129
this._context=context;
@@ -136,6 +137,7 @@ export class Request extends SdkObject {
136137
this._resourceType=resourceType;
137138
this._method=method;
138139
this._postData=postData;
140+
this._bodyCallback=bodyCallback;
139141
this._headers=headers;
140142
this._updateHeadersMap();
141143
this._isFavicon=url.endsWith('/favicon.ico')||!!redirectedFrom?._isFavicon;
@@ -173,6 +175,15 @@ export class Request extends SdkObject {
173175
returnthis._overrides?.method||this._method;
174176
}
175177

178+
asyncbody():Promise<Buffer|null>{
179+
if(this._overrides?.postData)
180+
returnthis._overrides?.postData;
181+
if(this._bodyCallback)
182+
returnawaitthis._bodyCallback();
183+
else
184+
returnthis._postData;
185+
}
186+
176187
postDataBuffer():Buffer|null{
177188
returnthis._overrides?.postData||this._postData;
178189
}

‎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
awaitpage1.route('**/echo_redir',asyncroute=>{
343343
awaitroute.fallback({
344344
url:server.PREFIX+'/echo',
345-
postData:+route.request().postData()+10,
345+
postData:+(awaitroute.request().body())+10,
346346
});
347347
});
348348
expect(awaitpage1.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
constcontext=awaitbrowser.newContext();
2323
letintercepted=false;
24-
awaitcontext.route('**/empty.html',route=>{
24+
awaitcontext.route('**/empty.html',asyncroute=>{
2525
intercepted=true;
2626
constrequest=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(awaitrequest.body()).toBe(null);
3131
expect(request.isNavigationRequest()).toBe(true);
3232
expect(request.resourceType()).toBe('document');
3333
expect(request.frame()===page.mainFrame()).toBe(true);

‎tests/page/network-post-data.spec.ts‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
import{testasit,expect}from'./pageTest';
1818

19-
it('should return correct postData buffer for utf-8 body',async({ page, server})=>{
19+
it.skip(({ channel})=>channel?.startsWith('bidi-chrom')||channel?.startsWith('moz-firefox'),'request.postData is not supported with BiDi');
20+
21+
it('should return correct postData buffer for utf-8 body',async({ page, server, channel})=>{
2022
awaitpage.goto(server.EMPTY_PAGE);
2123
constvalue='baẞ';
2224
const[request]=awaitPromise.all([
@@ -34,7 +36,7 @@ it('should return correct postData buffer for utf-8 body', async ({ page, server
3436
expect(request.postDataJSON()).toBe(value);
3537
});
3638

37-
it('should return post data w/o content-type @smoke',async({ page, server})=>{
39+
it('should return post data w/o content-type @smoke',async({ page, server, channel})=>{
3840
awaitpage.goto(server.EMPTY_PAGE);
3941
const[request]=awaitPromise.all([
4042
page.waitForRequest('**'),
@@ -50,7 +52,7 @@ it('should return post data w/o content-type @smoke', async ({ page, server }) =
5052
expect(request.postDataJSON()).toEqual({value:42});
5153
});
5254

53-
it('should throw on invalid JSON in post data',async({ page, server})=>{
55+
it('should throw on invalid JSON in post data',async({ page, server, channel})=>{
5456
awaitpage.goto(server.EMPTY_PAGE);
5557
const[request]=awaitPromise.all([
5658
page.waitForRequest('**'),
@@ -71,7 +73,7 @@ it('should throw on invalid JSON in post data', async ({ page, server }) => {
7173
expect(error.message).toContain('POST data is not a valid JSON object: <not a json>');
7274
});
7375

74-
it('should return post data for PUT requests',async({ page, server})=>{
76+
it('should return post data for PUT requests',async({ page, server, channel})=>{
7577
awaitpage.goto(server.EMPTY_PAGE);
7678
const[request]=awaitPromise.all([
7779
page.waitForRequest('**'),
@@ -86,7 +88,7 @@ it('should return post data for PUT requests', async ({ page, server }) => {
8688
expect(request.postDataJSON()).toEqual({value:42});
8789
});
8890

89-
it('should get post data for file/blob',async({ page, server, browserName})=>{
91+
it('should get post data for file/blob',async({ page, server, browserName, channel})=>{
9092
it.fail(browserName==='webkit'||browserName==='chromium');
9193
awaitpage.goto(server.EMPTY_PAGE);
9294
const[request]=awaitPromise.all([
@@ -106,7 +108,7 @@ it('should get post data for file/blob', async ({ page, server, browserName }) =
106108
expect(request.postData()).toBe('file-contents');
107109
});
108110

109-
it('should get post data for navigator.sendBeacon api calls',async({ page, server, browserName})=>{
111+
it('should get post data for navigator.sendBeacon api calls',async({ page, server, browserName, channel})=>{
110112
it.info().annotations.push({type:'issue',description:'https://github.com/microsoft/playwright/issues/12231'});
111113
it.fail(browserName==='chromium','postData is empty');
112114
it.fail(browserName==='webkit','postData is empty');

‎tests/page/page-network-request.spec.ts‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ it('should return postData', async ({ page, server }) => {
214214
page.on('request',r=>request=r);
215215
awaitpage.evaluate(()=>fetch('./post',{method:'POST',body:JSON.stringify({foo:'bar'})}));
216216
expect(request).toBeTruthy();
217-
expect(request.postData()).toBe('{"foo":"bar"}');
217+
expect(awaitrequest.body()).toBe('{"foo":"bar"}');
218218
});
219219

220220
it('should work with binary post data',async({ page, server})=>{
@@ -226,7 +226,7 @@ it('should work with binary post data', async ({ page, server }) => {
226226
awaitfetch('./post',{method:'POST',body:newUint8Array(Array.from(Array(256).keys()))});
227227
});
228228
expect(request).toBeTruthy();
229-
constbuffer=request.postDataBuffer();
229+
constbuffer=awaitrequest.bodyBuffer();
230230
expect(buffer.length).toBe(256);
231231
for(leti=0;i<256;++i)
232232
expect(buffer[i]).toBe(i);
@@ -242,7 +242,7 @@ it('should work with binary post data and interception', async ({ page, server }
242242
awaitfetch('./post',{method:'POST',body:newUint8Array(Array.from(Array(256).keys()))});
243243
});
244244
expect(request).toBeTruthy();
245-
constbuffer=request.postDataBuffer();
245+
constbuffer=awaitrequest.bodyBuffer();
246246
expect(buffer.length).toBe(256);
247247
for(leti=0;i<256;++i)
248248
expect(buffer[i]).toBe(i);
@@ -255,12 +255,12 @@ it('should override post data content type', async ({ page, server }) => {
255255
request=req;
256256
res.end();
257257
});
258-
awaitpage.route('**/post',(route,request)=>{
258+
awaitpage.route('**/post',async(route,request)=>{
259259
constheaders=request.headers();
260260
headers['content-type']='application/x-www-form-urlencoded; charset=UTF-8';
261261
voidroute.continue({
262262
headers,
263-
postData:request.postData()
263+
postData:awaitrequest.body()
264264
});
265265
});
266266
awaitpage.evaluate(async()=>{
@@ -270,9 +270,9 @@ it('should override post data content type', async ({ page, server }) => {
270270
expect(request.headers['content-type']).toBe('application/x-www-form-urlencoded; charset=UTF-8');
271271
});
272272

273-
it('should get |undefined| withpostData() when there is no post data',async({ page, server})=>{
273+
it('should get |undefined| withbody() when there is no post data',async({ page, server})=>{
274274
constresponse=awaitpage.goto(server.EMPTY_PAGE);
275-
expect(response.request().postData()).toBe(null);
275+
expect(awaitresponse.request().body()).toBe(null);
276276
});
277277

278278
it('should parse the json post data',async({ page, server})=>{
@@ -282,7 +282,7 @@ it('should parse the json post data', async ({ page, server }) => {
282282
page.on('request',r=>request=r);
283283
awaitpage.evaluate(()=>fetch('./post',{method:'POST',body:JSON.stringify({foo:'bar'})}));
284284
expect(request).toBeTruthy();
285-
expect(request.postDataJSON()).toEqual({'foo':'bar'});
285+
expect(awaitrequest.bodyJSON()).toEqual({'foo':'bar'});
286286
});
287287

288288
it('should parse the data if content-type is application/x-www-form-urlencoded',async({ page, server})=>{
@@ -293,7 +293,7 @@ it('should parse the data if content-type is application/x-www-form-urlencoded',
293293
awaitpage.setContent(`<form method='POST' action='/post'><input type='text' name='foo' value='bar'><input type='number' name='baz' value='123'><input type='submit'></form>`);
294294
awaitpage.click('input[type=submit]');
295295
expect(request).toBeTruthy();
296-
expect(request.postDataJSON()).toEqual({'foo':'bar','baz':'123'});
296+
expect(awaitrequest.bodyJSON()).toEqual({'foo':'bar','baz':'123'});
297297
});
298298

299299
it('should parse the data if content-type is application/x-www-form-urlencoded; charset=UTF-8',async({ page, server})=>{
@@ -307,12 +307,12 @@ it('should parse the data if content-type is application/x-www-form-urlencoded;
307307
},
308308
body:'foo=bar&baz=123'
309309
}));
310-
expect((awaitrequestPromise).postDataJSON()).toEqual({'foo':'bar','baz':'123'});
310+
expect(await(awaitrequestPromise).bodyJSON()).toEqual({'foo':'bar','baz':'123'});
311311
});
312312

313-
it('should get |undefined| withpostDataJSON() when there is no post data',async({ page, server})=>{
313+
it('should get |undefined| withbodyJSON() when there is no post data',async({ page, server})=>{
314314
constresponse=awaitpage.goto(server.EMPTY_PAGE);
315-
expect(response.request().postDataJSON()).toBe(null);
315+
expect(awaitresponse.request().bodyJSON()).toBe(null);
316316
});
317317

318318
it('should return multipart/form-data',async({ page, server, browserName, browserMajorVersion})=>{
@@ -337,7 +337,7 @@ it('should return multipart/form-data', async ({ page, server, browserName, brow
337337
expect(contentType).toMatch(re);
338338
constb=contentType.match(re)[1]!;
339339
constexpected=`--${b}\r\nContent-Disposition: form-data; name=\"name1\"\r\n\r\nvalue1\r\n--${b}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"foo.txt\"\r\nContent-Type: application/octet-stream\r\n\r\nfile-value\r\n--${b}\r\nContent-Disposition: form-data; name=\"name2\"\r\n\r\nvalue2\r\n--${b}\r\nContent-Disposition: form-data; name=\"name2\"\r\n\r\nanother-value2\r\n--${b}--\r\n`;
340-
expect(request.postDataBuffer().toString('utf8')).toEqual(expected);
340+
expect((awaitrequest.bodyBuffer()).toString('utf8')).toEqual(expected);
341341
});
342342

343343
it('should return event source',async({ page, server})=>{

‎tests/page/page-request-intercept.spec.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ it('should intercept multipart/form-data request body', async ({ page, server, a
191191
page.click('input[type=submit]',{noWaitAfter:true})
192192
]);
193193
expect(request.method()).toBe('POST');
194-
expect(request.postData()).toContain(fs.readFileSync(filePath,'utf8'));
194+
expect(awaitrequest.body()).toContain(fs.readFileSync(filePath,'utf8'));
195195
});
196196

197197
it('should fulfill intercepted response using alias',async({ page, server, isElectron, electronMajorVersion, isAndroid})=>{
@@ -307,7 +307,7 @@ it('request.postData is not null when fetching FormData with a Blob', {
307307
constpostDataPromise=newPromise<string>(resolve=>resolvePostData=resolve);
308308
awaitpage.route(server.PREFIX+'/upload',async(route,request)=>{
309309
expect(request.method()).toBe('POST');
310-
resolvePostData(awaitrequest.postData());
310+
resolvePostData(awaitrequest.body());
311311
awaitroute.fulfill({
312312
status:200,
313313
body:'ok',

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp