mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat: support fetching request POST data (#11598)
This commit is contained in:
parent
c660d4001d
commit
80143def96
19
docs/api/puppeteer.httprequest.fetchpostdata.md
Normal file
19
docs/api/puppeteer.httprequest.fetchpostdata.md
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_label: HTTPRequest.fetchPostData
|
||||
---
|
||||
|
||||
# HTTPRequest.fetchPostData() method
|
||||
|
||||
Fetches the POST data for the request from the browser.
|
||||
|
||||
#### Signature:
|
||||
|
||||
```typescript
|
||||
class HTTPRequest {
|
||||
abstract fetchPostData(): Promise<string | undefined>;
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
|
||||
Promise<string \| undefined>
|
19
docs/api/puppeteer.httprequest.haspostdata.md
Normal file
19
docs/api/puppeteer.httprequest.haspostdata.md
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_label: HTTPRequest.hasPostData
|
||||
---
|
||||
|
||||
# HTTPRequest.hasPostData() method
|
||||
|
||||
True when the request has POST data. Note that [HTTPRequest.postData()](./puppeteer.httprequest.postdata.md) might still be undefined when this flag is true when the data is too long or not readily available in the decoded form. In that case, use [HTTPRequest.fetchPostData()](./puppeteer.httprequest.fetchpostdata.md).
|
||||
|
||||
#### Signature:
|
||||
|
||||
```typescript
|
||||
class HTTPRequest {
|
||||
abstract hasPostData(): boolean;
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
|
||||
boolean
|
@ -48,8 +48,10 @@ The constructor for this class is marked as internal. Third-party code should no
|
||||
| [continueRequestOverrides()](./puppeteer.httprequest.continuerequestoverrides.md) | | The <code>ContinueRequestOverrides</code> that will be used if the interception is allowed to continue (ie, <code>abort()</code> and <code>respond()</code> aren't called). |
|
||||
| [enqueueInterceptAction(pendingHandler)](./puppeteer.httprequest.enqueueinterceptaction.md) | | Adds an async request handler to the processing queue. Deferred handlers are not guaranteed to execute in any particular order, but they are guaranteed to resolve before the request interception is finalized. |
|
||||
| [failure()](./puppeteer.httprequest.failure.md) | | Access information about the request's failure. |
|
||||
| [fetchPostData()](./puppeteer.httprequest.fetchpostdata.md) | | Fetches the POST data for the request from the browser. |
|
||||
| [finalizeInterceptions()](./puppeteer.httprequest.finalizeinterceptions.md) | | Awaits pending interception handlers and then decides how to fulfill the request interception. |
|
||||
| [frame()](./puppeteer.httprequest.frame.md) | | The frame that initiated the request, or null if navigating to error pages. |
|
||||
| [hasPostData()](./puppeteer.httprequest.haspostdata.md) | | True when the request has POST data. Note that [HTTPRequest.postData()](./puppeteer.httprequest.postdata.md) might still be undefined when this flag is true when the data is too long or not readily available in the decoded form. In that case, use [HTTPRequest.fetchPostData()](./puppeteer.httprequest.fetchpostdata.md). |
|
||||
| [headers()](./puppeteer.httprequest.headers.md) | | An object with HTTP headers associated with the request. All header names are lower-case. |
|
||||
| [initiator()](./puppeteer.httprequest.initiator.md) | | The initiator of the request. |
|
||||
| [interceptResolutionState()](./puppeteer.httprequest.interceptresolutionstate.md) | | <p>An InterceptResolutionState object describing the current resolution action and priority.</p><p>InterceptResolutionState contains: action: InterceptResolutionAction priority?: number</p><p>InterceptResolutionAction is one of: <code>abort</code>, <code>respond</code>, <code>continue</code>, <code>disabled</code>, <code>none</code>, or <code>already-handled</code>.</p> |
|
||||
|
@ -212,6 +212,19 @@ export abstract class HTTPRequest {
|
||||
*/
|
||||
abstract postData(): string | undefined;
|
||||
|
||||
/**
|
||||
* True when the request has POST data. Note that {@link HTTPRequest.postData}
|
||||
* might still be undefined when this flag is true when the data is too long
|
||||
* or not readily available in the decoded form. In that case, use
|
||||
* {@link HTTPRequest.fetchPostData}.
|
||||
*/
|
||||
abstract hasPostData(): boolean;
|
||||
|
||||
/**
|
||||
* Fetches the POST data for the request from the browser.
|
||||
*/
|
||||
abstract fetchPostData(): Promise<string | undefined>;
|
||||
|
||||
/**
|
||||
* An object with HTTP headers associated with the request. All
|
||||
* header names are lower-case.
|
||||
|
@ -89,6 +89,14 @@ export class BidiHTTPRequest extends HTTPRequest {
|
||||
return this.#postData;
|
||||
}
|
||||
|
||||
override hasPostData(): boolean {
|
||||
return this.#postData !== undefined;
|
||||
}
|
||||
|
||||
override async fetchPostData(): Promise<string | undefined> {
|
||||
return this.#postData;
|
||||
}
|
||||
|
||||
override headers(): Record<string, string> {
|
||||
return this.#headers;
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ export class CdpHTTPRequest extends HTTPRequest {
|
||||
#resourceType: ResourceType;
|
||||
|
||||
#method: string;
|
||||
#hasPostData = false;
|
||||
#postData?: string;
|
||||
#headers: Record<string, string> = {};
|
||||
#frame: Frame | null;
|
||||
@ -109,6 +110,7 @@ export class CdpHTTPRequest extends HTTPRequest {
|
||||
this.#resourceType = (data.type || 'other').toLowerCase() as ResourceType;
|
||||
this.#method = data.request.method;
|
||||
this.#postData = data.request.postData;
|
||||
this.#hasPostData = data.request.hasPostData ?? false;
|
||||
this.#frame = frame;
|
||||
this._redirectChain = redirectChain;
|
||||
this.#continueRequestOverrides = {};
|
||||
@ -189,6 +191,22 @@ export class CdpHTTPRequest extends HTTPRequest {
|
||||
return this.#postData;
|
||||
}
|
||||
|
||||
override hasPostData(): boolean {
|
||||
return this.#hasPostData;
|
||||
}
|
||||
|
||||
override async fetchPostData(): Promise<string | undefined> {
|
||||
try {
|
||||
const result = await this.#client.send('Network.getRequestPostData', {
|
||||
requestId: this._requestId,
|
||||
});
|
||||
return result.postData;
|
||||
} catch (err) {
|
||||
debugError(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
override headers(): Record<string, string> {
|
||||
return this.#headers;
|
||||
}
|
||||
|
@ -851,6 +851,13 @@
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[network.spec] network Request.postData should work with blobs",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"],
|
||||
"comment": "Not implemented for BiDi yet."
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[network.spec] network Response.fromServiceWorker Response.fromServiceWorker",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -2711,6 +2718,13 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[network.spec] network Request.postData should work with blobs",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["SKIP"],
|
||||
"comment": "Blobs have no POST data in Firefox's CDP implementation."
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[network.spec] network Response.buffer should throw if the response does not have a body",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
|
@ -267,12 +267,41 @@ describe('network', function () {
|
||||
expect(request).toBeTruthy();
|
||||
expect(request.postData()).toBe('{"foo":"bar"}');
|
||||
});
|
||||
|
||||
it('should be |undefined| when there is no post data', async () => {
|
||||
const {page, server} = await getTestState();
|
||||
|
||||
const response = (await page.goto(server.EMPTY_PAGE))!;
|
||||
expect(response.request().postData()).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should work with blobs', async () => {
|
||||
const {page, server} = await getTestState();
|
||||
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
server.setRoute('/post', (_req, res) => {
|
||||
return res.end();
|
||||
});
|
||||
|
||||
const [request] = await Promise.all([
|
||||
waitEvent<HTTPRequest>(page, 'request', r => {
|
||||
return !isFavicon(r);
|
||||
}),
|
||||
page.evaluate(() => {
|
||||
return fetch('./post', {
|
||||
method: 'POST',
|
||||
body: new Blob([JSON.stringify({foo: 'bar'})], {
|
||||
type: 'application/json',
|
||||
}),
|
||||
});
|
||||
}),
|
||||
]);
|
||||
|
||||
expect(request).toBeTruthy();
|
||||
expect(request.postData()).toBe(undefined);
|
||||
expect(request.hasPostData()).toBe(true);
|
||||
expect(await request.fetchPostData()).toBe('{"foo":"bar"}');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Response.text', function () {
|
||||
|
Loading…
Reference in New Issue
Block a user