@applitools/execution-grid-client
Advanced tools
Comparing version 1.1.8 to 1.1.9
@@ -21,13 +21,30 @@ #!/usr/bin/env node | ||
}, | ||
serverUrl: { | ||
description: 'run server with specific default eyes server url.', | ||
egTunnelUrl: { | ||
description: 'run server with specific eg tunnel url.', | ||
type: 'string', | ||
}, | ||
egTimeout: { | ||
description: 'run server with specific default eg timeout.', | ||
alias: 'timeout', | ||
type: 'number', | ||
}, | ||
egInactivityTimeout: { | ||
description: 'run server with specific default eg inactivity timeout.', | ||
alias: 'inactivityTimeout', | ||
type: 'number', | ||
}, | ||
proxyUrl: { | ||
description: 'run server with specific default proxy url.', | ||
alias: 'proxy', | ||
type: 'string', | ||
}, | ||
eyesServerUrl: { | ||
description: 'run server with specific default eyes server url.', | ||
alias: 'serverUrl', | ||
type: 'string', | ||
}, | ||
apiKey: { | ||
description: 'run server with specific default api key.', | ||
type: 'number', | ||
type: 'string', | ||
}, | ||
tunnelUrl: { | ||
description: 'run server with specific default tunnel url.', | ||
}, | ||
}); | ||
@@ -34,0 +51,0 @@ exports.builder = builder; |
@@ -25,12 +25,10 @@ "use strict"; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.makeServer = void 0; | ||
const http_1 = require("http"); | ||
const logger_1 = require("@applitools/logger"); | ||
const queue_1 = require("./queue"); | ||
const tunnel_1 = require("./tunnel"); | ||
const proxy_1 = require("./proxy"); | ||
const tunnel_1 = require("./tunnel"); | ||
const raw_body_1 = __importDefault(require("raw-body")); | ||
const logger_1 = require("@applitools/logger"); | ||
const parse_body_1 = require("./parse-body"); | ||
const utils = __importStar(require("@applitools/utils")); | ||
@@ -41,23 +39,38 @@ const RETRY_BACKOFF = [].concat(Array(5).fill(2000), // 5 tries with delay 2s (total 10s) | ||
const RETRY_ERROR_CODES = ['CONCURRENCY_LIMIT_REACHED', 'NO_AVAILABLE_DRIVER_POD']; | ||
function makeServer({ port = 0, forwardingUrl = 'https://exec-wus.applitools.com', tunnelUrl = process.env.APPLITOOLS_EG_TUNNEL_URL, serverUrl = process.env.APPLITOOLS_SERVER_URL, apiKey = process.env.APPLITOOLS_API_KEY, logger, } = {}) { | ||
function makeServer({ egServerUrl = 'https://exec-wus.applitools.com', egTunnelUrl = process.env.APPLITOOLS_EG_TUNNEL_URL, egTimeout = process.env.APPLITOOLS_EG_TIMEOUT, egInactivityTimeout = process.env.APPLITOOLS_EG_INACTIVITY_TIMEOUT, proxyUrl = process.env.APPLITOOLS_PROXY, eyesServerUrl = process.env.APPLITOOLS_SERVER_URL, apiKey = process.env.APPLITOOLS_API_KEY, port = 0, resolveUrls = true, logger, } = {}) { | ||
logger = logger ? logger.extend({ label: 'eg-client' }) : (0, logger_1.makeLogger)({ label: 'eg-client', colors: true }); | ||
const proxyRequest = (0, proxy_1.makeProxy)({ | ||
url: egServerUrl, | ||
resolveUrls, | ||
proxy: proxyUrl, | ||
shouldRetry: async (proxyResponse) => { | ||
var _a; | ||
if (proxyResponse.statusCode <= 400) | ||
return false; | ||
//@ts-ignore | ||
proxyResponse.body = await (0, parse_body_1.parseBody)(proxyResponse); | ||
return !((_a = proxyResponse.body) === null || _a === void 0 ? void 0 : _a.value); | ||
}, | ||
}); | ||
const { createTunnel, deleteTunnel } = (0, tunnel_1.makeTunnelManager)({ egTunnelUrl, logger }); | ||
const sessions = new Map(); | ||
const { createTunnel, deleteTunnel } = (0, tunnel_1.makeTunnelManager)({ tunnelUrl, logger }); | ||
const queues = new Map(); | ||
const server = (0, http_1.createServer)(async (request, response) => { | ||
const requestLogger = logger.extend({ | ||
tags: { signature: `[${request.method}]${request.url}`, requestId: utils.general.guid() }, | ||
tags: { request: `[${request.method}] ${request.url}`, requestId: utils.general.guid() }, | ||
}); | ||
try { | ||
if (request.method === 'POST' && /^\/session\/?$/.test(request.url)) { | ||
return await handleNewSession({ request, response, logger: requestLogger }); | ||
return await createSession({ request, response, logger: requestLogger }); | ||
} | ||
else if (request.method === 'DELETE' && /^\/session\/[^\/]+\/?$/.test(request.url)) { | ||
return await handleStopSession({ request, response, logger: requestLogger }); | ||
return await deleteSession({ request, response, logger: requestLogger }); | ||
} | ||
else { | ||
requestLogger.log('Passthrough request'); | ||
return await (0, proxy_1.proxy)({ request, response, options: { target: forwardingUrl }, logger: requestLogger }); | ||
return await proxyRequest({ request, response, logger: requestLogger }); | ||
} | ||
} | ||
catch (err) { | ||
// console.error(err) | ||
requestLogger.error(`Error during processing request:`, err); | ||
@@ -72,3 +85,3 @@ response | ||
}); | ||
server.listen(port, 'localhost'); | ||
server.listen(port); | ||
return new Promise((resolve, reject) => { | ||
@@ -85,20 +98,16 @@ server.on('listening', () => { | ||
}); | ||
async function handleNewSession({ request, response, logger, }) { | ||
async function createSession({ request, response, logger, }) { | ||
var _a, _b, _c, _d, _e; | ||
const requestBody = await (0, raw_body_1.default)(request, 'utf-8').then(body => (body ? JSON.parse(body) : undefined)); | ||
if (!requestBody) | ||
return logger.log(`Request has no body`); | ||
const requestBody = await (0, parse_body_1.parseBody)(request); | ||
logger.log(`Request was intercepted with body:`, requestBody); | ||
const session = {}; | ||
session.serverUrl = (_a = extractCapability(requestBody, 'applitools:eyesServerUrl')) !== null && _a !== void 0 ? _a : serverUrl; | ||
session.eyesServerUrl = (_a = extractCapability(requestBody, 'applitools:eyesServerUrl')) !== null && _a !== void 0 ? _a : eyesServerUrl; | ||
session.apiKey = (_b = extractCapability(requestBody, 'applitools:apiKey')) !== null && _b !== void 0 ? _b : apiKey; | ||
session.tunnelId = extractCapability(requestBody, 'applitools:tunnel') ? await createTunnel(session) : undefined; | ||
const timeout = (_c = extractCapability(requestBody, 'applitools:timeout')) !== null && _c !== void 0 ? _c : process.env.APPLITOOLS_EG_TIMEOUT; | ||
const inactivityTimeout = (_d = extractCapability(requestBody, 'applitools:inactivityTimeout')) !== null && _d !== void 0 ? _d : process.env.APPLITOOLS_EG_INACTIVITY_TIMEOUT; | ||
const applitoolsCapabilities = { | ||
'applitools:eyesServerUrl': session.serverUrl, | ||
'applitools:eyesServerUrl': session.eyesServerUrl, | ||
'applitools:apiKey': session.apiKey, | ||
'applitools:x-tunnel-id-0': session.tunnelId, | ||
'applitools:timeout': timeout, | ||
'applitools:inactivityTimeout': inactivityTimeout, | ||
'applitools:timeout': (_c = extractCapability(requestBody, 'applitools:timeout')) !== null && _c !== void 0 ? _c : egTimeout, | ||
'applitools:inactivityTimeout': (_d = extractCapability(requestBody, 'applitools:inactivityTimeout')) !== null && _d !== void 0 ? _d : egInactivityTimeout, | ||
}; | ||
@@ -112,44 +121,45 @@ if (requestBody.capabilities) { | ||
logger.log('Request body has modified:', requestBody); | ||
// const queue = queues.get(`${session.serverUrl}:${session.apiKey}`) ?? [] | ||
// queue.push({request, response, requestBody}) | ||
// if (queue.length === 1) { | ||
// queues.set(`${session.serverUrl}:${session.apiKey}`, queue) | ||
// return | ||
// } | ||
return proxyNewSession({ session, requestBody, request, response, logger }); | ||
} | ||
async function proxyNewSession({ session, requestBody, request, response, logger, }) { | ||
var _a, _b, _c, _d; | ||
let attempt = 0; | ||
while (true) { | ||
const proxyResponse = await (0, proxy_1.proxy)({ | ||
let queue = queues.get(`${session.eyesServerUrl}:${session.apiKey}`); | ||
if (!queue) { | ||
queue = (0, queue_1.makeQueue)({ logger }); | ||
queues.set(`${session.eyesServerUrl}:${session.apiKey}`, queue); | ||
} | ||
request.socket.on('close', () => queue.cancel(task)); | ||
await queue.run(task); | ||
async function task(signal, attempt = 0) { | ||
var _a, _b, _c, _d; | ||
// do not start the task if it is already aborted | ||
if (signal.aborted) | ||
return; | ||
const proxyResponse = await proxyRequest({ | ||
request, | ||
response, | ||
options: { target: forwardingUrl, body: requestBody, handle: true }, | ||
options: { body: JSON.stringify(requestBody), handle: false, signal }, | ||
logger, | ||
}); | ||
const responseBody = | ||
// @ts-ignore | ||
(_a = proxyResponse.body) !== null && _a !== void 0 ? _a : (await (0, raw_body_1.default)(proxyResponse, 'utf-8').then(body => (body ? JSON.parse(body) : undefined))); | ||
if (!responseBody) { | ||
response.writeHead(proxyResponse.statusCode, proxyResponse.headers).end(); | ||
return logger.log(`Response has no body`); | ||
// to decide if we get an expected response we might already parse the body | ||
const responseBody = (_a = proxyResponse.body) !== null && _a !== void 0 ? _a : (await (0, parse_body_1.parseBody)(proxyResponse)); | ||
logger.log(`Response was intercepted with body:`, responseBody); | ||
if (RETRY_ERROR_CODES.includes((_c = (_b = responseBody.value) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.appliErrorCode)) { | ||
queue.cork(); | ||
// after query is corked the task might be aborted | ||
if (signal.aborted) | ||
return; | ||
await utils.general.sleep(RETRY_BACKOFF[Math.min(attempt, RETRY_BACKOFF.length - 1)]); | ||
logger.log(`Retrying sending the request (attempt ${attempt})`); | ||
return task(signal, attempt + 1); | ||
} | ||
logger.log(`Response was intercepted with body:`, responseBody); | ||
if (!RETRY_ERROR_CODES.includes((_c = (_b = responseBody.value) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.appliErrorCode)) { | ||
else { | ||
queue.uncork(); | ||
if ((_d = responseBody.value) === null || _d === void 0 ? void 0 : _d.sessionId) | ||
sessions.set(responseBody.value.sessionId, session); | ||
response.writeHead(proxyResponse.statusCode, proxyResponse.headers).end(JSON.stringify(responseBody)); | ||
response.end(JSON.stringify(responseBody)); | ||
return; | ||
} | ||
await utils.general.sleep(RETRY_BACKOFF[Math.min(attempt, RETRY_BACKOFF.length - 1)]); | ||
attempt += 1; | ||
request.removeAllListeners(); | ||
logger.log(`Retrying sending the request (attempt ${attempt})`); | ||
} | ||
} | ||
async function handleStopSession({ request, response, logger, }) { | ||
async function deleteSession({ request, response, logger, }) { | ||
const sessionId = request.url.split('/').pop(); | ||
logger.log(`Request was intercepted with sessionId:`, sessionId); | ||
await (0, proxy_1.proxy)({ request, response, options: { target: forwardingUrl }, logger }); | ||
await proxyRequest({ request, response, logger }); | ||
const session = sessions.get(sessionId); | ||
@@ -156,0 +166,0 @@ if (session.tunnelId) { |
@@ -29,72 +29,102 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.proxy = void 0; | ||
const stream_1 = require("stream"); | ||
const http_proxy_1 = require("http-proxy"); | ||
const raw_body_1 = __importDefault(require("raw-body")); | ||
exports.makeProxy = void 0; | ||
const http_1 = require("http"); | ||
const https_1 = require("https"); | ||
const dns_1 = require("dns"); | ||
const proxy_agent_1 = __importDefault(require("proxy-agent")); | ||
const utils = __importStar(require("@applitools/utils")); | ||
// TODO: get rid of http-proxy library | ||
async function proxy({ request, response, options, logger, }) { | ||
const proxy = (0, http_proxy_1.createProxy)(); | ||
const content = options.body ? JSON.stringify(options.body) : undefined; | ||
const settings = { | ||
target: options.target, | ||
selfHandleResponse: true, | ||
ws: true, | ||
changeOrigin: true, | ||
buffer: content | ||
? new stream_1.Readable({ | ||
read() { | ||
this.push(content); | ||
this.push(null); | ||
}, | ||
}) | ||
: undefined, | ||
headers: content ? Object.assign(Object.assign({}, options.headers), { 'Content-Length': Buffer.byteLength(content).toString() }) : options.headers, | ||
}; | ||
return new Promise((resolve, _reject) => { | ||
// prevent modification of the request headers in the http-proxy library | ||
Object.freeze(request.headers); | ||
proxy.on('proxyRes', async (proxyResponse) => { | ||
let responseBody; | ||
if (proxyResponse.statusCode >= 400) { | ||
const rawBody = await (0, raw_body_1.default)(proxyResponse, 'utf-8'); | ||
try { | ||
responseBody = rawBody ? JSON.parse(rawBody) : undefined; | ||
function makeProxy(defaultOptions) { | ||
const resolveUrl = (defaultOptions === null || defaultOptions === void 0 ? void 0 : defaultOptions.resolveUrls) ? makeResolveUrl() : (url) => url; | ||
return async function proxyRequest({ request, response, options, logger, }) { | ||
var _a, _b, _c, _d, _e; | ||
options = Object.assign(Object.assign({}, defaultOptions), options); | ||
const isProxyRequest = !options.url && /^http/.test(request.url); | ||
const requestOptions = { | ||
url: isProxyRequest | ||
? request.url | ||
: new URL(`.${request.url}` /* relative path */, await resolveUrl(options.url, { logger })), | ||
method: (_a = options.method) !== null && _a !== void 0 ? _a : request.method, | ||
headers: Object.assign(Object.assign({}, request.headers), options.headers), | ||
body: options.body, | ||
proxy: options.proxy, | ||
signal: options.signal, | ||
}; | ||
requestOptions.headers.host = new URL(isProxyRequest ? request.url : options.url).host; | ||
if (requestOptions.body && !utils.types.isFunction(requestOptions.body, 'pipe')) { | ||
requestOptions.headers['Content-Length'] = Buffer.byteLength(requestOptions.body).toString(); | ||
} | ||
else { | ||
requestOptions.body = request; | ||
} | ||
const modifiedRequestOptions = (_c = (await ((_b = options.modifyRequest) === null || _b === void 0 ? void 0 : _b.call(options, requestOptions)))) !== null && _c !== void 0 ? _c : requestOptions; | ||
let proxyResponse; | ||
for (let attempt = 1; attempt <= 10; ++attempt) { | ||
try { | ||
proxyResponse = await send(modifiedRequestOptions); | ||
if (!(await ((_d = options.shouldRetry) === null || _d === void 0 ? void 0 : _d.call(options, proxyResponse)))) | ||
break; | ||
logger.error(`Attempt (${attempt}) to proxy request finished with unexpected status ${proxyResponse.statusCode}`); | ||
await utils.general.sleep((_e = options.retryTimeout) !== null && _e !== void 0 ? _e : 5000); | ||
} | ||
catch (error) { | ||
if (utils.types.instanceOf(error, 'AbortError')) | ||
throw error; | ||
logger.error(`Attempt (${attempt}) to proxy request failed with error`, error); | ||
if (attempt + 1 <= 10) | ||
throw error; | ||
} | ||
} | ||
if (request.httpVersion === '1.0') { | ||
proxyResponse.headers.connection = proxyResponse.headers.connection || 'close'; | ||
} | ||
else if (request.httpVersion !== '2.0' && !proxyResponse.headers.connection) { | ||
proxyResponse.headers.connection = request.headers.connection || 'keep-alive'; | ||
} | ||
response.sendDate = false; | ||
response.writeHead(proxyResponse.statusCode, proxyResponse.headers); | ||
if (options.handle !== false) | ||
proxyResponse.pipe(response); | ||
return proxyResponse; | ||
async function send(requestOptions) { | ||
const sendRequest = new URL(requestOptions.url).protocol === 'https:' ? https_1.request : http_1.request; | ||
return new Promise((resolve, reject) => { | ||
const request = sendRequest(requestOptions.url, Object.assign(Object.assign({}, requestOptions), { agent: new proxy_agent_1.default(requestOptions.proxy) })); | ||
request.on('error', reject); | ||
request.on('response', resolve); | ||
if (requestOptions.body && utils.types.isFunction(requestOptions.body, 'pipe')) { | ||
requestOptions.body.pipe(request); | ||
} | ||
catch (_a) { | ||
responseBody = null; | ||
else { | ||
request.write(requestOptions.body); | ||
request.end(); | ||
} | ||
if (!(responseBody === null || responseBody === void 0 ? void 0 : responseBody.value)) { | ||
logger.error(`Request respond with unexpected status and body (status ${proxyResponse.statusCode})`, rawBody); | ||
logger.log(`Retry on a network error`); | ||
retry(); | ||
return; | ||
} | ||
} | ||
if (!options.handle) { | ||
response.writeHead(proxyResponse.statusCode, proxyResponse.headers); | ||
if (responseBody) | ||
response.end(JSON.stringify(responseBody)); | ||
else | ||
proxyResponse.pipe(response); | ||
} | ||
// @ts-ignore | ||
proxyResponse.body = responseBody; | ||
resolve(proxyResponse); | ||
}); | ||
proxy.web(request, response, settings, err => { | ||
logger.error(`Unexpected error during proxying`, err); | ||
logger.log(`Retry on a unxpected error`); | ||
retry(); | ||
}); | ||
}); | ||
async function retry() { | ||
await utils.general.sleep(3000); | ||
proxy.web(request, response, settings, err => { | ||
logger.error(`Unexpected error during proxying`, err); | ||
logger.log(`Retry on a unxpected error`); | ||
retry(); | ||
}); | ||
} | ||
}); | ||
} | ||
}; | ||
} | ||
exports.proxy = proxy; | ||
exports.makeProxy = makeProxy; | ||
function makeResolveUrl() { | ||
const resolvedHosts = new Map(); | ||
return async function resolve(unresolvedUrl, { logger }) { | ||
const url = new URL(unresolvedUrl); | ||
let hostname = resolvedHosts.get(url.hostname); | ||
if (!hostname) { | ||
hostname = new Promise(resolve => { | ||
(0, dns_1.resolve)(url.hostname, (err, addresses) => { | ||
if (!err) { | ||
resolvedHosts.set(url.hostname, addresses[0]); | ||
logger.log(`Addresses were successfully resolved for url ${url.href} - ${addresses.join(', ')}`); | ||
resolve(addresses[0]); | ||
} | ||
else { | ||
logger.error(`Failed to resolve address for url ${url.href}`, err); | ||
resolve(url.hostname); | ||
} | ||
}); | ||
}); | ||
resolvedHosts.set(url.hostname, hostname); | ||
} | ||
url.hostname = await hostname; | ||
return url; | ||
}; | ||
} |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.makeQueue = void 0; | ||
function makeQueue({ _logger }) { | ||
const queue = []; | ||
return { run }; | ||
const abort_controller_1 = require("abort-controller"); | ||
const utils = __importStar(require("@applitools/utils")); | ||
function makeQueue(_options) { | ||
const pool = []; | ||
const map = new Map(); | ||
let corked = false; | ||
return { | ||
get corked() { | ||
return corked; | ||
}, | ||
run, | ||
cancel, | ||
cork, | ||
uncork, | ||
}; | ||
async function run(task) { | ||
// if (que) | ||
if (queue.length === 1) { | ||
const handle = {}; | ||
handle.running = false; | ||
handle.start = async () => { | ||
if (handle.running) | ||
return; | ||
handle.running = true; | ||
handle.controller = new abort_controller_1.AbortController(); | ||
try { | ||
return await task(); | ||
const result = await task(handle.controller.signal); | ||
if (handle.running) { | ||
pool.splice(pool.indexOf(handle), 1); | ||
handle.resolve(result); | ||
} | ||
} | ||
catch (error) { | ||
if (handle.running || !utils.types.instanceOf(error, 'AbortError')) | ||
handle.reject(error); | ||
} | ||
finally { | ||
return handle.promise; | ||
} | ||
} | ||
}; | ||
handle.abort = () => { | ||
if (!handle.running) | ||
return; | ||
handle.running = false; | ||
handle.controller.abort(); | ||
}; | ||
handle.promise = new Promise((resolve, reject) => { | ||
handle.resolve = resolve; | ||
handle.reject = reject; | ||
}); | ||
pool.push(handle); | ||
map.set(task, handle); | ||
if (!corked) | ||
handle.start(); | ||
return handle.promise; | ||
} | ||
function cancel(task) { | ||
const handle = map.get(task); | ||
if (!handle) | ||
return; | ||
handle.abort(); | ||
map.delete(task); | ||
pool.splice(pool.indexOf(handle), 1); | ||
} | ||
function cork() { | ||
if (corked) | ||
return; | ||
corked = true; | ||
pool.slice(1).forEach(handle => handle.abort()); | ||
} | ||
function uncork() { | ||
if (!corked) | ||
return; | ||
corked = false; | ||
pool.forEach(handle => handle.start()); | ||
} | ||
} | ||
exports.makeQueue = makeQueue; |
@@ -33,9 +33,9 @@ "use strict"; | ||
10000); | ||
function makeTunnelManager({ tunnelUrl, logger }) { | ||
function makeTunnelManager({ egTunnelUrl, logger }) { | ||
return { createTunnel, deleteTunnel }; | ||
async function createTunnel({ apiKey, serverUrl }) { | ||
async function createTunnel({ eyesServerUrl, apiKey }) { | ||
var _a, _b; | ||
const request = new node_fetch_1.Request(`${tunnelUrl}/tunnels`, { | ||
const request = new node_fetch_1.Request(`${egTunnelUrl}/tunnels`, { | ||
method: 'POST', | ||
headers: new node_fetch_1.Headers(Object.assign({ 'x-eyes-api-key': apiKey }, (serverUrl ? { 'x-eyes-server-url': serverUrl } : {}))), | ||
headers: new node_fetch_1.Headers(Object.assign({ 'x-eyes-api-key': apiKey }, (eyesServerUrl ? { 'x-eyes-server-url': eyesServerUrl } : {}))), | ||
}); | ||
@@ -57,7 +57,7 @@ let attempt = 0; | ||
} | ||
async function deleteTunnel({ tunnelId, apiKey, serverUrl, }) { | ||
async function deleteTunnel({ tunnelId, eyesServerUrl, apiKey, }) { | ||
var _a, _b; | ||
const request = new node_fetch_1.Request(`${tunnelUrl}/tunnels/${tunnelId}`, { | ||
const request = new node_fetch_1.Request(`${egTunnelUrl}/tunnels/${tunnelId}`, { | ||
method: 'DELETE', | ||
headers: new node_fetch_1.Headers(Object.assign({ 'x-eyes-api-key': apiKey }, (serverUrl ? { 'x-eyes-server-url': serverUrl } : {}))), | ||
headers: new node_fetch_1.Headers(Object.assign({ 'x-eyes-api-key': apiKey }, (eyesServerUrl ? { 'x-eyes-server-url': eyesServerUrl } : {}))), | ||
}); | ||
@@ -64,0 +64,0 @@ const response = await (0, node_fetch_1.default)(request); |
{ | ||
"name": "@applitools/execution-grid-client", | ||
"version": "1.1.8", | ||
"version": "1.1.9", | ||
"description": "", | ||
@@ -55,4 +55,5 @@ "license": "SEE LICENSE IN LICENSE", | ||
"@applitools/utils": "1.3.0", | ||
"http-proxy": "1.18.1", | ||
"abort-controller": "3.0.0", | ||
"node-fetch": "2.6.7", | ||
"proxy-agent": "5.0.0", | ||
"raw-body": "2.5.1", | ||
@@ -63,3 +64,2 @@ "yargs": "17.4.1" | ||
"@applitools/bongo": "^2.0.3", | ||
"@types/http-proxy": "^1.17.8", | ||
"@types/mocha": "^9.1.1", | ||
@@ -66,0 +66,0 @@ "@types/node": "^17.0.31", |
@@ -5,10 +5,14 @@ /// <reference types="node" /> | ||
export declare type ServerOptions = { | ||
egServerUrl?: string; | ||
egTunnelUrl?: string; | ||
egTimeout?: number | string; | ||
egInactivityTimeout?: number | string; | ||
proxyUrl?: string; | ||
eyesServerUrl?: string; | ||
apiKey?: string; | ||
port?: number; | ||
forwardingUrl?: string; | ||
tunnelUrl?: string; | ||
serverUrl?: string; | ||
apiKey?: string; | ||
logger?: Logger & any; | ||
resolveUrls?: boolean; | ||
logger?: Logger; | ||
}; | ||
export declare function makeServer({ port, forwardingUrl, tunnelUrl, serverUrl, apiKey, logger, }?: ServerOptions): Promise<{ | ||
export declare function makeServer({ egServerUrl, egTunnelUrl, egTimeout, egInactivityTimeout, proxyUrl, eyesServerUrl, apiKey, port, resolveUrls, logger, }?: ServerOptions): Promise<{ | ||
url: string; | ||
@@ -15,0 +19,0 @@ port: number; |
/// <reference types="node" /> | ||
import { type Readable } from 'stream'; | ||
import { type AbortSignal } from 'abort-controller'; | ||
import { type Logger } from '@applitools/logger'; | ||
import { type IncomingMessage, type ServerResponse } from 'http'; | ||
import { type Logger } from '@applitools/logger'; | ||
declare type ProxyOptions = { | ||
target: string; | ||
declare type RequestOptions = { | ||
url?: URL | string; | ||
method: string; | ||
headers?: Record<string, string | string[]>; | ||
body?: string | Buffer | Readable; | ||
proxy?: string; | ||
signal?: AbortSignal; | ||
}; | ||
declare type ProxyOptions = Partial<RequestOptions> & { | ||
handle?: boolean; | ||
body?: Record<string, any>; | ||
headers?: Record<string, string>; | ||
modifyRequest?: (options: RequestOptions) => Promise<RequestOptions> | RequestOptions; | ||
shouldRetry?: (proxyResponse: IncomingMessage) => Promise<boolean> | boolean; | ||
retryTimeout?: number; | ||
}; | ||
export declare function proxy({ request, response, options, logger, }: { | ||
export declare function makeProxy(defaultOptions?: Partial<ProxyOptions> & { | ||
resolveUrls?: boolean; | ||
}): ({ request, response, options, logger, }: { | ||
request: IncomingMessage; | ||
response: ServerResponse; | ||
options: ProxyOptions; | ||
options?: ProxyOptions; | ||
logger: Logger; | ||
}): Promise<IncomingMessage>; | ||
}) => Promise<IncomingMessage>; | ||
export {}; |
import { type Logger } from '@applitools/logger'; | ||
import { type AbortSignal } from 'abort-controller'; | ||
export declare type Queue = { | ||
run<TResult>(task: () => Promise<TResult>): Promise<TResult>; | ||
readonly corked: boolean; | ||
run<TResult>(task: Task<TResult>): Promise<TResult>; | ||
cancel(task: (signal: AbortSignal) => Promise<any>): void; | ||
cork(): void; | ||
uncork(): void; | ||
}; | ||
export declare function makeQueue({ _logger }: { | ||
_logger: Logger; | ||
declare type Task<TResult> = (signal: AbortSignal) => Promise<TResult>; | ||
export declare function makeQueue(_options: { | ||
logger: Logger; | ||
}): Queue; | ||
export {}; |
import { type Logger } from '@applitools/logger'; | ||
export declare function makeTunnelManager({ tunnelUrl, logger }: { | ||
tunnelUrl?: string; | ||
export declare function makeTunnelManager({ egTunnelUrl, logger }: { | ||
egTunnelUrl?: string; | ||
logger: Logger; | ||
}): { | ||
createTunnel: ({ apiKey, serverUrl }: { | ||
createTunnel: ({ eyesServerUrl, apiKey }: { | ||
eyesServerUrl?: string; | ||
apiKey: string; | ||
serverUrl?: string; | ||
}) => Promise<string>; | ||
deleteTunnel: ({ tunnelId, apiKey, serverUrl, }: { | ||
deleteTunnel: ({ tunnelId, eyesServerUrl, apiKey, }: { | ||
tunnelId: string; | ||
eyesServerUrl?: string; | ||
apiKey: string; | ||
serverUrl?: string; | ||
}) => Promise<void>; | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
47251
20
17
680
7
7
4
+ Addedabort-controller@3.0.0
+ Addedproxy-agent@5.0.0
+ Added@tootallnate/once@1.1.2(transitive)
+ Addedabort-controller@3.0.0(transitive)
+ Addedacorn@8.14.0(transitive)
+ Addedacorn-walk@8.3.4(transitive)
+ Addedagent-base@6.0.2(transitive)
+ Addedast-types@0.13.4(transitive)
+ Addedcore-util-is@1.0.3(transitive)
+ Addeddata-uri-to-buffer@3.0.1(transitive)
+ Addeddebug@4.3.7(transitive)
+ Addeddeep-is@0.1.4(transitive)
+ Addeddegenerator@3.0.4(transitive)
+ Addedescodegen@1.14.3(transitive)
+ Addedesprima@4.0.1(transitive)
+ Addedestraverse@4.3.0(transitive)
+ Addedesutils@2.0.3(transitive)
+ Addedevent-target-shim@5.0.1(transitive)
+ Addedfast-levenshtein@2.0.6(transitive)
+ Addedfile-uri-to-path@2.0.0(transitive)
+ Addedfs-extra@8.1.0(transitive)
+ Addedftp@0.3.10(transitive)
+ Addedget-uri@3.0.2(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedhttp-proxy-agent@4.0.1(transitive)
+ Addedhttps-proxy-agent@5.0.1(transitive)
+ Addedip@1.1.9(transitive)
+ Addedip-address@9.0.5(transitive)
+ Addedisarray@0.0.1(transitive)
+ Addedjsbn@1.1.0(transitive)
+ Addedjsonfile@4.0.0(transitive)
+ Addedlevn@0.3.0(transitive)
+ Addedlru-cache@5.1.1(transitive)
+ Addedms@2.1.3(transitive)
+ Addednetmask@2.0.2(transitive)
+ Addedoptionator@0.8.3(transitive)
+ Addedpac-proxy-agent@5.0.0(transitive)
+ Addedpac-resolver@5.0.1(transitive)
+ Addedprelude-ls@1.1.2(transitive)
+ Addedproxy-agent@5.0.0(transitive)
+ Addedproxy-from-env@1.1.0(transitive)
+ Addedreadable-stream@1.1.14(transitive)
+ Addedsmart-buffer@4.2.0(transitive)
+ Addedsocks@2.8.3(transitive)
+ Addedsocks-proxy-agent@5.0.1(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addedsprintf-js@1.1.3(transitive)
+ Addedstring_decoder@0.10.31(transitive)
+ Addedtslib@2.8.1(transitive)
+ Addedtype-check@0.3.2(transitive)
+ Addeduniversalify@0.1.2(transitive)
+ Addedvm2@3.9.19(transitive)
+ Addedword-wrap@1.2.5(transitive)
+ Addedxregexp@2.0.0(transitive)
+ Addedyallist@3.1.1(transitive)
- Removedhttp-proxy@1.18.1
- Removedeventemitter3@4.0.7(transitive)
- Removedfollow-redirects@1.15.9(transitive)
- Removedhttp-proxy@1.18.1(transitive)
- Removedrequires-port@1.0.0(transitive)