refactor: migrate onto Fetch domain (#4265)

Request interception in Network domain is deprecated.
Move on onto Fetch domain - the new bright future.
This commit is contained in:
Andrey Lushnikov 2019-04-11 15:02:06 -04:00 committed by GitHub
parent a79b775430
commit 2265974ce5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -45,8 +45,9 @@ class NetworkManager extends EventEmitter {
/** @type {!Map<string, string>} */
this._requestIdToInterceptionId = new Map();
this._client.on('Fetch.requestPaused', this._onRequestPaused.bind(this));
this._client.on('Fetch.authRequired', this._onAuthRequired.bind(this));
this._client.on('Network.requestWillBeSent', this._onRequestWillBeSent.bind(this));
this._client.on('Network.requestIntercepted', this._onRequestIntercepted.bind(this));
this._client.on('Network.requestServedFromCache', this._onRequestServedFromCache.bind(this));
this._client.on('Network.responseReceived', this._onResponseReceived.bind(this));
this._client.on('Network.loadingFinished', this._onLoadingFinished.bind(this));
@ -138,11 +139,20 @@ class NetworkManager extends EventEmitter {
if (enabled === this._protocolRequestInterceptionEnabled)
return;
this._protocolRequestInterceptionEnabled = enabled;
const patterns = enabled ? [{urlPattern: '*'}] : [];
await Promise.all([
this._updateProtocolCacheDisabled(),
this._client.send('Network.setRequestInterception', {patterns})
]);
if (enabled) {
await Promise.all([
this._updateProtocolCacheDisabled(),
this._client.send('Fetch.enable', {
handleAuthRequests: true,
patterns: [{urlPattern: '*'}],
}),
]);
} else {
await Promise.all([
this._updateProtocolCacheDisabled(),
this._client.send('Fetch.disable')
]);
}
}
async _updateProtocolCacheDisabled() {
@ -171,38 +181,42 @@ class NetworkManager extends EventEmitter {
}
/**
* @param {!Protocol.Network.requestInterceptedPayload} event
* @param {!Protocol.Fetch.authRequiredPayload} event
*/
_onRequestIntercepted(event) {
if (event.authChallenge) {
/** @type {"Default"|"CancelAuth"|"ProvideCredentials"} */
let response = 'Default';
if (this._attemptedAuthentications.has(event.interceptionId)) {
response = 'CancelAuth';
} else if (this._credentials) {
response = 'ProvideCredentials';
this._attemptedAuthentications.add(event.interceptionId);
}
const {username, password} = this._credentials || {username: undefined, password: undefined};
this._client.send('Network.continueInterceptedRequest', {
interceptionId: event.interceptionId,
authChallengeResponse: { response, username, password }
}).catch(debugError);
return;
_onAuthRequired(event) {
/** @type {"Default"|"CancelAuth"|"ProvideCredentials"} */
let response = 'Default';
if (this._attemptedAuthentications.has(event.requestId)) {
response = 'CancelAuth';
} else if (this._credentials) {
response = 'ProvideCredentials';
this._attemptedAuthentications.add(event.requestId);
}
const {username, password} = this._credentials || {username: undefined, password: undefined};
this._client.send('Fetch.continueWithAuth', {
requestId: event.requestId,
authChallengeResponse: { response, username, password },
}).catch(debugError);
}
/**
* @param {!Protocol.Fetch.requestPausedPayload} event
*/
_onRequestPaused(event) {
if (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) {
this._client.send('Network.continueInterceptedRequest', {
interceptionId: event.interceptionId
this._client.send('Fetch.continueRequest', {
requestId: event.requestId
}).catch(debugError);
}
const requestId = event.requestId;
const requestId = event.networkId;
const interceptionId = event.requestId;
if (requestId && this._requestIdToRequestWillBeSentEvent.has(requestId)) {
const requestWillBeSentEvent = this._requestIdToRequestWillBeSentEvent.get(requestId);
this._onRequest(requestWillBeSentEvent, event.interceptionId);
this._onRequest(requestWillBeSentEvent, interceptionId);
this._requestIdToRequestWillBeSentEvent.delete(requestId);
} else {
this._requestIdToInterceptionId.set(requestId, event.interceptionId);
this._requestIdToInterceptionId.set(requestId, interceptionId);
}
}
@ -424,12 +438,12 @@ class Request {
headers
} = overrides;
this._interceptionHandled = true;
await this._client.send('Network.continueInterceptedRequest', {
interceptionId: this._interceptionId,
await this._client.send('Fetch.continueRequest', {
requestId: this._interceptionId,
url,
method,
postData,
headers,
headers: headers ? headersArray(headers) : undefined,
}).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.
@ -450,6 +464,7 @@ class Request {
const responseBody = response.body && helper.isString(response.body) ? Buffer.from(/** @type {string} */(response.body)) : /** @type {?Buffer} */(response.body || null);
/** @type {!Object<string, string>} */
const responseHeaders = {};
if (response.headers) {
for (const header of Object.keys(response.headers))
@ -458,24 +473,13 @@ class Request {
if (response.contentType)
responseHeaders['content-type'] = response.contentType;
if (responseBody && !('content-length' in responseHeaders))
responseHeaders['content-length'] = Buffer.byteLength(responseBody);
responseHeaders['content-length'] = String(Buffer.byteLength(responseBody));
const statusCode = response.status || 200;
const statusText = statusTexts[statusCode] || '';
const statusLine = `HTTP/1.1 ${statusCode} ${statusText}`;
const CRLF = '\r\n';
let text = statusLine + CRLF;
for (const header of Object.keys(responseHeaders))
text += header + ': ' + responseHeaders[header] + CRLF;
text += CRLF;
let responseBuffer = Buffer.from(text, 'utf8');
if (responseBody)
responseBuffer = Buffer.concat([responseBuffer, responseBody]);
await this._client.send('Network.continueInterceptedRequest', {
interceptionId: this._interceptionId,
rawResponse: responseBuffer.toString('base64')
await this._client.send('Fetch.fulfillRequest', {
requestId: this._interceptionId,
responseCode: response.status || 200,
responseHeaders: headersArray(responseHeaders),
body: responseBody ? responseBody.toString('base64') : undefined,
}).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.
@ -495,8 +499,8 @@ class Request {
assert(this._allowInterception, 'Request Interception is not enabled!');
assert(!this._interceptionHandled, 'Request is already handled!');
this._interceptionHandled = true;
await this._client.send('Network.continueInterceptedRequest', {
interceptionId: this._interceptionId,
await this._client.send('Fetch.failRequest', {
requestId: this._interceptionId,
errorReason
}).catch(error => {
// In certain cases, protocol will return error if the request was already canceled
@ -712,67 +716,15 @@ class SecurityDetails {
}
}
const statusTexts = {
'100': 'Continue',
'101': 'Switching Protocols',
'102': 'Processing',
'200': 'OK',
'201': 'Created',
'202': 'Accepted',
'203': 'Non-Authoritative Information',
'204': 'No Content',
'206': 'Partial Content',
'207': 'Multi-Status',
'208': 'Already Reported',
'209': 'IM Used',
'300': 'Multiple Choices',
'301': 'Moved Permanently',
'302': 'Found',
'303': 'See Other',
'304': 'Not Modified',
'305': 'Use Proxy',
'306': 'Switch Proxy',
'307': 'Temporary Redirect',
'308': 'Permanent Redirect',
'400': 'Bad Request',
'401': 'Unauthorized',
'402': 'Payment Required',
'403': 'Forbidden',
'404': 'Not Found',
'405': 'Method Not Allowed',
'406': 'Not Acceptable',
'407': 'Proxy Authentication Required',
'408': 'Request Timeout',
'409': 'Conflict',
'410': 'Gone',
'411': 'Length Required',
'412': 'Precondition Failed',
'413': 'Payload Too Large',
'414': 'URI Too Long',
'415': 'Unsupported Media Type',
'416': 'Range Not Satisfiable',
'417': 'Expectation Failed',
'418': 'I\'m a teapot',
'421': 'Misdirected Request',
'422': 'Unprocessable Entity',
'423': 'Locked',
'424': 'Failed Dependency',
'426': 'Upgrade Required',
'428': 'Precondition Required',
'429': 'Too Many Requests',
'431': 'Request Header Fields Too Large',
'451': 'Unavailable For Legal Reasons',
'500': 'Internal Server Error',
'501': 'Not Implemented',
'502': 'Bad Gateway',
'503': 'Service Unavailable',
'504': 'Gateway Timeout',
'505': 'HTTP Version Not Supported',
'506': 'Variant Also Negotiates',
'507': 'Insufficient Storage',
'508': 'Loop Detected',
'510': 'Not Extended',
'511': 'Network Authentication Required',
};
/**
* @param {Object<string, string>} headers
* @return {!Array<{name: string, value: string}>}
*/
function headersArray(headers) {
const result = [];
for (const name in headers)
result.push({name, value: headers[name]});
return result;
}
module.exports = {Request, Response, NetworkManager, SecurityDetails};