Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added proxy complience #914

Merged
merged 10 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
node-version: [12, 14, 16, 18, 20]
udarrr marked this conversation as resolved.
Show resolved Hide resolved
node-version: [14, 16, 18, 20]
java-version: [11]
include:
- os: macos-latest
Expand Down
3 changes: 3 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 9.6.0 (2023-10-21)
udarrr marked this conversation as resolved.
Show resolved Hide resolved
* added proxy complience

# 9.2.3 (2023-10-21)
* fixed onCancel bug with got

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Node.js Selenium Standalone [![Test](https://github.com/webdriverio/selenium-standalone/actions/workflows/test.yml/badge.svg?branch=main&event=push)](https://github.com/webdriverio/selenium-standalone/actions/workflows/test.yml) ![Supported node versions](https://img.shields.io/badge/node-12%2C%2013%2C%2014%2C%2015%2C%2016%2C%2017%2C%2018%2C%2019%2C%2020-green)
Node.js Selenium Standalone [![Test](https://github.com/webdriverio/selenium-standalone/actions/workflows/test.yml/badge.svg?branch=main&event=push)](https://github.com/webdriverio/selenium-standalone/actions/workflows/test.yml) ![Supported node versions](https://img.shields.io/badge/node-%2014%2C%2016%2C%2018%2C%2020-green)
===========================

> A node based CLI library for launching [Selenium](http://www.seleniumhq.org/download/) with [WebDriver](https://w3c.github.io/webdriver/) support.
Expand Down
4 changes: 4 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,7 @@ since 9.1.0 it's been checked and killed automatically
## Set `selenium-standalone` Version as NodeJS environment parameter

You can set any version by `process.env.SELENIUM_VERSION=3.141.59` before starting selenium-standalone. Default values are here: [lib/default-config.js](../lib/default-config.js)

## Use the package behind corparate proxy

Should be specified `process.env.HTTP_PROXY=http://proxy-url:port` and `process.env.HTTPS_PROXY=http://proxy-url:port` or the same system envirement variables `HTTP_PROXY=http://proxy-url:port`, `HTTPS_PROXY=http://proxy-url:port`
3 changes: 2 additions & 1 deletion lib/check-started.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module.exports = checkStarted;

const { default: got } = require('got');
const { sleep } = require('./delay');
const { getProxtAgent } = require('./proxyManager');

async function checkStarted(selenium, seleniumStatusUrl) {
const cpState = {
Expand Down Expand Up @@ -49,7 +50,7 @@ async function checkStarted(selenium, seleniumStatusUrl) {

try {
// server has one minute to start
await got(seleniumStatusUrl, gotOptions);
await got(seleniumStatusUrl, { ...getProxtAgent(seleniumStatusUrl), ...gotOptions });
selenium.removeListener('exit', errorIfNeverStarted);
return null;
} catch (err) {
Expand Down
50 changes: 28 additions & 22 deletions lib/compute-download-urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const {
getIeDriverArchitectureOld,
getFirefoxDriverArchitectureOld,
} = require('./platformDetection');
const microsoftEdgeReleases = require('./microsoft-edge-releases');
const { getProxtAgent } = require('./proxyManager');

const urls = {
selenium: '%s/%s/selenium-server-standalone-%s.jar',
Expand Down Expand Up @@ -188,8 +190,6 @@ async function computeDownloadUrls(options) {
return downloadUrls;
}

const microsoftEdgeReleases = require('./microsoft-edge-releases');

function getEdgeDriverUrl(version) {
const release = microsoftEdgeReleases[version];
if (!release) {
Expand All @@ -209,7 +209,7 @@ async function chromiumEdgeBundleAvailable(opts) {
getChromiumEdgeDriverArchitectureOld(opts.drivers.chromiumedge.platform, opts.drivers.chromiumedge.version)
);
try {
await got.head(url, { timeout: 10000 });
await got.head(url, { ...getProxtAgent(url), timeout: 10000 });
} catch (_) {
return false;
}
Expand Down Expand Up @@ -247,7 +247,7 @@ async function resolveLatestVersion(opts, browserDriver, url) {

async function getLatestChromium(opts, browserDriver, url) {
try {
const response = await got(url, { timeout: 10000 });
const response = await got(url, { ...getProxtAgent(url), timeout: 10000 });
// edgewebdriver latest version file contains invalid characters
const version = response.body.replace(/\r|\n/g, '').replace(/[^\d|.]/g, '');

Expand All @@ -260,10 +260,10 @@ async function getLatestChromium(opts, browserDriver, url) {
}

async function getLatestGeckodriver(opts, browserDriver, url) {
const response = await got(url, { timeout: 10000, responseType: 'json' });
if (typeof response.body.name === 'string' && response.body.name) {
const response = await got(url, { ...getProxtAgent(url), timeout: 10000 }).json();
if (typeof response.name === 'string' && response.name) {
// eslint-disable-next-line no-param-reassign
opts.drivers[browserDriver].version = response.body.name;
opts.drivers[browserDriver].version = response.name;
return true;
}
}
Expand All @@ -277,15 +277,18 @@ function resolveDownloadPath(platform, buildId) {
}

async function getLastChromedriverVersionFromMajor(version) {
const url = 'https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json';
const response = await got({
method: 'get',
url: 'https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json',
responseType: 'json',
headers: {
'Content-Type': 'application/json',
...getProxtAgent(url),
...{
method: 'get',
url: url,
headers: {
'Content-Type': 'application/json',
},
},
});
const versionsWithMajor = response.body.versions.filter(
}).json();
const versionsWithMajor = response.versions.filter(
(f) =>
validateMajorVersionPrefix(f.version) === validateMajorVersionPrefix(version) && 'chromedriver' in f.downloads
);
Expand All @@ -299,18 +302,21 @@ async function getLastChromedriverVersionFromMajor(version) {
}

async function getLatestChromeVersion(possibleChanel) {
const url = 'https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json';
const response = await got({
method: 'get',
url: 'https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json',
responseType: 'json',
headers: {
'Content-Type': 'application/json',
...getProxtAgent(url),
...{
method: 'get',
url: url,
headers: {
'Content-Type': 'application/json',
},
},
});
const channel = Object.keys(response.body.channels).find((i) => i.toLowerCase() === possibleChanel.toLowerCase());
}).json();
const channel = Object.keys(response.channels).find((i) => i.toLowerCase() === possibleChanel.toLowerCase());

try {
return response.body.channels[channel].version;
return response.channels[channel].version;
} catch (err) {
console.log();
throw new Error(`channel can't be - ${possibleChanel}, possible only Stable, Beta, Dev, Canary`);
Expand Down
2 changes: 2 additions & 0 deletions lib/install-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const { default: got } = require('got');
const debug = require('debug')('selenium-standalone:install');
const { logError } = require('./log-error');
const md5 = require('md5');
const { getProxtAgent } = require('./proxyManager');

const installers = ['selenium', 'chrome', 'ie', 'firefox', 'edge', 'chromiumedge'];

Expand Down Expand Up @@ -107,6 +108,7 @@ async function isUpToDate(url, file, pathToFile) {
}
try {
const response = await got.head(url, {
...getProxtAgent(url),
timeout: 2500,
});
if (response.headers['content-length'] === `${fs.statSync(pathToFile).size}`) {
Expand Down
3 changes: 2 additions & 1 deletion lib/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const {
} = require('./install-utils');
const { checkArgs } = require('./check-args');
const { logError } = require('./log-error');
const { getProxtAgent } = require('./proxyManager');

/**
* used ONLY to deal with progress bar.
Expand Down Expand Up @@ -287,7 +288,7 @@ async function install(_opts) {

async function getDownloadStream(downloadUrl) {
let prevTransferred = 0;
const downloadStream = got.stream(downloadUrl, { ...requestOpts, isStream: true });
const downloadStream = got.stream(downloadUrl, { ...getProxtAgent(downloadUrl), ...requestOpts, isStream: true });
return await new Promise((resolve, reject) => {
downloadStream
.once('response', () => {
Expand Down
19 changes: 19 additions & 0 deletions lib/proxyManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { HttpsProxyAgent } = require('https-proxy-agent');
const { HttpProxyAgent } = require('http-proxy-agent');
/**
* Returns proxy agent if exist.
* @param {string} url
* @returns {any}
*/
function getProxtAgent(url) {
if (url.startsWith('http:') && process.env.HTTP_PROXY) {
const httpProxyAgent = new HttpProxyAgent(process.env.HTTP_PROXY);
return { agent: { http: httpProxyAgent } };
}
if (url.startsWith('https:') && process.env.HTTPS_PROXY) {
const httpProxyAgent = new HttpsProxyAgent(process.env.HTTPS_PROXY);
return { agent: { https: httpProxyAgent } };
}
return {};
}
module.exports = { getProxtAgent };
10 changes: 3 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
"release:patch": "npm run release -- patch",
"release:minor": "npm run release -- minor",
"release:major": "npm run release -- major",
"lint": "eslint --ignore-path .gitignore ."
"lint": "eslint --ignore-path .gitignore .",
"lint:fix": "eslint --fix --ignore-path .gitignore ."
},
"engines": {
"node": ">=12"
"node": ">=14"
},
"bin": {
"selenium-standalone": "./bin/selenium-standalone"
Expand Down Expand Up @@ -49,6 +50,8 @@
"find-process": "^1.4.7",
"fkill": "^7.2.1",
"got": "^11.8.6",
"http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.4",
"is-port-reachable": "^3.0.0",
"lodash.mapvalues": "^4.6.0",
"lodash.merge": "^4.6.2",
Expand Down
73 changes: 38 additions & 35 deletions test/no-reinstall.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,47 @@ const selenium = require('..');

const targetDir = path.join(__dirname, '..', '.selenium');

describe('when files are installed', () => {
it('should not reinstall them', async function () {
this.timeout(120000);
if (process.platform !== 'darwin') {
describe('when files are installed', () => {
it('should not reinstall them', async function () {
this.timeout(120000);

/**
* Recursively find files in the given directory
* @param {string} dirname
* @param {string[]} files
* @returns {string[]}
*/
function walk(dirname, files = []) {
fs.readdirSync(dirname).forEach((name) => {
const filepath = path.join(dirname, name);
if (fs.statSync(filepath).isDirectory()) {
walk(filepath, files);
} else {
files.push(filepath);
}
});
return files;
}
const installedFiles = walk(targetDir);
/**
* Recursively find files in the given directory
* @param {string} dirname
* @param {string[]} files
* @returns {string[]}
*/
function walk(dirname, files = []) {
fs.readdirSync(dirname).forEach((name) => {
const filepath = path.join(dirname, name);
if (fs.statSync(filepath).isDirectory()) {
walk(filepath, files);
} else {
files.push(filepath);
}
});
return files;
}
const installedFiles = walk(targetDir);

// Get last modified time of files that should already be installed in
// the .selenium directory.
const mtimes = installedFiles.reduce((acc, filepath) => {
acc[filepath] = fs.statSync(filepath).mtime.getTime();
return acc;
}, {});
// Get last modified time of files that should already be installed in
// the .selenium directory.
const mtimes = installedFiles.reduce((acc, filepath) => {
acc[filepath] = fs.statSync(filepath).mtime.getTime();
return acc;
}, {});

// Compare last modified time of files after running the installation
// again. It shouldn't download any files, otherwise it fails.
await selenium.install();
// Compare last modified time of files after running the installation
// again. It shouldn't download any files, otherwise it fails.
await selenium.install();

const isModified = !installedFiles.every((filepath) => {
return mtimes[filepath] === fs.statSync(filepath).mtime.getTime();
});
const mtimesAfter = installedFiles.reduce((acc, filepath) => {
acc[filepath] = fs.statSync(filepath).mtime.getTime();
return acc;
}, {});

assert.strictEqual(isModified, false, 'It should not have reinstalled files');
assert.strictEqual(JSON.stringify(mtimes), JSON.stringify(mtimesAfter), 'It should not have reinstalled files');
});
});
});
}
Loading
Loading