Innovenergy_trunk/frontend/node_modules/testcafe-hammerhead/lib/request-pipeline/destination-request/http2.js

105 lines
4.9 KiB
JavaScript

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.clearSessionsCache = exports.createResponseLike = exports.formatRequestHttp2Headers = exports.getHttp2Session = void 0;
const http2_1 = __importDefault(require("http2"));
const lru_cache_1 = __importDefault(require("lru-cache"));
const lodash_1 = require("lodash");
const connection_reset_guard_1 = require("../connection-reset-guard");
const logger_1 = __importDefault(require("../../utils/logger"));
const { HTTP2_HEADER_PATH, HTTP2_HEADER_STATUS, HTTP2_HEADER_METHOD, HTTP2_HEADER_AUTHORITY, HTTP2_HEADER_CONNECTION, HTTP2_HEADER_UPGRADE, HTTP2_HEADER_KEEP_ALIVE, HTTP2_HEADER_PROXY_CONNECTION, HTTP2_HEADER_TRANSFER_ENCODING, HTTP2_HEADER_HTTP2_SETTINGS, HTTP2_HEADER_HOST, } = http2_1.default.constants;
const HTTP2_SESSIONS_CACHE_SIZE = 100;
const HTTP2_SESSION_TIMEOUT = 60000;
const HTTP2_CONNECT_TIMEOUT = 5000;
const HTTP2_LOCAL_SETTINGS_TIMEOUT = 3000;
const HTTP2_UNSUPPORTED_HEADERS = [
HTTP2_HEADER_CONNECTION, HTTP2_HEADER_UPGRADE, HTTP2_HEADER_HTTP2_SETTINGS, HTTP2_HEADER_KEEP_ALIVE,
HTTP2_HEADER_PROXY_CONNECTION, HTTP2_HEADER_TRANSFER_ENCODING, HTTP2_HEADER_HOST,
];
const unsupportedOrigins = [];
const pendingSessions = new Map();
const sessionsCache = new lru_cache_1.default({
max: HTTP2_SESSIONS_CACHE_SIZE,
dispose: (_, session) => {
if (!session.closed)
session.close();
},
});
async function getHttp2Session(requestId, origin) {
if (sessionsCache.has(origin))
return sessionsCache.get(origin) || null;
if (pendingSessions.has(origin))
return pendingSessions.get(origin) || null;
if (unsupportedOrigins.includes(origin))
return null;
const pendingSession = new Promise(resolve => {
const session = http2_1.default.connect(origin, { settings: { enablePush: false } });
const errorHandler = (err) => {
pendingSessions.delete(origin);
if (err.code === 'ERR_HTTP2_ERROR' || err.code === 'ERR_HTTP2_PING_CANCEL') {
unsupportedOrigins.push(origin);
logger_1.default.destination.onHttp2Unsupported(requestId, origin);
}
session.destroy();
resolve(null);
};
const connectTimeout = setTimeout(() => errorHandler({ code: 'ERR_HTTP2_ERROR' }), HTTP2_CONNECT_TIMEOUT);
session.once('error', errorHandler);
session.once('connect', () => {
const localSettingsTimeout = setTimeout(() => errorHandler({ code: 'ERR_HTTP2_ERROR' }), HTTP2_LOCAL_SETTINGS_TIMEOUT);
clearTimeout(connectTimeout);
session.ping(lodash_1.noop);
session.once('localSettings', () => {
clearTimeout(localSettingsTimeout);
pendingSessions.delete(origin);
sessionsCache.set(origin, session);
logger_1.default.destination.onHttp2SessionCreated(requestId, origin, sessionsCache.length, HTTP2_SESSIONS_CACHE_SIZE);
session.once('close', () => {
sessionsCache.del(origin);
logger_1.default.destination.onHttp2SessionClosed(requestId, origin, sessionsCache.length, HTTP2_SESSIONS_CACHE_SIZE);
});
session.off('error', errorHandler);
session.once('error', (err) => {
if (!(0, connection_reset_guard_1.isConnectionResetError)(err)) {
logger_1.default.destination.onHttp2Error(requestId, origin, err);
throw err;
}
});
session.setTimeout(HTTP2_SESSION_TIMEOUT, () => {
logger_1.default.destination.onHttp2SessionTimeout(origin, HTTP2_SESSION_TIMEOUT);
sessionsCache.del(origin);
});
resolve(session);
});
});
});
pendingSessions.set(origin, pendingSession);
return pendingSession;
}
exports.getHttp2Session = getHttp2Session;
function formatRequestHttp2Headers(opts) {
return Object.keys(opts.headers).reduce((headers, key) => {
if (!HTTP2_UNSUPPORTED_HEADERS.includes(key))
headers[key] = opts.headers[key];
return headers;
}, {
[HTTP2_HEADER_METHOD]: opts.method,
[HTTP2_HEADER_PATH]: opts.path,
[HTTP2_HEADER_AUTHORITY]: opts.headers.host,
});
}
exports.formatRequestHttp2Headers = formatRequestHttp2Headers;
function createResponseLike(stream, response) {
const statusCode = response[HTTP2_HEADER_STATUS];
const headers = Object.assign({}, response);
delete headers[HTTP2_HEADER_STATUS];
return Object.assign(stream, { trailers: {}, statusCode, headers });
}
exports.createResponseLike = createResponseLike;
function clearSessionsCache() {
sessionsCache.reset();
}
exports.clearSessionsCache = clearSessionsCache;