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>} */
|
||||
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: '*'}] : [];
|
||||
if (enabled) {
|
||||
await Promise.all([
|
||||
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() {
|
||||
@ -171,38 +181,42 @@ class NetworkManager extends EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Protocol.Network.requestInterceptedPayload} event
|
||||
* @param {!Protocol.Fetch.authRequiredPayload} event
|
||||
*/
|
||||
_onRequestIntercepted(event) {
|
||||
if (event.authChallenge) {
|
||||
_onAuthRequired(event) {
|
||||
/** @type {"Default"|"CancelAuth"|"ProvideCredentials"} */
|
||||
let response = 'Default';
|
||||
if (this._attemptedAuthentications.has(event.interceptionId)) {
|
||||
if (this._attemptedAuthentications.has(event.requestId)) {
|
||||
response = 'CancelAuth';
|
||||
} else if (this._credentials) {
|
||||
response = 'ProvideCredentials';
|
||||
this._attemptedAuthentications.add(event.interceptionId);
|
||||
this._attemptedAuthentications.add(event.requestId);
|
||||
}
|
||||
const {username, password} = this._credentials || {username: undefined, password: undefined};
|
||||
this._client.send('Network.continueInterceptedRequest', {
|
||||
interceptionId: event.interceptionId,
|
||||
authChallengeResponse: { response, username, password }
|
||||
}).catch(debugError);
|
||||
return;
|
||||
}
|
||||
if (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) {
|
||||
this._client.send('Network.continueInterceptedRequest', {
|
||||
interceptionId: event.interceptionId
|
||||
this._client.send('Fetch.continueWithAuth', {
|
||||
requestId: event.requestId,
|
||||
authChallengeResponse: { response, username, password },
|
||||
}).catch(debugError);
|
||||
}
|
||||
|
||||
const requestId = event.requestId;
|
||||
/**
|
||||
* @param {!Protocol.Fetch.requestPausedPayload} event
|
||||
*/
|
||||
_onRequestPaused(event) {
|
||||
if (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) {
|
||||
this._client.send('Fetch.continueRequest', {
|
||||
requestId: event.requestId
|
||||
}).catch(debugError);
|
||||
}
|
||||
|
||||
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};
|
||||
|
Loading…
Reference in New Issue
Block a user