mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
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:
parent
a79b775430
commit
2265974ce5
@ -45,8 +45,9 @@ class NetworkManager extends EventEmitter {
|
|||||||
/** @type {!Map<string, string>} */
|
/** @type {!Map<string, string>} */
|
||||||
this._requestIdToInterceptionId = new Map();
|
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.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.requestServedFromCache', this._onRequestServedFromCache.bind(this));
|
||||||
this._client.on('Network.responseReceived', this._onResponseReceived.bind(this));
|
this._client.on('Network.responseReceived', this._onResponseReceived.bind(this));
|
||||||
this._client.on('Network.loadingFinished', this._onLoadingFinished.bind(this));
|
this._client.on('Network.loadingFinished', this._onLoadingFinished.bind(this));
|
||||||
@ -138,11 +139,20 @@ class NetworkManager extends EventEmitter {
|
|||||||
if (enabled === this._protocolRequestInterceptionEnabled)
|
if (enabled === this._protocolRequestInterceptionEnabled)
|
||||||
return;
|
return;
|
||||||
this._protocolRequestInterceptionEnabled = enabled;
|
this._protocolRequestInterceptionEnabled = enabled;
|
||||||
const patterns = enabled ? [{urlPattern: '*'}] : [];
|
if (enabled) {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._updateProtocolCacheDisabled(),
|
this._updateProtocolCacheDisabled(),
|
||||||
this._client.send('Network.setRequestInterception', {patterns})
|
this._client.send('Fetch.enable', {
|
||||||
]);
|
handleAuthRequests: true,
|
||||||
|
patterns: [{urlPattern: '*'}],
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
await Promise.all([
|
||||||
|
this._updateProtocolCacheDisabled(),
|
||||||
|
this._client.send('Fetch.disable')
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _updateProtocolCacheDisabled() {
|
async _updateProtocolCacheDisabled() {
|
||||||
@ -171,38 +181,42 @@ class NetworkManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!Protocol.Network.requestInterceptedPayload} event
|
* @param {!Protocol.Fetch.authRequiredPayload} event
|
||||||
*/
|
*/
|
||||||
_onRequestIntercepted(event) {
|
_onAuthRequired(event) {
|
||||||
if (event.authChallenge) {
|
/** @type {"Default"|"CancelAuth"|"ProvideCredentials"} */
|
||||||
/** @type {"Default"|"CancelAuth"|"ProvideCredentials"} */
|
let response = 'Default';
|
||||||
let response = 'Default';
|
if (this._attemptedAuthentications.has(event.requestId)) {
|
||||||
if (this._attemptedAuthentications.has(event.interceptionId)) {
|
response = 'CancelAuth';
|
||||||
response = 'CancelAuth';
|
} else if (this._credentials) {
|
||||||
} else if (this._credentials) {
|
response = 'ProvideCredentials';
|
||||||
response = 'ProvideCredentials';
|
this._attemptedAuthentications.add(event.requestId);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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) {
|
if (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) {
|
||||||
this._client.send('Network.continueInterceptedRequest', {
|
this._client.send('Fetch.continueRequest', {
|
||||||
interceptionId: event.interceptionId
|
requestId: event.requestId
|
||||||
}).catch(debugError);
|
}).catch(debugError);
|
||||||
}
|
}
|
||||||
|
|
||||||
const requestId = event.requestId;
|
const requestId = event.networkId;
|
||||||
|
const interceptionId = event.requestId;
|
||||||
if (requestId && this._requestIdToRequestWillBeSentEvent.has(requestId)) {
|
if (requestId && this._requestIdToRequestWillBeSentEvent.has(requestId)) {
|
||||||
const requestWillBeSentEvent = this._requestIdToRequestWillBeSentEvent.get(requestId);
|
const requestWillBeSentEvent = this._requestIdToRequestWillBeSentEvent.get(requestId);
|
||||||
this._onRequest(requestWillBeSentEvent, event.interceptionId);
|
this._onRequest(requestWillBeSentEvent, interceptionId);
|
||||||
this._requestIdToRequestWillBeSentEvent.delete(requestId);
|
this._requestIdToRequestWillBeSentEvent.delete(requestId);
|
||||||
} else {
|
} else {
|
||||||
this._requestIdToInterceptionId.set(requestId, event.interceptionId);
|
this._requestIdToInterceptionId.set(requestId, interceptionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,12 +438,12 @@ class Request {
|
|||||||
headers
|
headers
|
||||||
} = overrides;
|
} = overrides;
|
||||||
this._interceptionHandled = true;
|
this._interceptionHandled = true;
|
||||||
await this._client.send('Network.continueInterceptedRequest', {
|
await this._client.send('Fetch.continueRequest', {
|
||||||
interceptionId: this._interceptionId,
|
requestId: this._interceptionId,
|
||||||
url,
|
url,
|
||||||
method,
|
method,
|
||||||
postData,
|
postData,
|
||||||
headers,
|
headers: headers ? headersArray(headers) : undefined,
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
// In certain cases, protocol will return error if the request was already canceled
|
// In certain cases, protocol will return error if the request was already canceled
|
||||||
// or the page was closed. We should tolerate these errors.
|
// 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);
|
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 = {};
|
const responseHeaders = {};
|
||||||
if (response.headers) {
|
if (response.headers) {
|
||||||
for (const header of Object.keys(response.headers))
|
for (const header of Object.keys(response.headers))
|
||||||
@ -458,24 +473,13 @@ class Request {
|
|||||||
if (response.contentType)
|
if (response.contentType)
|
||||||
responseHeaders['content-type'] = response.contentType;
|
responseHeaders['content-type'] = response.contentType;
|
||||||
if (responseBody && !('content-length' in responseHeaders))
|
if (responseBody && !('content-length' in responseHeaders))
|
||||||
responseHeaders['content-length'] = Buffer.byteLength(responseBody);
|
responseHeaders['content-length'] = String(Buffer.byteLength(responseBody));
|
||||||
|
|
||||||
const statusCode = response.status || 200;
|
await this._client.send('Fetch.fulfillRequest', {
|
||||||
const statusText = statusTexts[statusCode] || '';
|
requestId: this._interceptionId,
|
||||||
const statusLine = `HTTP/1.1 ${statusCode} ${statusText}`;
|
responseCode: response.status || 200,
|
||||||
|
responseHeaders: headersArray(responseHeaders),
|
||||||
const CRLF = '\r\n';
|
body: responseBody ? responseBody.toString('base64') : undefined,
|
||||||
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')
|
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
// In certain cases, protocol will return error if the request was already canceled
|
// In certain cases, protocol will return error if the request was already canceled
|
||||||
// or the page was closed. We should tolerate these errors.
|
// 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._allowInterception, 'Request Interception is not enabled!');
|
||||||
assert(!this._interceptionHandled, 'Request is already handled!');
|
assert(!this._interceptionHandled, 'Request is already handled!');
|
||||||
this._interceptionHandled = true;
|
this._interceptionHandled = true;
|
||||||
await this._client.send('Network.continueInterceptedRequest', {
|
await this._client.send('Fetch.failRequest', {
|
||||||
interceptionId: this._interceptionId,
|
requestId: this._interceptionId,
|
||||||
errorReason
|
errorReason
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
// In certain cases, protocol will return error if the request was already canceled
|
// In certain cases, protocol will return error if the request was already canceled
|
||||||
@ -712,67 +716,15 @@ class SecurityDetails {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const statusTexts = {
|
/**
|
||||||
'100': 'Continue',
|
* @param {Object<string, string>} headers
|
||||||
'101': 'Switching Protocols',
|
* @return {!Array<{name: string, value: string}>}
|
||||||
'102': 'Processing',
|
*/
|
||||||
'200': 'OK',
|
function headersArray(headers) {
|
||||||
'201': 'Created',
|
const result = [];
|
||||||
'202': 'Accepted',
|
for (const name in headers)
|
||||||
'203': 'Non-Authoritative Information',
|
result.push({name, value: headers[name]});
|
||||||
'204': 'No Content',
|
return result;
|
||||||
'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',
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {Request, Response, NetworkManager, SecurityDetails};
|
module.exports = {Request, Response, NetworkManager, SecurityDetails};
|
||||||
|
Loading…
Reference in New Issue
Block a user