From 4f64dfd9935e87c2752a4db04867b4a9928c2cd3 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Wed, 18 Oct 2017 00:26:48 -0700 Subject: [PATCH] feat(Request): allow aborting intercepted requests with custom reasons (#1080) This patch adds optional parameter to the `request.abort()` method that specifies abort reason. References #1020. --- docs/api.md | 19 +++++++++++++++++-- lib/NetworkManager.js | 25 +++++++++++++++++++++++-- test/test.js | 12 ++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/docs/api.md b/docs/api.md index 0af0b78c..cefdf228 100644 --- a/docs/api.md +++ b/docs/api.md @@ -162,7 +162,7 @@ * [elementHandle.type(text[, options])](#elementhandletypetext-options) * [elementHandle.uploadFile(...filePaths)](#elementhandleuploadfilefilepaths) - [class: Request](#class-request) - * [request.abort()](#requestabort) + * [request.abort([errorCode])](#requestaborterrorcode) * [request.continue([overrides])](#requestcontinueoverrides) * [request.failure()](#requestfailure) * [request.headers](#requestheaders) @@ -1831,7 +1831,22 @@ If request fails at some point, then instead of 'requestfinished' event (and pos If request gets a 'redirect' response, the request is successfully finished with the 'requestfinished' event, and a new request is issued to a redirected url. -#### request.abort() +#### request.abort([errorCode]) +- `errorCode` <[string]> Optional error code. Defaults to `failed`, could be + one of the following: + - `aborted` - An operation was aborted (due to user action) + - `accessdenied` - Permission to access a resource, other than the network, was denied + - `addressunreachable` - The IP address is unreachable. This usually means + that there is no route to the specified host or network. + - `connectionaborted` - A connection timed out as a result of not receiving an ACK for data sent. + - `connectionclosed` - A connection was closed (corresponding to a TCP FIN). + - `connectionfailed` - A connection attempt failed. + - `connectionrefused` - A connection attempt was refused. + - `connectionreset` - A connection was reset (corresponding to a TCP RST). + - `internetdisconnected` - The Internet connection has been lost. + - `namenotresolved` - The host name could not be resolved. + - `timedout` - An operation timed out. + - `failed` - A generic failure occurred. - returns: <[Promise]> Aborts request. To use this, request interception should be enabled with `page.setRequestInterceptionEnabled`. diff --git a/lib/NetworkManager.js b/lib/NetworkManager.js index 6a53dd48..f63bb82c 100644 --- a/lib/NetworkManager.js +++ b/lib/NetworkManager.js @@ -340,16 +340,21 @@ class Request { }); } - async abort() { + /** + * @param {string=} errorCode + */ + async abort(errorCode = 'failed') { // DataURL's are not interceptable. In this case, do nothing. if (this.url.startsWith('data:')) return; + const errorReason = errorReasons[errorCode]; + console.assert(errorReason, 'Unknown error code: ' + errorCode); console.assert(this._allowInterception, 'Request Interception is not enabled!'); console.assert(!this._interceptionHandled, 'Request is already handled!'); this._interceptionHandled = true; await this._client.send('Network.continueInterceptedRequest', { interceptionId: this._interceptionId, - errorReason: 'Failed' + errorReason }).catch(error => { // In certain cases, protocol will return error if the request was already canceled // or the page was closed. We should tolerate these errors. @@ -357,6 +362,22 @@ class Request { }); } } + +const errorReasons = { + 'aborted': 'Aborted', + 'accessdenied': 'AccessDenied', + 'addressunreachable': 'AddressUnreachable', + 'connectionaborted': 'ConnectionAborted', + 'connectionclosed': 'ConnectionClosed', + 'connectionfailed': 'ConnectionFailed', + 'connectionrefused': 'ConnectionRefused', + 'connectionreset': 'ConnectionReset', + 'internetdisconnected': 'InternetDisconnected', + 'namenotresolved': 'NameNotResolved', + 'timedout': 'TimedOut', + 'failed': 'Failed', +}; + helper.tracePublicAPI(Request); class Response { diff --git a/test/test.js b/test/test.js index 7fbca221..826d37a3 100644 --- a/test/test.js +++ b/test/test.js @@ -1176,8 +1176,20 @@ describe('Page', function() { page.on('requestfailed', event => ++failedRequests); const response = await page.goto(PREFIX + '/one-style.html'); expect(response.ok).toBe(true); + expect(response.request().failure()).toBe(null); expect(failedRequests).toBe(1); })); + it('should be abortable with custom error codes', SX(async function() { + await page.setRequestInterceptionEnabled(true); + page.on('request', request => { + request.abort('internetdisconnected'); + }); + let failedRequest = null; + page.on('requestfailed', request => failedRequest = request); + await page.goto(EMPTY_PAGE).catch(e => {}); + expect(failedRequest).toBeTruthy(); + expect(failedRequest.failure().errorText).toBe('net::ERR_INTERNET_DISCONNECTED'); + })); it('should amend HTTP headers', SX(async function() { await page.setRequestInterceptionEnabled(true); page.on('request', request => {