Skip to content

Commit 6e4cd09

Browse files
authored
fix: skip proxy-chain (#53)
1 parent 9509172 commit 6e4cd09

File tree

14 files changed

+302
-141
lines changed

14 files changed

+302
-141
lines changed

.github/workflows/check.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
strategy:
1616
matrix:
1717
os: [ubuntu-latest, windows-latest]
18-
node-version: [10, 12, 14]
18+
node-version: [15, 16]
1919

2020
steps:
2121
-
@@ -43,10 +43,10 @@ jobs:
4343
-
4444
uses: actions/checkout@v2
4545
-
46-
name: Use Node.js 14
46+
name: Use Node.js 16
4747
uses: actions/setup-node@v1
4848
with:
49-
node-version: 14
49+
node-version: 16
5050
-
5151
name: Install Dependencies
5252
run: npm install

.github/workflows/release.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
strategy:
2020
matrix:
2121
os: [ubuntu-latest, windows-latest]
22-
node-version: [10, 12, 14]
22+
node-version: [15, 16]
2323

2424
steps:
2525
-
@@ -47,10 +47,10 @@ jobs:
4747
-
4848
uses: actions/checkout@v2
4949
-
50-
name: Use Node.js 14
50+
name: Use Node.js 16
5151
uses: actions/setup-node@v1
5252
with:
53-
node-version: 14
53+
node-version: 16
5454
-
5555
name: Install Dependencies
5656
run: npm install
@@ -70,7 +70,7 @@ jobs:
7070
-
7171
uses: actions/setup-node@v1
7272
with:
73-
node-version: 14
73+
node-version: 16
7474
registry-url: https://registry.npmjs.org/
7575
-
7676
name: Install Dependencies

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
3.0.0 / 2021/10/17
2+
====================
3+
- fix: skip proxy-chain #53
4+
15
2.0.4 / 2021/10/05
26
====================
37
- fix `proxyUrl` in incognito context (#51), closes apify/apify-js#1195

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
{
22
"name": "browser-pool",
3-
"version": "2.0.4",
3+
"version": "3.0.0",
44
"description": "Rotate multiple browsers using popular automation libraries such as Playwright or Puppeteer.",
5+
"engines": {
6+
"node": ">=15.10.0"
7+
},
58
"main": "dist/index.js",
69
"module": "dist/index.mjs",
710
"types": "dist/index.d.ts",
@@ -45,7 +48,6 @@
4548
"nanoid": "^3.1.25",
4649
"ow": "^0.27.0",
4750
"p-limit": "^3.1.0",
48-
"proxy-chain": "^1.0.2",
4951
"tiny-typed-emitter": "^2.1.0",
5052
"tslib": "^2.3.1"
5153
},
@@ -66,6 +68,7 @@
6668
"jsdoc-to-markdown": "^7.0.1",
6769
"markdown-toc": "^1.2.0",
6870
"playwright": "^1.13.1",
71+
"proxy-chain": "^2.0.0-beta.0",
6972
"puppeteer": "^10.4.0",
7073
"rimraf": "^3.0.2",
7174
"ts-jest": "^27.0.4",

src/abstract-classes/browser-controller.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,6 @@ export abstract class BrowserController<
112112

113113
isActive = false;
114114

115-
supportsPageOptions = false;
116-
117115
activePages = 0;
118116

119117
totalPages = 0;

src/abstract-classes/browser-plugin.ts

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
import merge from 'lodash.merge';
2-
import { log } from '../logger';
32
import { LaunchContext, LaunchContextOptions } from '../launch-context';
43
import { BrowserController } from './browser-controller';
54
import { throwImplementationNeeded } from './utils';
65
import { UnwrapPromise } from '../utils';
76

8-
// eslint-disable-next-line @typescript-eslint/no-var-requires -- TODO: Type this module, and convert import
9-
const proxyChain = require('proxy-chain');
10-
117
/**
128
* Each plugin expects an instance of the object with the `.launch()` property.
139
* For Puppeteer, it is the `puppeteer` module itself, whereas for Playwright
@@ -177,44 +173,4 @@ export abstract class BrowserPlugin<
177173
protected abstract _createController(): BrowserController<Library, LibraryOptions, LaunchResult, NewPageOptions, NewPageResult> {
178174
throwImplementationNeeded('_createController');
179175
}
180-
181-
/**
182-
* Starts proxy-chain server - https://www.npmjs.com/package/proxy-chain#anonymizeproxyproxyurl-callback
183-
* @param proxyUrl Proxy URL with username and password.
184-
* @return URL of the anonymization proxy server that needs to be closed after the proxy is not used anymore.
185-
* @private
186-
*/
187-
protected async _getAnonymizedProxyUrl(proxyUrl: string): Promise<string> {
188-
try {
189-
return await proxyChain.anonymizeProxy(proxyUrl);
190-
} catch (e) {
191-
throw new Error(`BrowserPool: Could not anonymize proxyUrl: ${proxyUrl}. Reason: ${(e as Error).message}.`);
192-
}
193-
}
194-
195-
/**
196-
* @param proxyUrl Anonymized proxy URL of a running proxy server.
197-
* @private
198-
*/
199-
protected async _closeAnonymizedProxy(proxyUrl: string): Promise<boolean> {
200-
return proxyChain.closeAnonymizedProxy(proxyUrl, true).catch((err: Error) => {
201-
log.debug(`Could not close anonymized proxy server.\nCause:${err.message}`);
202-
});
203-
}
204-
205-
/**
206-
* Checks if proxy URL should be anonymized.
207-
* @private
208-
*/
209-
protected _shouldAnonymizeProxy(proxyUrl: string): boolean {
210-
const parsedProxyUrl = proxyChain.parseUrl(proxyUrl);
211-
if (parsedProxyUrl.username || parsedProxyUrl.password) {
212-
if (parsedProxyUrl.scheme !== 'http') {
213-
throw new Error('Invalid "proxyUrl" option: authentication is only supported for HTTP proxy type.');
214-
}
215-
return true;
216-
}
217-
218-
return false;
219-
}
220176
}

src/browser-pool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ export class BrowserPool<
451451
// eslint-disable-next-line dot-notation -- accessing private property
452452
await browserController['isActivePromise'];
453453

454-
const finalPageOptions = browserController.supportsPageOptions ? pageOptions : undefined;
454+
const finalPageOptions = browserController.launchContext.useIncognitoPages ? pageOptions : undefined;
455455
await this._executeHooks(this.prePageCreateHooks, pageId, browserController, finalPageOptions);
456456

457457
let page: PageReturn;

src/playwright/playwright-controller.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import type { Browser, BrowserType, Page } from 'playwright';
22
import { BrowserController, Cookie } from '../abstract-classes/browser-controller';
33

44
export class PlaywrightController extends BrowserController<BrowserType, Parameters<BrowserType['launch']>[0], Browser> {
5-
override supportsPageOptions = true;
5+
protected async _newPage(contextOptions?: Parameters<Browser['newPage']>[0]): Promise<Page> {
6+
if (contextOptions !== undefined && !this.launchContext.useIncognitoPages) {
7+
throw new Error('A new page can be created with provided context only when using incognito pages.');
8+
}
69

7-
protected async _newPage(pageOptions?: Parameters<Browser['newPage']>[0]): Promise<Page> {
8-
const page = await this.browser.newPage(pageOptions);
10+
const page = await this.browser.newPage(contextOptions);
911

1012
page.once('close', () => {
1113
this.activePages--;

src/playwright/playwright-plugin.ts

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ export class PlaywrightPlugin extends BrowserPlugin<BrowserType, Parameters<Brow
1212
protected async _launch(launchContext: LaunchContext<BrowserType>): Promise<PlaywrightBrowser> {
1313
const {
1414
launchOptions,
15-
anonymizedProxyUrl,
1615
useIncognitoPages,
1716
userDataDir,
1817
} = launchContext;
@@ -36,12 +35,6 @@ export class PlaywrightPlugin extends BrowserPlugin<BrowserType, Parameters<Brow
3635
browser = new PlaywrightBrowserWithPersistentContext({ browserContext, version: this._browserVersion });
3736
}
3837

39-
if (anonymizedProxyUrl) {
40-
browser.once('disconnected', () => {
41-
this._closeAnonymizedProxy(anonymizedProxyUrl as string);
42-
});
43-
}
44-
4538
return browser;
4639
}
4740

@@ -55,13 +48,13 @@ export class PlaywrightPlugin extends BrowserPlugin<BrowserType, Parameters<Brow
5548
const { launchOptions, proxyUrl } = launchContext;
5649

5750
if (proxyUrl) {
58-
if (this._shouldAnonymizeProxy(proxyUrl)) {
59-
const anonymizedProxyUrl = await this._getAnonymizedProxyUrl(proxyUrl);
60-
launchContext.anonymizedProxyUrl = anonymizedProxyUrl;
61-
launchOptions.proxy = { server: anonymizedProxyUrl };
62-
} else {
63-
launchOptions.proxy = { server: proxyUrl };
64-
}
51+
const url = new URL(proxyUrl);
52+
53+
launchOptions.proxy = {
54+
server: url.origin,
55+
username: decodeURIComponent(url.username),
56+
password: decodeURIComponent(url.password),
57+
};
6558
}
6659
}
6760
}

src/puppeteer/puppeteer-controller.ts

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,44 @@
1-
import type * as Puppeteer from 'puppeteer';
1+
import type Puppeteer from 'puppeteer';
22
import { BrowserController, Cookie } from '../abstract-classes/browser-controller';
3+
import { log } from '../logger';
34

45
const PROCESS_KILL_TIMEOUT_MILLIS = 5000;
56

7+
interface ContextOptions extends Puppeteer.BrowserContextOptions {
8+
proxyUsername?: string;
9+
proxyPassword?: string;
10+
}
11+
612
export class PuppeteerController extends BrowserController<typeof Puppeteer> {
7-
protected async _newPage(): Promise<Puppeteer.Page> {
13+
protected async _newPage(contextOptions?: ContextOptions): Promise<Puppeteer.Page> {
14+
if (contextOptions !== undefined) {
15+
if (!this.launchContext.useIncognitoPages) {
16+
throw new Error('A new page can be created with provided context only when using incognito pages.');
17+
}
18+
19+
const context = await this.browser.createIncognitoBrowserContext(contextOptions);
20+
const page = await context.newPage();
21+
22+
if (contextOptions.proxyUsername || contextOptions.proxyPassword) {
23+
await page.authenticate({
24+
username: contextOptions.proxyUsername ?? '',
25+
password: contextOptions.proxyPassword ?? '',
26+
});
27+
}
28+
29+
page.once('close', async () => {
30+
this.activePages--;
31+
32+
try {
33+
await context.close();
34+
} catch (error: any) {
35+
log.exception(error, 'Failed to close context.');
36+
}
37+
});
38+
39+
return page;
40+
}
41+
842
const page = await this.browser.newPage();
943

1044
page.once('close', () => {

0 commit comments

Comments
 (0)