feat(network): introduce Request.isNavigationRequest() method (#2633)

This patch introduces `Request.isNavigationRequest()` method.

Fixes #2627, #1132.
This commit is contained in:
Andrey Lushnikov 2018-05-31 17:38:30 -07:00 committed by GitHub
parent f6356683cd
commit 724fa512cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 7 deletions

View File

@ -231,6 +231,7 @@
* [request.failure()](#requestfailure) * [request.failure()](#requestfailure)
* [request.frame()](#requestframe) * [request.frame()](#requestframe)
* [request.headers()](#requestheaders) * [request.headers()](#requestheaders)
* [request.isNavigationRequest()](#requestisnavigationrequest)
* [request.method()](#requestmethod) * [request.method()](#requestmethod)
* [request.postData()](#requestpostdata) * [request.postData()](#requestpostdata)
* [request.redirectChain()](#requestredirectchain) * [request.redirectChain()](#requestredirectchain)
@ -2649,6 +2650,11 @@ page.on('requestfailed', request => {
#### request.headers() #### request.headers()
- returns: <[Object]> An object with HTTP headers associated with the request. All header names are lower-case. - returns: <[Object]> An object with HTTP headers associated with the request. All header names are lower-case.
#### request.isNavigationRequest()
- returns: <[boolean]>
Whether this request is driving frame's navigation.
#### request.method() #### request.method()
- returns: <[string]> Request's method (GET, POST, etc.) - returns: <[string]> Request's method (GET, POST, etc.)

View File

@ -155,7 +155,7 @@ class NetworkManager extends EventEmitter {
const request = this._interceptionIdToRequest.get(event.interceptionId); const request = this._interceptionIdToRequest.get(event.interceptionId);
if (request) { if (request) {
this._handleRequestRedirect(request, event.responseStatusCode, event.responseHeaders, false /* fromDiskCache */, false /* fromServiceWorker */, null /* securityDetails */); this._handleRequestRedirect(request, event.responseStatusCode, event.responseHeaders, false /* fromDiskCache */, false /* fromServiceWorker */, null /* securityDetails */);
this._handleRequestStart(request._requestId, event.interceptionId, event.redirectUrl, event.resourceType, event.request, event.frameId, request._redirectChain); this._handleRequestStart(request._requestId, event.interceptionId, event.redirectUrl, event.isNavigationRequest, event.resourceType, event.request, event.frameId, request._redirectChain);
} }
return; return;
} }
@ -163,10 +163,10 @@ class NetworkManager extends EventEmitter {
const requestId = this._requestHashToRequestIds.firstValue(requestHash); const requestId = this._requestHashToRequestIds.firstValue(requestHash);
if (requestId) { if (requestId) {
this._requestHashToRequestIds.delete(requestHash, requestId); this._requestHashToRequestIds.delete(requestHash, requestId);
this._handleRequestStart(requestId, event.interceptionId, event.request.url, event.resourceType, event.request, event.frameId, []); this._handleRequestStart(requestId, event.interceptionId, event.request.url, event.isNavigationRequest, event.resourceType, event.request, event.frameId, []);
} else { } else {
this._requestHashToInterceptionIds.set(requestHash, event.interceptionId); this._requestHashToInterceptionIds.set(requestHash, event.interceptionId);
this._handleRequestStart(null, event.interceptionId, event.request.url, event.resourceType, event.request, event.frameId, []); this._handleRequestStart(null, event.interceptionId, event.request.url, event.isNavigationRequest, event.resourceType, event.request, event.frameId, []);
} }
} }
@ -203,16 +203,17 @@ class NetworkManager extends EventEmitter {
* @param {?string} requestId * @param {?string} requestId
* @param {?string} interceptionId * @param {?string} interceptionId
* @param {string} url * @param {string} url
* @param {boolean} isNavigationRequest
* @param {string} resourceType * @param {string} resourceType
* @param {!Protocol.Network.Request} requestPayload * @param {!Protocol.Network.Request} requestPayload
* @param {?string} frameId * @param {?string} frameId
* @param {!Array<!Request>} redirectChain * @param {!Array<!Request>} redirectChain
*/ */
_handleRequestStart(requestId, interceptionId, url, resourceType, requestPayload, frameId, redirectChain) { _handleRequestStart(requestId, interceptionId, url, isNavigationRequest, resourceType, requestPayload, frameId, redirectChain) {
let frame = null; let frame = null;
if (frameId) if (frameId)
frame = this._frameManager.frame(frameId); frame = this._frameManager.frame(frameId);
const request = new Request(this._client, requestId, interceptionId, this._userRequestInterceptionEnabled, url, resourceType, requestPayload, frame, redirectChain); const request = new Request(this._client, requestId, interceptionId, isNavigationRequest, this._userRequestInterceptionEnabled, url, resourceType, requestPayload, frame, redirectChain);
if (requestId) if (requestId)
this._requestIdToRequest.set(requestId, request); this._requestIdToRequest.set(requestId, request);
if (interceptionId) if (interceptionId)
@ -249,7 +250,8 @@ class NetworkManager extends EventEmitter {
redirectChain = request._redirectChain; redirectChain = request._redirectChain;
} }
} }
this._handleRequestStart(event.requestId, null, event.request.url, event.type, event.request, event.frameId, redirectChain); const isNavigationRequest = event.requestId === event.loaderId && event.type === 'Document';
this._handleRequestStart(event.requestId, null, event.request.url, isNavigationRequest, event.type, event.request, event.frameId, redirectChain);
} }
/** /**
@ -307,6 +309,7 @@ class Request {
* @param {!Puppeteer.CDPSession} client * @param {!Puppeteer.CDPSession} client
* @param {?string} requestId * @param {?string} requestId
* @param {string} interceptionId * @param {string} interceptionId
* @param {boolean} isNavigationRequest
* @param {boolean} allowInterception * @param {boolean} allowInterception
* @param {string} url * @param {string} url
* @param {string} resourceType * @param {string} resourceType
@ -314,9 +317,10 @@ class Request {
* @param {?Puppeteer.Frame} frame * @param {?Puppeteer.Frame} frame
* @param {!Array<!Request>} redirectChain * @param {!Array<!Request>} redirectChain
*/ */
constructor(client, requestId, interceptionId, allowInterception, url, resourceType, payload, frame, redirectChain) { constructor(client, requestId, interceptionId, isNavigationRequest, allowInterception, url, resourceType, payload, frame, redirectChain) {
this._client = client; this._client = client;
this._requestId = requestId; this._requestId = requestId;
this._isNavigationRequest = isNavigationRequest;
this._interceptionId = interceptionId; this._interceptionId = interceptionId;
this._allowInterception = allowInterception; this._allowInterception = allowInterception;
this._interceptionHandled = false; this._interceptionHandled = false;
@ -385,6 +389,13 @@ class Request {
return this._frame; return this._frame;
} }
/**
* @return {boolean}
*/
isNavigationRequest() {
return this._isNavigationRequest;
}
/** /**
* @return {!Array<!Request>} * @return {!Array<!Request>}
*/ */

View File

@ -199,6 +199,41 @@ module.exports.addTests = function({testRunner, expect}) {
}); });
}); });
describe('Request.isNavigationRequest', () => {
it('should work', async({page, server}) => {
const requests = new Map();
page.on('request', request => requests.set(request.url().split('/').pop(), request));
server.setRedirect('/rrredirect', '/frames/one-frame.html');
await page.goto(server.PREFIX + '/rrredirect');
expect(requests.get('rrredirect').isNavigationRequest()).toBe(true);
expect(requests.get('one-frame.html').isNavigationRequest()).toBe(true);
expect(requests.get('frame.html').isNavigationRequest()).toBe(true);
expect(requests.get('script.js').isNavigationRequest()).toBe(false);
expect(requests.get('style.css').isNavigationRequest()).toBe(false);
});
it('should work with request interception', async({page, server}) => {
const requests = new Map();
page.on('request', request => {
requests.set(request.url().split('/').pop(), request);
request.continue();
});
await page.setRequestInterception(true);
server.setRedirect('/rrredirect', '/frames/one-frame.html');
await page.goto(server.PREFIX + '/rrredirect');
expect(requests.get('rrredirect').isNavigationRequest()).toBe(true);
expect(requests.get('one-frame.html').isNavigationRequest()).toBe(true);
expect(requests.get('frame.html').isNavigationRequest()).toBe(true);
expect(requests.get('script.js').isNavigationRequest()).toBe(false);
expect(requests.get('style.css').isNavigationRequest()).toBe(false);
});
it('should work when navigating to image', async({page, server}) => {
const requests = [];
page.on('request', request => requests.push(request));
await page.goto(server.PREFIX + '/pptr.png');
expect(requests[0].isNavigationRequest()).toBe(true);
});
});
describe('Page.setRequestInterception', function() { describe('Page.setRequestInterception', function() {
it('should intercept', async({page, server}) => { it('should intercept', async({page, server}) => {
await page.setRequestInterception(true); await page.setRequestInterception(true);
@ -207,6 +242,7 @@ module.exports.addTests = function({testRunner, expect}) {
expect(request.headers()['user-agent']).toBeTruthy(); expect(request.headers()['user-agent']).toBeTruthy();
expect(request.method()).toBe('GET'); expect(request.method()).toBe('GET');
expect(request.postData()).toBe(undefined); expect(request.postData()).toBe(undefined);
expect(request.isNavigationRequest()).toBe(true);
expect(request.resourceType()).toBe('document'); expect(request.resourceType()).toBe('document');
expect(request.frame() === page.mainFrame()).toBe(true); expect(request.frame() === page.mainFrame()).toBe(true);
expect(request.frame().url()).toBe('about:blank'); expect(request.frame().url()).toBe('about:blank');
@ -327,6 +363,7 @@ module.exports.addTests = function({testRunner, expect}) {
expect(redirectChain[2].url()).toContain('/non-existing-page-3.html'); expect(redirectChain[2].url()).toContain('/non-existing-page-3.html');
for (let i = 0; i < redirectChain.length; ++i) { for (let i = 0; i < redirectChain.length; ++i) {
const request = redirectChain[i]; const request = redirectChain[i];
expect(request.isNavigationRequest()).toBe(true);
expect(request.redirectChain().indexOf(request)).toBe(i); expect(request.redirectChain().indexOf(request)).toBe(i);
} }
}); });