Software: Apache/2.4.41 (Ubuntu). PHP/8.0.30 uname -a: Linux apirnd 5.4.0-204-generic #224-Ubuntu SMP Thu Dec 5 13:38:28 UTC 2024 x86_64 uid=33(www-data) gid=33(www-data) groups=33(www-data) Safe-mode: OFF (not secure) /var/www/html/invoice_pdf/node_modules/chromium-bidi/lib/cjs/bidiMapper/domains/network/ drwxr-xr-x | |
| Viewing file: Select action/file-type: "use strict";
/*
* Copyright 2023 Google LLC.
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.NetworkRequest = void 0;
const protocol_js_1 = require("../../../protocol/protocol.js");
const assert_js_1 = require("../../../utils/assert.js");
const Deferred_js_1 = require("../../../utils/Deferred.js");
const NetworkUtils_js_1 = require("./NetworkUtils.js");
/** Abstracts one individual network request. */
class NetworkRequest {
static #unknown = 'UNKNOWN';
/**
* Each network request has an associated request id, which is a string
* uniquely identifying that request.
*
* The identifier for a request resulting from a redirect matches that of the
* request that initiated it.
*/
#id;
#fetchId;
/**
* Indicates the network intercept phase, if the request is currently blocked.
* Undefined necessarily implies that the request is not blocked.
*/
#interceptPhase;
#servedFromCache = false;
#redirectCount;
#request = {};
#response = {};
#beforeRequestSentDeferred = new Deferred_js_1.Deferred();
#responseStartedDeferred = new Deferred_js_1.Deferred();
#responseCompletedDeferred = new Deferred_js_1.Deferred();
#eventManager;
#networkStorage;
#cdpTarget;
constructor(id, eventManager, networkStorage, cdpTarget, redirectCount = 0) {
this.#id = id;
this.#eventManager = eventManager;
this.#networkStorage = networkStorage;
this.#cdpTarget = cdpTarget;
this.#redirectCount = redirectCount;
}
get id() {
return this.#id;
}
get fetchId() {
return this.#fetchId;
}
get phase() {
return this.#interceptPhase;
}
get url() {
return (this.#response.info?.url ??
this.#request.info?.request.url ??
this.#request.paused?.request.url ??
this.#response.paused?.request.url);
}
get redirectCount() {
return this.#redirectCount;
}
get blocked() {
return this.#isBlockedInPhase(this.#interceptPhase);
}
get cdpClient() {
return this.#cdpTarget.cdpClient;
}
isRedirecting() {
return Boolean(this.#request.info);
}
#isBlockedInPhase(phase) {
return this.#networkStorage.requestBlockedBy(this, phase).size > 0;
}
handleRedirect(event) {
this.#queueResponseStartedEvent();
this.#queueResponseCompletedEvent();
this.#response.hasExtraInfo = event.redirectHasExtraInfo;
this.#response.info = event.redirectResponse;
this.#emitEventsIfReady(true);
}
#emitEventsIfReady(wasRedirected = false) {
const requestExtraInfoCompleted =
// Flush redirects
wasRedirected ||
Boolean(this.#request.extraInfo) ||
// Requests from cache don't have extra info
this.#servedFromCache ||
// Sometimes there is no extra info and the response
// is the only place we can find out
Boolean(this.#response.info && !this.#response.hasExtraInfo);
const requestInterceptionExpected = this.#isBlockedInPhase("beforeRequestSent" /* Network.InterceptPhase.BeforeRequestSent */);
const requestInterceptionCompleted = (requestInterceptionExpected && Boolean(this.#request.paused)) ||
!requestInterceptionExpected;
if (Boolean(this.#request.info) &&
(requestInterceptionExpected
? requestInterceptionCompleted
: requestExtraInfoCompleted)) {
this.#beforeRequestSentDeferred.resolve({
kind: 'success',
value: undefined,
});
}
const responseExtraInfoCompleted = Boolean(this.#response.extraInfo) ||
// Response from cache don't have extra info
this.#servedFromCache ||
// Don't expect extra info if the flag is false
Boolean(this.#response.info && !this.#response.hasExtraInfo);
const responseInterceptionExpected = this.#isBlockedInPhase("responseStarted" /* Network.InterceptPhase.ResponseStarted */);
const responseInterceptionCompleted = (responseInterceptionExpected && Boolean(this.#response.paused)) ||
!responseInterceptionExpected;
if (responseInterceptionExpected && Boolean(this.#response.paused)) {
this.#responseStartedDeferred.resolve({
kind: 'success',
value: undefined,
});
}
else if (this.#response.info) {
this.#responseStartedDeferred.resolve({
kind: 'success',
value: undefined,
});
}
if (Boolean(this.#response.info) &&
responseExtraInfoCompleted &&
responseInterceptionCompleted) {
this.#responseCompletedDeferred.resolve({
kind: 'success',
value: undefined,
});
}
}
onRequestWillBeSentEvent(event) {
this.#request.info = event;
this.#queueBeforeRequestSentEvent();
this.#emitEventsIfReady();
}
onRequestWillBeSentExtraInfoEvent(event) {
this.#request.extraInfo = event;
this.#emitEventsIfReady();
}
onResponseReceivedExtraInfoEvent(event) {
this.#response.extraInfo = event;
this.#emitEventsIfReady();
}
onResponseReceivedEvent(event) {
this.#response.hasExtraInfo = event.hasExtraInfo;
this.#response.info = event.response;
this.#queueResponseStartedEvent();
this.#queueResponseCompletedEvent();
this.#emitEventsIfReady();
}
onServedFromCache() {
this.#servedFromCache = true;
this.#emitEventsIfReady();
}
onLoadingFailedEvent(event) {
this.#beforeRequestSentDeferred.resolve({
kind: 'success',
value: undefined,
});
this.#responseStartedDeferred.resolve({
kind: 'error',
error: new Error('Network event loading failed'),
});
this.#responseCompletedDeferred.resolve({
kind: 'error',
error: new Error('Network event loading failed'),
});
this.#queueEventPromise(Promise.resolve({ kind: 'success', value: undefined }), () => {
return {
params: {
...this.#getBaseEventParams(),
errorText: event.errorText,
},
method: protocol_js_1.ChromiumBidi.Network.EventNames.FetchError,
type: 'event',
};
}, protocol_js_1.ChromiumBidi.Network.EventNames.FetchError);
}
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-failRequest */
async failRequest(errorReason) {
(0, assert_js_1.assert)(this.#fetchId, 'Network Interception not set-up.');
await this.cdpClient.sendCommand('Fetch.failRequest', {
requestId: this.#fetchId,
errorReason,
});
this.#interceptPhase = undefined;
}
onRequestPaused(event) {
this.#fetchId = event.requestId;
// CDP https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#event-requestPaused
if (event.responseStatusCode || event.responseErrorReason) {
this.#interceptPhase = "responseStarted" /* Network.InterceptPhase.ResponseStarted */;
this.#response.paused = event;
this.#emitEventsIfReady();
if (!this.blocked) {
void this.continueResponse();
}
else if (!this.#response.info) {
this.#queueResponseStartedEvent();
this.#queueResponseCompletedEvent();
}
}
else {
this.#request.paused = event;
this.#interceptPhase = "beforeRequestSent" /* Network.InterceptPhase.BeforeRequestSent */;
this.#emitEventsIfReady();
if (!this.blocked) {
void this.continueRequest();
}
}
}
onAuthRequired(_event) {
this.#interceptPhase = "authRequired" /* Network.InterceptPhase.AuthRequired */;
if (!this.blocked) {
void this.continueWithAuth();
}
this.#queueEventPromise(Promise.resolve({ kind: 'success', value: undefined }), () => {
return {
params: {
...this.#getBaseEventParams("authRequired" /* Network.InterceptPhase.AuthRequired */),
// TODO: Why is this on the Spec
// How are we suppose to know the response if we are blocked by Auth
response: {},
},
method: protocol_js_1.ChromiumBidi.Network.EventNames.AuthRequired,
type: 'event',
};
}, protocol_js_1.ChromiumBidi.Network.EventNames.AuthRequired);
}
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-continueRequest */
async continueRequest(url, method, headers) {
(0, assert_js_1.assert)(this.#fetchId, 'Network Interception not set-up.');
// TODO: Expand.
await this.cdpClient.sendCommand('Fetch.continueRequest', {
requestId: this.#fetchId,
url,
method,
headers,
// TODO: Set?
// postData:,
// interceptResponse:,
});
this.#interceptPhase = undefined;
}
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-continueResponse */
async continueResponse({ responseCode, responsePhrase, responseHeaders, } = {}) {
(0, assert_js_1.assert)(this.#fetchId, 'Network Interception not set-up.');
await this.cdpClient.sendCommand('Fetch.continueResponse', {
requestId: this.#fetchId,
responseCode,
responsePhrase,
responseHeaders,
});
this.#interceptPhase = undefined;
}
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-continueWithAuth */
async continueWithAuth(authChallengeResponse = {
response: 'Default',
}) {
(0, assert_js_1.assert)(this.#fetchId, 'Network Interception not set-up.');
await this.cdpClient.sendCommand('Fetch.continueWithAuth', {
requestId: this.#fetchId,
authChallengeResponse,
});
this.#interceptPhase = undefined;
}
/** @see https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#method-provideResponse */
async provideResponse({ responseCode, responsePhrase, responseHeaders, body, }) {
(0, assert_js_1.assert)(this.#fetchId, 'Network Interception not set-up.');
await this.cdpClient.sendCommand('Fetch.fulfillRequest', {
requestId: this.#fetchId,
responseCode,
responsePhrase,
responseHeaders,
...(body ? { body: btoa(body) } : {}), // TODO: Double-check if btoa usage is correct.
});
this.#interceptPhase = undefined;
}
dispose() {
const result = {
kind: 'error',
error: new Error('Network processor detached'),
};
this.#beforeRequestSentDeferred.resolve(result);
this.#responseStartedDeferred.resolve(result);
this.#responseCompletedDeferred.resolve(result);
}
get #context() {
return this.#request.info?.frameId ?? null;
}
/** Returns the HTTP status code associated with this request if any. */
get statusCode() {
return (this.#response.info?.status ?? this.#response.extraInfo?.statusCode ?? -1 // TODO: Throw an exception or use some other status code?
);
}
#queueEventPromise(deferred, getEventData, eventName) {
if (this.#isIgnoredEvent()) {
return;
}
this.#eventManager.registerPromiseEvent(deferred.then((result) => {
if (result.kind === 'success') {
try {
return {
kind: 'success',
value: getEventData(),
};
}
catch (error) {
return {
kind: 'error',
error: error instanceof Error ? error : new Error('Unknown'),
};
}
}
return result;
}), this.#context, eventName);
}
#getBaseEventParams(phase) {
const interceptProps = {
isBlocked: false,
};
if (phase && phase === this.#interceptPhase) {
const blockedBy = this.#networkStorage.requestBlockedBy(this, phase);
interceptProps.isBlocked = blockedBy.size > 0;
if (interceptProps.isBlocked) {
interceptProps.intercepts = [...blockedBy];
}
}
return {
context: this.#context,
navigation: this.#getNavigationId(),
redirectCount: this.#redirectCount,
request: this.#getRequestData(),
// Timestamp should be in milliseconds, while CDP provides it in seconds.
timestamp: Math.round((this.#request.info?.wallTime ?? 0) * 1000),
// Contains isBlocked and intercepts
...interceptProps,
};
}
#getNavigationId() {
if (!this.#request.info ||
!this.#request.info.loaderId ||
// When we navigate all CDP network events have `loaderId`
// CDP's `loaderId` and `requestId` match when
// that request triggered the loading
this.#request.info.loaderId !== this.#request.info.requestId) {
return null;
}
return this.#request.info.loaderId;
}
#getRequestData() {
const cookies = this.#request.extraInfo
? NetworkRequest.#getCookies(this.#request.extraInfo.associatedCookies)
: [];
const headers = (0, NetworkUtils_js_1.bidiNetworkHeadersFromCdpNetworkHeaders)(this.#request.info?.request.headers);
return {
request: this.#request.info?.requestId ?? NetworkRequest.#unknown,
url: this.#request.info?.request.url ?? NetworkRequest.#unknown,
method: this.#request.info?.request.method ?? NetworkRequest.#unknown,
headers,
cookies,
headersSize: (0, NetworkUtils_js_1.computeHeadersSize)(headers),
// TODO: implement.
bodySize: 0,
timings: this.#getTimings(),
};
}
// TODO: implement.
#getTimings() {
return {
timeOrigin: 0,
requestTime: 0,
redirectStart: 0,
redirectEnd: 0,
fetchStart: 0,
dnsStart: 0,
dnsEnd: 0,
connectStart: 0,
connectEnd: 0,
tlsStart: 0,
requestStart: 0,
responseStart: 0,
responseEnd: 0,
};
}
#queueBeforeRequestSentEvent() {
this.#queueEventPromise(this.#beforeRequestSentDeferred, () => {
return Object.assign(this.#getBeforeRequestEvent(), {
type: 'event',
});
}, protocol_js_1.ChromiumBidi.Network.EventNames.BeforeRequestSent);
}
#getBeforeRequestEvent() {
(0, assert_js_1.assert)(this.#request.info, 'RequestWillBeSentEvent is not set');
return {
method: protocol_js_1.ChromiumBidi.Network.EventNames.BeforeRequestSent,
params: {
...this.#getBaseEventParams("beforeRequestSent" /* Network.InterceptPhase.BeforeRequestSent */),
initiator: {
type: NetworkRequest.#getInitiatorType(this.#request.info.initiator.type),
},
},
};
}
#queueResponseStartedEvent() {
this.#queueEventPromise(this.#responseStartedDeferred, () => {
return Object.assign(this.#getResponseStartedEvent(), {
type: 'event',
});
}, protocol_js_1.ChromiumBidi.Network.EventNames.ResponseStarted);
}
#getResponseStartedEvent() {
(0, assert_js_1.assert)(this.#request.info, 'RequestWillBeSentEvent is not set');
(0, assert_js_1.assert)(
// The response paused comes before any data for the response
this.#response.paused || this.#response.info, 'ResponseReceivedEvent is not set');
// Chromium sends wrong extraInfo events for responses served from cache.
// See https://github.com/puppeteer/puppeteer/issues/9965 and
// https://crbug.com/1340398.
if (this.#response.info?.fromDiskCache) {
this.#response.extraInfo = undefined;
}
// TODO: get headers from Fetch.requestPaused
const headers = (0, NetworkUtils_js_1.bidiNetworkHeadersFromCdpNetworkHeaders)(this.#response.info?.headers);
return {
method: protocol_js_1.ChromiumBidi.Network.EventNames.ResponseStarted,
params: {
...this.#getBaseEventParams("responseStarted" /* Network.InterceptPhase.ResponseStarted */),
response: {
url: this.#response.info?.url ??
this.#response.paused?.request.url ??
NetworkRequest.#unknown,
protocol: this.#response.info?.protocol ?? '',
status: this.statusCode || this.#response.paused?.responseStatusCode || 0,
statusText: this.#response.info?.statusText ||
this.#response.paused?.responseStatusText ||
'',
fromCache: this.#response.info?.fromDiskCache ||
this.#response.info?.fromPrefetchCache ||
this.#servedFromCache,
headers,
mimeType: this.#response.info?.mimeType || '',
bytesReceived: this.#response.info?.encodedDataLength || 0,
headersSize: (0, NetworkUtils_js_1.computeHeadersSize)(headers),
// TODO: consider removing from spec.
bodySize: 0,
content: {
// TODO: consider removing from spec.
size: 0,
},
},
},
};
}
#queueResponseCompletedEvent() {
this.#queueEventPromise(this.#responseCompletedDeferred, () => {
return Object.assign(this.#getResponseReceivedEvent(), {
type: 'event',
});
}, protocol_js_1.ChromiumBidi.Network.EventNames.ResponseCompleted);
}
#getResponseReceivedEvent() {
(0, assert_js_1.assert)(this.#request.info, 'RequestWillBeSentEvent is not set');
(0, assert_js_1.assert)(this.#response.info, 'ResponseReceivedEvent is not set');
// Chromium sends wrong extraInfo events for responses served from cache.
// See https://github.com/puppeteer/puppeteer/issues/9965 and
// https://crbug.com/1340398.
if (this.#response.info.fromDiskCache) {
this.#response.extraInfo = undefined;
}
const headers = (0, NetworkUtils_js_1.bidiNetworkHeadersFromCdpNetworkHeaders)(this.#response.info.headers);
return {
method: protocol_js_1.ChromiumBidi.Network.EventNames.ResponseCompleted,
params: {
...this.#getBaseEventParams(),
response: {
url: this.#response.info.url ?? NetworkRequest.#unknown,
protocol: this.#response.info.protocol ?? '',
status: this.statusCode,
statusText: this.#response.info.statusText,
fromCache: this.#response.info.fromDiskCache ||
this.#response.info.fromPrefetchCache ||
this.#servedFromCache,
headers,
mimeType: this.#response.info.mimeType,
bytesReceived: this.#response.info.encodedDataLength,
headersSize: (0, NetworkUtils_js_1.computeHeadersSize)(headers),
// TODO: consider removing from spec.
bodySize: 0,
content: {
// TODO: consider removing from spec.
size: 0,
},
},
},
};
}
#isIgnoredEvent() {
return this.#request.info?.request.url.endsWith('/favicon.ico') ?? false;
}
static #getInitiatorType(initiatorType) {
switch (initiatorType) {
case 'parser':
case 'script':
case 'preflight':
return initiatorType;
default:
return 'other';
}
}
static #getCookies(associatedCookies) {
return associatedCookies
.filter(({ blockedReasons }) => {
return !Array.isArray(blockedReasons) || blockedReasons.length === 0;
})
.map(({ cookie }) => (0, NetworkUtils_js_1.cdpToBiDiCookie)(cookie));
}
}
exports.NetworkRequest = NetworkRequest;
//# sourceMappingURL=NetworkRequest.js.map |
:: Command execute :: | |
--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0055 ]-- |