fix(core/utils/puppeteer): proxy-chain error (#11470)

HTTPS/SOCKS proxy is not supported by proxy-chain and will cause an
error unconditionally. If an HTTPS/SOCKS proxy does not need
authentication, explicitly bypassing proxy-chain is a must. If it does
need, making a warning and continuing without proxy seems to be the best
choice.

Signed-off-by: Rongrong <i@rong.moe>

Signed-off-by: Rongrong <i@rong.moe>
This commit is contained in:
Rongrong 2022-12-19 23:39:11 +08:00 committed by GitHub
parent cb210c8c72
commit 1381377e91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 5 deletions

View File

@ -1,6 +1,7 @@
const config = require('@/config').value;
let puppeteer = require('puppeteer');
const proxyChain = require('proxy-chain');
const logger = require('./logger');
const options = {
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-infobars', '--window-position=0,0', '--ignore-certificate-errors', '--ignore-certificate-errors-spki-list', `--user-agent=${config.ua}`],
@ -50,7 +51,17 @@ module.exports = async (extraOptions = {}) => {
}
let browser;
if (proxyUri) {
options.args.push(`--proxy-server=${await proxyChain.anonymizeProxy(proxyUri)}`);
if (proxyUri.includes('@')) {
// only proxies with authentication need to be anonymized
if (proxyUri.startsWith('http:')) {
options.args.push(`--proxy-server=${await proxyChain.anonymizeProxy(proxyUri)}`);
} else {
logger.warn('SOCKS/HTTPS proxy with authentication is not supported by puppeteer, continue without proxy');
}
} else {
// Chromium cannot recognize socks5h and socks4a, so we need to trim their postfixes
options.args.push(`--proxy-server=${proxyUri.replace('socks5h://', 'socks5://').replace('socks4a://', 'socks4://')}`);
}
}
if (config.puppeteerWSEndpoint) {
browser = await puppeteer.connect({

View File

@ -67,16 +67,35 @@ describe('puppeteer', () => {
expect(chromeTest).toBe('present (passed)');
}, 15000);
it('puppeteer accept proxy uri', async () => {
it('puppeteer accept http proxy uri w/ auth', async () => {
process.env.PROXY_URI = 'http://user:pass@rsshub.proxy:2333';
puppeteer = require('../../lib/utils/puppeteer');
browser = await puppeteer();
expect(browser.process().spawnargs.some((arg) => /^--proxy-server=http:\/\/.*$/.test(arg))).toBe(true);
// trailing slash will cause net::ERR_NO_SUPPORTED_PROXIES, prohibit it
expect(browser.process().spawnargs.some((arg) => /^--proxy-server=http:\/\/.*[^/]$/.test(arg))).toBe(true);
});
it('puppeteer accept proxy', async () => {
it('puppeteer reject https proxy uri w/ auth', async () => {
process.env.PROXY_URI = 'https://user:pass@rsshub.proxy:2333';
puppeteer = require('../../lib/utils/puppeteer');
browser = await puppeteer();
expect(browser.process().spawnargs.some((arg) => arg.includes('--proxy-server'))).toBe(false);
});
it('puppeteer reject socks proxy uri w/ auth', async () => {
process.env.PROXY_URI = 'socks5://user:pass@rsshub.proxy:2333';
puppeteer = require('../../lib/utils/puppeteer');
browser = await puppeteer();
expect(browser.process().spawnargs.some((arg) => arg.includes('--proxy-server'))).toBe(false);
});
it('puppeteer accept http proxy', async () => {
process.env.PROXY_PROTOCOL = 'http';
process.env.PROXY_HOST = 'rsshub.proxy';
process.env.PROXY_PORT = '2333';
@ -84,6 +103,39 @@ describe('puppeteer', () => {
puppeteer = require('../../lib/utils/puppeteer');
browser = await puppeteer();
expect(browser.process().spawnargs.some((arg) => /^--proxy-server=http:\/\/.*$/.test(arg))).toBe(true);
expect(browser.process().spawnargs.some((arg) => /^--proxy-server=http:\/\/rsshub.proxy:2333$/.test(arg))).toBe(true);
}, 10000);
it('puppeteer accept https proxy', async () => {
process.env.PROXY_PROTOCOL = 'https';
process.env.PROXY_HOST = 'rsshub.proxy';
process.env.PROXY_PORT = '2333';
puppeteer = require('../../lib/utils/puppeteer');
browser = await puppeteer();
expect(browser.process().spawnargs.some((arg) => /^--proxy-server=https:\/\/rsshub.proxy:2333$/.test(arg))).toBe(true);
}, 10000);
it('puppeteer accept socks4a proxy', async () => {
process.env.PROXY_PROTOCOL = 'socks4a';
process.env.PROXY_HOST = 'rsshub.proxy';
process.env.PROXY_PORT = '2333';
puppeteer = require('../../lib/utils/puppeteer');
browser = await puppeteer();
expect(browser.process().spawnargs.some((arg) => /^--proxy-server=socks4:\/\/rsshub.proxy:2333$/.test(arg))).toBe(true);
}, 10000);
it('puppeteer accept socks5h proxy', async () => {
process.env.PROXY_PROTOCOL = 'socks5h';
process.env.PROXY_HOST = 'rsshub.proxy';
process.env.PROXY_PORT = '2333';
puppeteer = require('../../lib/utils/puppeteer');
browser = await puppeteer();
expect(browser.process().spawnargs.some((arg) => /^--proxy-server=socks5:\/\/rsshub.proxy:2333$/.test(arg))).toBe(true);
}, 10000);
});