Innovenergy_trunk/frontend/node_modules/testcafe/lib/proxyless/request-pipeline/index.js

230 lines
41 KiB
JavaScript
Raw Normal View History

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");
const event_provider_1 = __importDefault(require("../request-hooks/event-provider"));
const resource_injector_1 = __importDefault(require("../resource-injector"));
const headers_1 = require("../utils/headers");
const cdp_1 = require("../utils/cdp");
const error_route_1 = __importDefault(require("../error-route"));
const debug_loggers_1 = require("../../utils/debug-loggers");
const testcafe_hammerhead_1 = require("testcafe-hammerhead");
const default_setup_options_1 = __importDefault(require("../default-setup-options"));
const special_handlers_1 = __importDefault(require("./special-handlers"));
const safe_api_1 = require("./safe-api");
const api_base_1 = __importDefault(require("../api-base"));
const resendAuthRequest_1 = require("./resendAuthRequest");
const test_run_bridge_1 = __importDefault(require("./test-run-bridge"));
const context_info_1 = __importDefault(require("./context-info"));
class ProxylessRequestPipeline extends api_base_1.default {
constructor(browserId, client) {
super(browserId, client);
this._testRunBridge = new test_run_bridge_1.default(browserId);
this._contextInfo = new context_info_1.default(this._testRunBridge);
this._specialServiceRoutes = this._getSpecialServiceRoutes();
this.requestHookEventProvider = new event_provider_1.default();
this._resourceInjector = new resource_injector_1.default(this._testRunBridge, this._specialServiceRoutes);
this._options = default_setup_options_1.default;
this._stopped = false;
this._currentFrameTree = null;
this._failedRequestIds = [];
this.restoringStorages = null;
this.contextStorage = null;
}
_getSpecialServiceRoutes() {
const browserConnection = this._testRunBridge.getBrowserConnection();
const proxy = browserConnection.browserConnectionGateway.proxy;
return {
errorPage1: proxy.resolveRelativeServiceUrl(error_route_1.default, proxy.server1Info.domain),
errorPage2: proxy.resolveRelativeServiceUrl(error_route_1.default, proxy.server2Info.domain),
idlePage: browserConnection.idleUrl,
openFileProtocolUrl: browserConnection.openFileProtocolUrl,
};
}
async _handleMockErrorIfNecessary(pipelineContext, event) {
if (!pipelineContext.mock.hasError)
return;
await pipelineContext.handleMockError(this.requestHookEventProvider);
(0, debug_loggers_1.requestPipelineMockLogger)('%s\n%s', event.networkId, pipelineContext.mock.error);
}
async _handleMockResponse(mockedResponse, pipelineContext, event) {
const mockedResponseBodyStr = mockedResponse.getBody().toString();
const fulfillInfo = {
requestId: event.requestId,
responseCode: mockedResponse.statusCode,
responseHeaders: (0, headers_1.convertToHeaderEntries)(mockedResponse.headers),
body: mockedResponseBodyStr,
};
if (pipelineContext.reqOpts.isAjax)
await this._resourceInjector.processNonProxiedContent(fulfillInfo, this._client);
else {
await this._resourceInjector.processHTMLPageContent(fulfillInfo, {
isIframe: false,
contextStorage: this.contextStorage,
}, this._client);
}
(0, debug_loggers_1.requestPipelineMockLogger)(`Mock request ${event.requestId}`);
}
_createContinueResponseRequest(event, modified) {
const continueResponseRequest = {
requestId: event.requestId,
};
if (modified) {
continueResponseRequest.responseHeaders = event.responseHeaders;
continueResponseRequest.responseCode = event.responseStatusCode;
}
return continueResponseRequest;
}
_shouldRedirectToErrorPage(event) {
return event.resourceType === 'Document'
&& !this._isIframe(event.frameId);
}
async _getUserScripts(event) {
const { pipelineContext, eventFactory } = this._contextInfo.getContextData(event);
await pipelineContext.prepareInjectableUserScripts(eventFactory, this._testRunBridge.getUserScripts());
return pipelineContext.injectableUserScripts;
}
async _respondToOtherRequest(event) {
if ((0, testcafe_hammerhead_1.isRedirectStatusCode)(event.responseStatusCode)) {
await (0, safe_api_1.safeContinueResponse)(this._client, { requestId: event.requestId });
return;
}
const resourceInfo = await this._resourceInjector.getDocumentResourceInfo(event, this._client);
if (resourceInfo.error) {
if (this._shouldRedirectToErrorPage(event)) {
await this._resourceInjector.redirectToErrorPage(this._client, resourceInfo.error, event.request.url);
this._contextInfo.dispose((0, cdp_1.getRequestId)(event));
}
return;
}
const modified = await this.requestHookEventProvider.onResponse(event, resourceInfo.body, this._contextInfo, this._client);
if (event.resourceType !== 'Document') {
const continueResponseRequest = this._createContinueResponseRequest(event, modified);
await (0, safe_api_1.safeContinueResponse)(this._client, continueResponseRequest);
this._contextInfo.dispose((0, cdp_1.getRequestId)(event));
}
else {
const fulfillInfo = {
requestId: event.requestId,
responseHeaders: event.responseHeaders,
responseCode: event.responseStatusCode,
body: resourceInfo.body.toString(),
};
// NOTE: Strange behavior of the CDP API:
// if we pass the empty "responseStatusText" value, we get an error 'Invalid status code or phrase'.
if (event.responseStatusText !== '')
fulfillInfo.responsePhrase = event.responseStatusText;
if ((0, cdp_1.isUnauthorized)(event.responseStatusCode))
await this._tryAuthorizeWithHttpBasicAuthCredentials(event, fulfillInfo);
const userScripts = await this._getUserScripts(event);
await this._resourceInjector.processHTMLPageContent(fulfillInfo, {
isIframe: this._isIframe(event.frameId),
url: event.request.url,
restoringStorages: this.restoringStorages,
contextStorage: this.contextStorage,
userScripts,
}, this._client);
this._contextInfo.dispose((0, cdp_1.getRequestId)(event));
this.restoringStorages = null;
}
}
async _tryAuthorizeWithHttpBasicAuthCredentials(event, fulfillInfo) {
const credentials = this._testRun.getAuthCredentials();
if (!credentials)
return;
const authRequest = await (0, resendAuthRequest_1.resendAuthRequest)(event.request, credentials);
if (typeof authRequest !== 'string' && !(0, cdp_1.isUnauthorized)(authRequest.status)) {
fulfillInfo.responseCode = authRequest.status;
fulfillInfo.body = authRequest.body.toString();
fulfillInfo.responsePhrase = authRequest.statusText;
}
}
async _tryRespondToOtherRequest(event) {
try {
await this._respondToOtherRequest(event);
}
catch (err) {
if (event.networkId && this._failedRequestIds.includes(event.networkId)) {
(0, lodash_1.remove)(this._failedRequestIds, event.networkId);
return;
}
throw err;
}
}
async _handleOtherRequests(event) {
(0, debug_loggers_1.requestPipelineOtherRequestLogger)('%r', event);
if (!event.responseErrorReason && ((0, cdp_1.isRequest)(event) || (0, testcafe_hammerhead_1.isRedirectStatusCode)(event.responseStatusCode))) {
this._contextInfo.init(event);
await this.requestHookEventProvider.onRequest(event, this._contextInfo);
const pipelineContext = this._contextInfo.getPipelineContext(event.networkId);
if (!pipelineContext || !pipelineContext.mock)
await (0, safe_api_1.safeContinueRequest)(this._client, event);
else {
const mockedResponse = await pipelineContext.getMockResponse();
await this._handleMockErrorIfNecessary(pipelineContext, event);
const mockedResponseEvent = (0, cdp_1.createRequestPausedEventForResponse)(mockedResponse, event);
await this.requestHookEventProvider.onResponse(mockedResponseEvent, mockedResponse.getBody(), this._contextInfo, this._client);
await this._handleMockResponse(mockedResponse, pipelineContext, event);
this._contextInfo.dispose((0, cdp_1.getRequestId)(event));
}
}
else
await this._tryRespondToOtherRequest(event);
}
_topFrameNavigation(event) {
return event.type === 'Navigation'
&& !event.frame.parentId;
}
async _updateCurrentFrameTree() {
// NOTE: Due to CDP restrictions (it hangs), we can't get the frame tree
// right before injecting service scripts.
// So, we are forced tracking frames tree.
const result = await this._client.Page.getFrameTree();
this._currentFrameTree = result.frameTree;
}
_isIframe(frameId) {
if (!this._currentFrameTree)
return false;
return this._currentFrameTree.frame.id !== frameId;
}
async init(options) {
this._options = options;
this._client.Fetch.on('requestPaused', async (event) => {
if (this._stopped)
return;
const specialRequestHandler = (0, special_handlers_1.default)(event, this._options, this._specialServiceRoutes);
if (specialRequestHandler)
await specialRequestHandler(event, this._client, this._options);
else
await this._handleOtherRequests(event);
});
this._client.Page.on('frameNavigated', async (event) => {
(0, debug_loggers_1.requestPipelineLogger)('%f', event);
if (!this._topFrameNavigation(event)
|| event.frame.url !== testcafe_hammerhead_1.SPECIAL_BLANK_PAGE)
return;
this._contextInfo.init(event);
const userScripts = await this._getUserScripts(event);
await this._resourceInjector.processAboutBlankPage(event, userScripts, this._client);
this._contextInfo.dispose((0, cdp_1.getRequestId)(event));
});
this._client.Page.on('frameStartedLoading', async () => {
await this._updateCurrentFrameTree();
});
this._client.Network.on('loadingFailed', async (event) => {
(0, debug_loggers_1.requestPipelineLogger)('%l', event);
this._failedRequestIds.push(event.requestId);
if (event.requestId)
this._contextInfo.dispose(event.requestId);
});
await this._client.Page.setBypassCSP({ enabled: true });
}
stop() {
this._stopped = true;
}
}
exports.default = ProxylessRequestPipeline;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcHJveHlsZXNzL3JlcXVlc3QtcGlwZWxpbmUvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxtQ0FBZ0M7QUFTaEMscUZBQWdGO0FBQ2hGLDZFQUFvRDtBQUNwRCw4Q0FBMEQ7QUFFMUQsc0NBS3NCO0FBRXRCLGlFQUF5QztBQUV6Qyw2REFJbUM7QUFFbkMsNkRBSzZCO0FBSTdCLHFGQUF1RTtBQUN2RSwwRUFBMEQ7QUFDMUQseUNBQXVFO0FBQ3ZFLDJEQUEyQztBQUMzQywyREFBd0Q7QUFDeEQsd0VBQThDO0FBQzlDLGtFQUF5RDtBQUd6RCxNQUFxQix3QkFBeUIsU0FBUSxrQkFBZ0I7SUFhbEUsWUFBb0IsU0FBaUIsRUFBRSxNQUFtQjtRQUN0RCxLQUFLLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRXpCLElBQUksQ0FBQyxjQUFjLEdBQWEsSUFBSSx5QkFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxZQUFZLEdBQWUsSUFBSSxzQkFBMkIsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDckYsSUFBSSxDQUFDLHFCQUFxQixHQUFNLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO1FBQ2hFLElBQUksQ0FBQyx3QkFBd0IsR0FBRyxJQUFJLHdCQUFpQyxFQUFFLENBQUM7UUFDeEUsSUFBSSxDQUFDLGlCQUFpQixHQUFVLElBQUksMkJBQWdCLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUN0RyxJQUFJLENBQUMsUUFBUSxHQUFtQiwrQkFBK0IsQ0FBQztRQUNoRSxJQUFJLENBQUMsUUFBUSxHQUFtQixLQUFLLENBQUM7UUFDdEMsSUFBSSxDQUFDLGlCQUFpQixHQUFVLElBQUksQ0FBQztRQUNyQyxJQUFJLENBQUMsaUJBQWlCLEdBQVUsRUFBRSxDQUFDO1FBQ25DLElBQUksQ0FBQyxpQkFBaUIsR0FBVSxJQUFJLENBQUM7UUFDckMsSUFBSSxDQUFDLGNBQWMsR0FBYSxJQUFJLENBQUM7SUFDekMsQ0FBQztJQUVPLHdCQUF3QjtRQUM1QixNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUNyRSxNQUFNLEtBQUssR0FBZSxpQkFBaUIsQ0FBQyx3QkFBd0IsQ0FBQyxLQUFLLENBQUM7UUFFM0UsT0FBTztZQUNILFVBQVUsRUFBVyxLQUFLLENBQUMseUJBQXlCLENBQUMscUJBQVcsRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQztZQUMzRixVQUFVLEVBQVcsS0FBSyxDQUFDLHlCQUF5QixDQUFDLHFCQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUM7WUFDM0YsUUFBUSxFQUFhLGlCQUFpQixDQUFDLE9BQU87WUFDOUMsbUJBQW1CLEVBQUUsaUJBQWlCLENBQUMsbUJBQW1CO1NBQzdELENBQUM7SUFDTixDQUFDO0lBRU8sS0FBSyxDQUFDLDJCQUEyQixDQUFFLGVBQXlDLEVBQUUsS0FBeUI7UUFDM0csSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsUUFBUTtZQUM5QixPQUFPO1FBRVgsTUFBTSxlQUFlLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBRXJFLElBQUEseUNBQXlCLEVBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxTQUFTLEVBQUUsZUFBZSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNyRixDQUFDO0lBRU8sS0FBSyxDQUFDLG1CQUFtQixDQUFFLGNBQW1DLEVBQUUsZUFBeUMsRUFBRSxLQUF5QjtRQUN4SSxNQUFNLHFCQUFxQixHQUFJLGNBQWMsQ0FBQyxPQUFPLEVBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUU5RSxNQUFNLFdBQVcsR0FBRztZQUNoQixTQUFTLEVBQVEsS0FBSyxDQUFDLFNBQVM7WUFDaEMsWUFBWSxFQUFLLGNBQWMsQ0FBQyxVQUFVO1lBQzFDLGVBQWUsRUFBRSxJQUFBLGdDQUFzQixFQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUM7WUFDL0QsSUFBSSxFQUFhLHFCQUFxQjtTQUN6QyxDQUFDO1FBRUYsSUFBSSxlQUFlLENBQUMsT0FBTyxDQUFDLE1BQU07WUFDOUIsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsd0JBQXdCLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQzthQUNoRjtZQUNELE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLHNCQUFzQixDQUFDLFdBQVcsRUFBRTtnQkFDN0QsUUFBUSxFQUFRLEtBQUs7Z0JBQ3JCLGNBQWMsRUFBRSxJQUFJLENBQUMsY0FBYzthQUN0QyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUNwQjtRQUVELElBQUEseUNBQXlCLEVBQUMsZ0JBQWdCLEtBQUssQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBQ2pFLENBQUM7SUFFTyw4QkFBOEIsQ0FBRSxLQUF5QixFQUFFLFFBQWlCO1FBQ2hGLE1BQU0sdUJBQXVCLEdBQUc7WUFDNUIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1NBQ0YsQ0FBQztRQUU3QixJQUFJLFFBQVEsRUFBRTtZQUNWLHVCQUF1QixDQUFDLGVBQWUsR0FBRyxLQUFLLENBQUMsZUFBZSxDQUFDO1lBQ2hFLHVCQUF1QixDQUFDLFlBQVksR0FBTSxLQUFLLENBQUMsa0JBQTRCLENBQUM7U0FDaEY7UUFFRCxPQUFPLHVCQUF1QixDQUFDO0lBQ25DLENBQUM7SUFFTywwQkFBMEIsQ0FBRSxLQUF5QjtRQUN6RCxPQUFPLEtBQUssQ0FBQyxZQUFZLEtBQUssVUFBVTtlQUNqQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFTyxLQUFLLENBQUMsZUFBZSxDQUFFLEtBQStDO1FBQzFFLE1BQU0sRUFBRSxlQUFlLEVBQUUsWUFBWSxFQUFFLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFbEYsTUFBTSxlQUFlLENBQUMsNEJBQTRCLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztRQUV2RyxPQUFPLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQztJQUNqRCxDQUFDO0lBRU8sS0FBSyxDQUFDLHNCQUFzQixDQUFFLEtBQXlCO1FBQzNELElBQUksSUFBQSwwQ0FBb0IsRUFBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsRUFBRTtZQUNoRCxNQUFNLElBQUEsK0JBQW9CLEVBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUFFLFNBQVMsRUFBR