mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat(network): request interception and caching compatibility (#6996)
This patch enables developers to also keep the cache on when doing request interception.
This commit is contained in:
parent
bf60a300e7
commit
8695759a22
@ -166,7 +166,7 @@
|
|||||||
* [page.setGeolocation(options)](#pagesetgeolocationoptions)
|
* [page.setGeolocation(options)](#pagesetgeolocationoptions)
|
||||||
* [page.setJavaScriptEnabled(enabled)](#pagesetjavascriptenabledenabled)
|
* [page.setJavaScriptEnabled(enabled)](#pagesetjavascriptenabledenabled)
|
||||||
* [page.setOfflineMode(enabled)](#pagesetofflinemodeenabled)
|
* [page.setOfflineMode(enabled)](#pagesetofflinemodeenabled)
|
||||||
* [page.setRequestInterception(value)](#pagesetrequestinterceptionvalue)
|
* [page.setRequestInterception(value[, cacheSafe])](#pagesetrequestinterceptionvalue-cachesafe)
|
||||||
* [page.setUserAgent(userAgent)](#pagesetuseragentuseragent)
|
* [page.setUserAgent(userAgent)](#pagesetuseragentuseragent)
|
||||||
* [page.setViewport(viewport)](#pagesetviewportviewport)
|
* [page.setViewport(viewport)](#pagesetviewportviewport)
|
||||||
* [page.tap(selector)](#pagetapselector)
|
* [page.tap(selector)](#pagetapselector)
|
||||||
@ -2039,8 +2039,9 @@ await page.setGeolocation({latitude: 59.95, longitude: 30.31667});
|
|||||||
- `enabled` <[boolean]> When `true`, enables offline mode for the page.
|
- `enabled` <[boolean]> When `true`, enables offline mode for the page.
|
||||||
- returns: <[Promise]>
|
- returns: <[Promise]>
|
||||||
|
|
||||||
#### page.setRequestInterception(value)
|
#### page.setRequestInterception(value[, cacheSafe])
|
||||||
- `value` <[boolean]> Whether to enable request interception.
|
- `value` <[boolean]> Whether to enable request interception.
|
||||||
|
- `cacheSafe` <[boolean]> Whether to trust browser caching. If set to false, enabling request interception disables page caching. Defaults to false.
|
||||||
- returns: <[Promise]>
|
- returns: <[Promise]>
|
||||||
|
|
||||||
Activating request interception enables `request.abort`, `request.continue` and
|
Activating request interception enables `request.abort`, `request.continue` and
|
||||||
|
@ -54,6 +54,7 @@ export interface InternalNetworkConditions extends NetworkConditions {
|
|||||||
*/
|
*/
|
||||||
export const NetworkManagerEmittedEvents = {
|
export const NetworkManagerEmittedEvents = {
|
||||||
Request: Symbol('NetworkManager.Request'),
|
Request: Symbol('NetworkManager.Request'),
|
||||||
|
RequestServedFromCache: Symbol('NetworkManager.RequestServedFromCache'),
|
||||||
Response: Symbol('NetworkManager.Response'),
|
Response: Symbol('NetworkManager.Response'),
|
||||||
RequestFailed: Symbol('NetworkManager.RequestFailed'),
|
RequestFailed: Symbol('NetworkManager.RequestFailed'),
|
||||||
RequestFinished: Symbol('NetworkManager.RequestFinished'),
|
RequestFinished: Symbol('NetworkManager.RequestFinished'),
|
||||||
@ -75,6 +76,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
_credentials?: Credentials = null;
|
_credentials?: Credentials = null;
|
||||||
_attemptedAuthentications = new Set<string>();
|
_attemptedAuthentications = new Set<string>();
|
||||||
_userRequestInterceptionEnabled = false;
|
_userRequestInterceptionEnabled = false;
|
||||||
|
_userRequestInterceptionCacheSafe = false;
|
||||||
_protocolRequestInterceptionEnabled = false;
|
_protocolRequestInterceptionEnabled = false;
|
||||||
_userCacheDisabled = false;
|
_userCacheDisabled = false;
|
||||||
_requestIdToInterceptionId = new Map<string, string>();
|
_requestIdToInterceptionId = new Map<string, string>();
|
||||||
@ -189,8 +191,12 @@ export class NetworkManager extends EventEmitter {
|
|||||||
await this._updateProtocolCacheDisabled();
|
await this._updateProtocolCacheDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
async setRequestInterception(value: boolean): Promise<void> {
|
async setRequestInterception(
|
||||||
|
value: boolean,
|
||||||
|
cacheSafe = false
|
||||||
|
): Promise<void> {
|
||||||
this._userRequestInterceptionEnabled = value;
|
this._userRequestInterceptionEnabled = value;
|
||||||
|
this._userRequestInterceptionCacheSafe = cacheSafe;
|
||||||
await this._updateProtocolRequestInterception();
|
await this._updateProtocolRequestInterception();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +223,9 @@ export class NetworkManager extends EventEmitter {
|
|||||||
async _updateProtocolCacheDisabled(): Promise<void> {
|
async _updateProtocolCacheDisabled(): Promise<void> {
|
||||||
await this._client.send('Network.setCacheDisabled', {
|
await this._client.send('Network.setCacheDisabled', {
|
||||||
cacheDisabled:
|
cacheDisabled:
|
||||||
this._userCacheDisabled || this._userRequestInterceptionEnabled,
|
this._userCacheDisabled ||
|
||||||
|
(this._userRequestInterceptionEnabled &&
|
||||||
|
!this._userRequestInterceptionCacheSafe),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,6 +331,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
): void {
|
): void {
|
||||||
const request = this._requestIdToRequest.get(event.requestId);
|
const request = this._requestIdToRequest.get(event.requestId);
|
||||||
if (request) request._fromMemoryCache = true;
|
if (request) request._fromMemoryCache = true;
|
||||||
|
this.emit(NetworkManagerEmittedEvents.RequestServedFromCache, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleRequestRedirect(
|
_handleRequestRedirect(
|
||||||
|
@ -287,6 +287,14 @@ export const enum PageEmittedEvents {
|
|||||||
* and mutating requests.
|
* and mutating requests.
|
||||||
*/
|
*/
|
||||||
Request = 'request',
|
Request = 'request',
|
||||||
|
/**
|
||||||
|
* Emitted when a request ended up loading from cache. Contains a {@link HTTPRequest}.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* For certain requests, might contain undefined.
|
||||||
|
* @see https://crbug.com/750469
|
||||||
|
*/
|
||||||
|
RequestServedFromCache = 'requestservedfromcache',
|
||||||
/**
|
/**
|
||||||
* Emitted when a request fails, for example by timing out.
|
* Emitted when a request fails, for example by timing out.
|
||||||
*
|
*
|
||||||
@ -483,6 +491,10 @@ export class Page extends EventEmitter {
|
|||||||
networkManager.on(NetworkManagerEmittedEvents.Request, (event) =>
|
networkManager.on(NetworkManagerEmittedEvents.Request, (event) =>
|
||||||
this.emit(PageEmittedEvents.Request, event)
|
this.emit(PageEmittedEvents.Request, event)
|
||||||
);
|
);
|
||||||
|
networkManager.on(
|
||||||
|
NetworkManagerEmittedEvents.RequestServedFromCache,
|
||||||
|
(event) => this.emit(PageEmittedEvents.RequestServedFromCache, event)
|
||||||
|
);
|
||||||
networkManager.on(NetworkManagerEmittedEvents.Response, (event) =>
|
networkManager.on(NetworkManagerEmittedEvents.Response, (event) =>
|
||||||
this.emit(PageEmittedEvents.Response, event)
|
this.emit(PageEmittedEvents.Response, event)
|
||||||
);
|
);
|
||||||
@ -688,6 +700,8 @@ export class Page extends EventEmitter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param value - Whether to enable request interception.
|
* @param value - Whether to enable request interception.
|
||||||
|
* @param cacheSafe - Whether to trust browser caching. If set to false,
|
||||||
|
* enabling request interception disables page caching. Defaults to false.
|
||||||
*
|
*
|
||||||
* @remarks
|
* @remarks
|
||||||
* Activating request interception enables {@link HTTPRequest.abort},
|
* Activating request interception enables {@link HTTPRequest.abort},
|
||||||
@ -695,9 +709,7 @@ export class Page extends EventEmitter {
|
|||||||
* provides the capability to modify network requests that are made by a page.
|
* provides the capability to modify network requests that are made by a page.
|
||||||
*
|
*
|
||||||
* Once request interception is enabled, every request will stall unless it's
|
* Once request interception is enabled, every request will stall unless it's
|
||||||
* continued, responded or aborted.
|
* continued, responded or aborted; or completed using the browser cache.
|
||||||
*
|
|
||||||
* **NOTE** Enabling request interception disables page caching.
|
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* An example of a naïve request interceptor that aborts all image requests:
|
* An example of a naïve request interceptor that aborts all image requests:
|
||||||
@ -719,8 +731,13 @@ export class Page extends EventEmitter {
|
|||||||
* })();
|
* })();
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
async setRequestInterception(value: boolean): Promise<void> {
|
async setRequestInterception(
|
||||||
return this._frameManager.networkManager().setRequestInterception(value);
|
value: boolean,
|
||||||
|
cacheSafe = false
|
||||||
|
): Promise<void> {
|
||||||
|
return this._frameManager
|
||||||
|
.networkManager()
|
||||||
|
.setRequestInterception(value, cacheSafe);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -355,6 +355,20 @@ describe('network', function () {
|
|||||||
expect(requests[0].frame() === page.mainFrame()).toBe(true);
|
expect(requests[0].frame() === page.mainFrame()).toBe(true);
|
||||||
expect(requests[0].frame().url()).toBe(server.EMPTY_PAGE);
|
expect(requests[0].frame().url()).toBe(server.EMPTY_PAGE);
|
||||||
});
|
});
|
||||||
|
it('Page.Events.RequestServedFromCache', async () => {
|
||||||
|
const { page, server } = getTestState();
|
||||||
|
|
||||||
|
const cached = [];
|
||||||
|
page.on('requestservedfromcache', (r) =>
|
||||||
|
cached.push(r.url().split('/').pop())
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.goto(server.PREFIX + '/cached/one-style.html');
|
||||||
|
expect(cached).toEqual([]);
|
||||||
|
|
||||||
|
await page.reload();
|
||||||
|
expect(cached).toEqual(['one-style.css']);
|
||||||
|
});
|
||||||
it('Page.Events.Response', async () => {
|
it('Page.Events.Response', async () => {
|
||||||
const { page, server } = getTestState();
|
const { page, server } = getTestState();
|
||||||
|
|
||||||
|
@ -495,6 +495,36 @@ describe('request interception', function () {
|
|||||||
expect(urls.has('one-style.html')).toBe(true);
|
expect(urls.has('one-style.html')).toBe(true);
|
||||||
expect(urls.has('one-style.css')).toBe(true);
|
expect(urls.has('one-style.css')).toBe(true);
|
||||||
});
|
});
|
||||||
|
it('should not cache if not cache-safe', async () => {
|
||||||
|
const { page, server } = getTestState();
|
||||||
|
|
||||||
|
// Load and re-load to make sure it's cached.
|
||||||
|
await page.goto(server.PREFIX + '/cached/one-style.html');
|
||||||
|
|
||||||
|
await page.setRequestInterception(true, false);
|
||||||
|
page.on('request', (request) => request.continue());
|
||||||
|
|
||||||
|
const cached = [];
|
||||||
|
page.on('requestservedfromcache', (r) => cached.push(r));
|
||||||
|
|
||||||
|
await page.reload();
|
||||||
|
expect(cached.length).toBe(0);
|
||||||
|
});
|
||||||
|
it('should cache if cache-safe', async () => {
|
||||||
|
const { page, server } = getTestState();
|
||||||
|
|
||||||
|
// Load and re-load to make sure it's cached.
|
||||||
|
await page.goto(server.PREFIX + '/cached/one-style.html');
|
||||||
|
|
||||||
|
await page.setRequestInterception(true, true);
|
||||||
|
page.on('request', (request) => request.continue());
|
||||||
|
|
||||||
|
const cached = [];
|
||||||
|
page.on('requestservedfromcache', (r) => cached.push(r));
|
||||||
|
|
||||||
|
await page.reload();
|
||||||
|
expect(cached.length).toBe(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describeFailsFirefox('Request.continue', function () {
|
describeFailsFirefox('Request.continue', function () {
|
||||||
|
Loading…
Reference in New Issue
Block a user