chore: route.fetch(postData) (#19436)

This commit is contained in:
Pavel Feldman 2022-12-13 14:01:39 -08:00 committed by GitHub
parent 87141f6856
commit d1559a0fcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 65 deletions

View File

@ -115,7 +115,7 @@ If set changes the request method (e.g. GET or POST).
### option: Route.continue.postData ### option: Route.continue.postData
* since: v1.8 * since: v1.8
* langs: js, python, java * langs: js, python, java
- `postData` <[string]|[Buffer]> - `postData` <[string]|[Buffer]|[Serializable]>
If set changes the post data of request. If set changes the post data of request.
@ -391,7 +391,7 @@ If set changes the request method (e.g. GET or POST).
### option: Route.fallback.postData ### option: Route.fallback.postData
* since: v1.23 * since: v1.23
* langs: js, python, java * langs: js, python, java
- `postData` <[string]|[Buffer]> - `postData` <[string]|[Buffer]|[Serializable]>
If set changes the post data of request. If set changes the post data of request.
@ -480,10 +480,10 @@ If set changes the request URL. New URL must have same protocol as original one.
If set changes the request method (e.g. GET or POST). If set changes the request method (e.g. GET or POST).
### option: Route.fetch.postData = %%-js-python-csharp-fetch-option-data-%% ### option: Route.fetch.postData = %%-js-python-csharp-fetch-option-post-data-%%
* since: v1.29 * since: v1.29
### option: Route.fetch.data ### option: Route.fetch.postData
* since: v1.29 * since: v1.29
* langs: csharp * langs: csharp
- `postData` <[Buffer]> - `postData` <[Buffer]>
@ -616,33 +616,6 @@ Optional response body as raw bytes.
JSON response. This method will set the content type to `application/json` if not set. JSON response. This method will set the content type to `application/json` if not set.
**Usage**
```js
await page.route('https://dog.ceo/api/breeds/list/all', async route => {
const json = {
message: { 'test_breed': [] }
};
await route.fulfill({ json });
});
```
```python async
async def handle(route):
json = { "test_breed": [] }
await route.fulfill(json=json)
await page.route("https://dog.ceo/api/breeds/list/all", handle)
```
```python sync
async def handle(route):
json = { "test_breed": [] }
route.fulfill(json=json)
page.route("https://dog.ceo/api/breeds/list/all", handle)
```
### option: Route.fulfill.json ### option: Route.fulfill.json
* since: v1.29 * since: v1.29
* langs: csharp * langs: csharp

View File

@ -389,6 +389,14 @@ Allows to set post data of the request. If the data parameter is an object, it w
and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` header will be and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` header will be
set to `application/octet-stream` if not explicitly set. set to `application/octet-stream` if not explicitly set.
## js-python-csharp-fetch-option-post-data
* langs: js, python, csharp
- `postData` <[string]|[Buffer]|[Serializable]>
Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` header will be
set to `application/octet-stream` if not explicitly set.
## js-python-csharp-fetch-option-ignorehttpserrors ## js-python-csharp-fetch-option-ignorehttpserrors
* langs: js, python, csharp * langs: js, python, csharp
- `ignoreHTTPSErrors` <[boolean]> - `ignoreHTTPSErrors` <[boolean]>

View File

@ -32,6 +32,7 @@ import type { HeadersArray, URLMatch } from '../common/types';
import { urlMatches } from '../common/netUtils'; import { urlMatches } from '../common/netUtils';
import { MultiMap } from '../utils/multimap'; import { MultiMap } from '../utils/multimap';
import { APIResponse } from './fetch'; import { APIResponse } from './fetch';
import type { Serializable } from '../../types/structs';
export type NetworkCookie = { export type NetworkCookie = {
name: string, name: string,
@ -56,11 +57,18 @@ export type SetNetworkCookieParam = {
sameSite?: 'Strict' | 'Lax' | 'None' sameSite?: 'Strict' | 'Lax' | 'None'
}; };
type SerializedFallbackOverrides = {
url?: string;
method?: string;
headers?: Headers;
postDataBuffer?: Buffer;
};
type FallbackOverrides = { type FallbackOverrides = {
url?: string; url?: string;
method?: string; method?: string;
headers?: Headers; headers?: Headers;
postData?: string | Buffer; postData?: string | Buffer | Serializable;
}; };
export class Request extends ChannelOwner<channels.RequestChannel> implements api.Request { export class Request extends ChannelOwner<channels.RequestChannel> implements api.Request {
@ -71,7 +79,7 @@ export class Request extends ChannelOwner<channels.RequestChannel> implements ap
private _actualHeadersPromise: Promise<RawHeaders> | undefined; private _actualHeadersPromise: Promise<RawHeaders> | undefined;
private _postData: Buffer | null; private _postData: Buffer | null;
_timing: ResourceTiming; _timing: ResourceTiming;
private _fallbackOverrides: FallbackOverrides = {}; private _fallbackOverrides: SerializedFallbackOverrides = {};
static from(request: channels.RequestChannel): Request { static from(request: channels.RequestChannel): Request {
return (request as any)._object; return (request as any)._object;
@ -114,17 +122,14 @@ export class Request extends ChannelOwner<channels.RequestChannel> implements ap
} }
postData(): string | null { postData(): string | null {
if (this._fallbackOverrides.postData) if (this._fallbackOverrides.postDataBuffer)
return this._fallbackOverrides.postData.toString('utf-8'); return this._fallbackOverrides.postDataBuffer.toString('utf-8');
return this._postData ? this._postData.toString('utf8') : null; return this._postData ? this._postData.toString('utf8') : null;
} }
postDataBuffer(): Buffer | null { postDataBuffer(): Buffer | null {
if (this._fallbackOverrides.postData) { if (this._fallbackOverrides.postDataBuffer)
if (isString(this._fallbackOverrides.postData)) return this._fallbackOverrides.postDataBuffer;
return Buffer.from(this._fallbackOverrides.postData, 'utf-8');
return this._fallbackOverrides.postData;
}
return this._postData; return this._postData;
} }
@ -251,7 +256,21 @@ export class Request extends ChannelOwner<channels.RequestChannel> implements ap
} }
_applyFallbackOverrides(overrides: FallbackOverrides) { _applyFallbackOverrides(overrides: FallbackOverrides) {
this._fallbackOverrides = { ...this._fallbackOverrides, ...overrides }; const basicOptions = { ...overrides, postData: undefined };
const postData = overrides.postData;
let postDataBuffer = this._fallbackOverrides.postDataBuffer;
if (isString(postData))
postDataBuffer = Buffer.from(postData, 'utf-8');
else if (postData instanceof Buffer)
postDataBuffer = postData;
else if (postData)
postDataBuffer = Buffer.from(JSON.stringify(postData), 'utf-8');
this._fallbackOverrides = {
...this._fallbackOverrides,
...basicOptions,
postDataBuffer,
};
} }
_fallbackOverridesForContinue() { _fallbackOverridesForContinue() {
@ -400,12 +419,11 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
async _innerContinue(internal = false) { async _innerContinue(internal = false) {
const options = this.request()._fallbackOverridesForContinue(); const options = this.request()._fallbackOverridesForContinue();
return await this._wrapApiCall(async () => { return await this._wrapApiCall(async () => {
const postDataBuffer = isString(options.postData) ? Buffer.from(options.postData, 'utf8') : options.postData;
await this._raceWithTargetClose(this._channel.continue({ await this._raceWithTargetClose(this._channel.continue({
url: options.url, url: options.url,
method: options.method, method: options.method,
headers: options.headers ? headersObjectToArray(options.headers) : undefined, headers: options.headers ? headersObjectToArray(options.headers) : undefined,
postData: postDataBuffer, postData: options.postDataBuffer,
})); }));
}, !!internal); }, !!internal);
} }

View File

@ -17067,7 +17067,7 @@ export interface Route {
/** /**
* If set changes the post data of request. * If set changes the post data of request.
*/ */
postData?: string|Buffer; postData?: string|Buffer|Serializable;
/** /**
* If set changes the request URL. New URL must have same protocol as original one. * If set changes the request URL. New URL must have same protocol as original one.
@ -17154,7 +17154,7 @@ export interface Route {
/** /**
* If set changes the post data of request. * If set changes the post data of request.
*/ */
postData?: string|Buffer; postData?: string|Buffer|Serializable;
/** /**
* If set changes the request URL. New URL must have same protocol as original one. Changing the URL won't affect the * If set changes the request URL. New URL must have same protocol as original one. Changing the URL won't affect the
@ -17181,13 +17181,6 @@ export interface Route {
* @param options * @param options
*/ */
fetch(options?: { fetch(options?: {
/**
* Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
* and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
* header will be set to `application/octet-stream` if not explicitly set.
*/
data?: string|Buffer|Serializable;
/** /**
* If set changes the request HTTP headers. Header values will be converted to a string. * If set changes the request HTTP headers. Header values will be converted to a string.
*/ */
@ -17198,6 +17191,13 @@ export interface Route {
*/ */
method?: string; method?: string;
/**
* Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
* and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
* header will be set to `application/octet-stream` if not explicitly set.
*/
postData?: string|Buffer|Serializable;
/** /**
* If set changes the request URL. New URL must have same protocol as original one. * If set changes the request URL. New URL must have same protocol as original one.
*/ */
@ -17247,18 +17247,6 @@ export interface Route {
/** /**
* JSON response. This method will set the content type to `application/json` if not set. * JSON response. This method will set the content type to `application/json` if not set.
*
* **Usage**
*
* ```js
* await page.route('https://dog.ceo/api/breeds/list/all', async route => {
* const json = {
* message: { 'test_breed': [] }
* };
* await route.fulfill({ json });
* });
* ```
*
*/ */
json?: Serializable; json?: Serializable;

View File

@ -259,4 +259,22 @@ it.describe('post data', () => {
expect(postDataBuffer[i]).toBe(arr[i]); expect(postDataBuffer[i]).toBe(arr[i]);
} }
}); });
it('should amend json post data', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
let postData: string;
await page.route('**/*', route => {
postData = route.request().postDataJSON();
route.continue();
});
await page.route('**/*', route => {
route.fallback({ postData: { foo: 'bar' } });
});
const [serverRequest] = await Promise.all([
server.waitForRequest('/sleep.zzz'),
page.evaluate(() => fetch('/sleep.zzz', { method: 'POST', body: 'birdy' }))
]);
expect(postData).toEqual({ foo: 'bar' });
expect((await serverRequest.postBody).toString('utf8')).toBe('{"foo":"bar"}');
});
}); });

View File

@ -224,7 +224,7 @@ it('should intercept with post data override', async ({ page, server, isElectron
const requestPromise = server.waitForRequest('/empty.html'); const requestPromise = server.waitForRequest('/empty.html');
await page.route('**/*.html', async route => { await page.route('**/*.html', async route => {
const response = await route.fetch({ const response = await route.fetch({
data: { 'foo': 'bar' }, postData: { 'foo': 'bar' },
}); });
await route.fulfill({ response }); await route.fulfill({ response });
}); });