@browserless.io/browserless 2.24.0 → 2.24.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -3
- package/build/browsers/index.js +1 -1
- package/build/routes/chrome/http/content.post.body.json +8 -8
- package/build/routes/chrome/http/pdf.post.body.json +8 -8
- package/build/routes/chrome/http/scrape.post.body.json +8 -8
- package/build/routes/chrome/http/screenshot.post.body.json +8 -8
- package/build/routes/chromium/http/content.post.body.json +8 -8
- package/build/routes/chromium/http/pdf.post.body.json +8 -8
- package/build/routes/chromium/http/scrape.post.body.json +8 -8
- package/build/routes/chromium/http/screenshot.post.body.json +8 -8
- package/build/routes/management/http/meta.get.js +3 -1
- package/build/shared/utils/performance/main.js +2 -1
- package/extensions/ublock/_locales/ar/messages.json +3 -3
- package/extensions/ublock/_locales/bg/messages.json +1 -1
- package/extensions/ublock/_locales/br_FR/messages.json +2 -2
- package/extensions/ublock/_locales/cy/messages.json +11 -11
- package/extensions/ublock/_locales/el/messages.json +2 -2
- package/extensions/ublock/_locales/hu/messages.json +1 -1
- package/extensions/ublock/_locales/id/messages.json +1 -1
- package/extensions/ublock/_locales/lv/messages.json +4 -4
- package/extensions/ublock/_locales/mk/messages.json +130 -130
- package/extensions/ublock/_locales/oc/messages.json +1 -1
- package/extensions/ublock/_locales/pt_BR/messages.json +1 -1
- package/extensions/ublock/_locales/pt_PT/messages.json +2 -2
- package/extensions/ublock/_locales/si/messages.json +100 -100
- package/extensions/ublock/_locales/sr/messages.json +4 -4
- package/extensions/ublock/_locales/vi/messages.json +19 -19
- package/extensions/ublock/_locales/zh_TW/messages.json +28 -28
- package/extensions/ublock/assets/assets.json +33 -29
- package/extensions/ublock/assets/thirdparties/easylist/easylist.txt +2984 -3287
- package/extensions/ublock/assets/thirdparties/easylist/easyprivacy.txt +150 -171
- package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/serverlist +37 -27
- package/extensions/ublock/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat +802 -888
- package/extensions/ublock/assets/thirdparties/urlhaus-filter/urlhaus-filter-online.txt +2355 -2071
- package/extensions/ublock/assets/ublock/badlists.txt +9 -1
- package/extensions/ublock/assets/ublock/badware.min.txt +354 -243
- package/extensions/ublock/assets/ublock/filters.min.txt +5837 -5737
- package/extensions/ublock/assets/ublock/privacy.min.txt +151 -38
- package/extensions/ublock/assets/ublock/quick-fixes.min.txt +83 -127
- package/extensions/ublock/assets/ublock/unbreak.min.txt +66 -50
- package/extensions/ublock/css/codemirror.css +4 -0
- package/extensions/ublock/document-blocked.html +3 -1
- package/extensions/ublock/js/arglist-parser.js +116 -0
- package/extensions/ublock/js/background.js +1 -1
- package/extensions/ublock/js/logger-ui.js +1 -1
- package/extensions/ublock/js/messaging.js +9 -2
- package/extensions/ublock/js/pagestore.js +3 -1
- package/extensions/ublock/js/redirect-engine.js +3 -1
- package/extensions/ublock/{assets/resources/set-attr.js → js/resources/attribute.js} +115 -11
- package/extensions/ublock/js/resources/base.js +38 -0
- package/extensions/ublock/js/resources/cookie.js +419 -0
- package/extensions/ublock/js/resources/href-sanitizer.js +188 -0
- package/extensions/ublock/js/resources/localstorage.js +235 -0
- package/extensions/ublock/js/resources/parse-replace.js +54 -0
- package/extensions/ublock/js/resources/prevent-settimeout.js +236 -0
- package/extensions/ublock/js/resources/proxy-apply.js +109 -0
- package/extensions/ublock/js/resources/replace-argument.js +120 -0
- package/extensions/ublock/{assets → js}/resources/run-at.js +20 -4
- package/extensions/ublock/{assets → js}/resources/safe-self.js +5 -4
- package/extensions/ublock/{assets → js}/resources/scriptlets.js +90 -1589
- package/extensions/ublock/js/resources/set-constant.js +287 -0
- package/extensions/ublock/js/resources/shared.js +44 -0
- package/extensions/ublock/js/resources/spoof-css.js +163 -0
- package/extensions/ublock/js/s14e-serializer.js +2 -1
- package/extensions/ublock/js/scriptlet-filtering-core.js +1 -1
- package/extensions/ublock/js/scriptlet-filtering.js +1 -31
- package/extensions/ublock/js/static-dnr-filtering.js +143 -129
- package/extensions/ublock/js/static-filtering-parser.js +27 -117
- package/extensions/ublock/js/static-net-filtering.js +53 -141
- package/extensions/ublock/js/traffic.js +1 -1
- package/extensions/ublock/js/urlskip.js +166 -0
- package/extensions/ublock/js/vapi-background-ext.js +38 -14
- package/extensions/ublock/manifest.json +1 -1
- package/package.json +11 -11
- package/src/browsers/index.ts +1 -1
- package/src/routes/management/http/meta.get.ts +6 -1
- package/src/shared/utils/performance/main.ts +2 -8
- package/static/docs/swagger.json +10 -10
- package/static/docs/swagger.min.json +9 -9
- package/static/function/client.js +119 -18
- package/static/function/index.html +119 -18
|
@@ -28,6 +28,7 @@ import BidiTrieContainer from './biditrie.js';
|
|
|
28
28
|
import { CompiledListReader } from './static-filtering-io.js';
|
|
29
29
|
import { FilteringContext } from './filtering-context.js';
|
|
30
30
|
import HNTrieContainer from './hntrie.js';
|
|
31
|
+
import { urlSkip } from './urlskip.js';
|
|
31
32
|
|
|
32
33
|
/******************************************************************************/
|
|
33
34
|
|
|
@@ -418,7 +419,7 @@ class LogData {
|
|
|
418
419
|
}
|
|
419
420
|
|
|
420
421
|
static requote(s) {
|
|
421
|
-
if (
|
|
422
|
+
if ( /^\$|^(["'`]).*\1$|,/.test(s) === false ) { return s; }
|
|
422
423
|
if ( s.includes("'") === false ) { return `'${s}'`; }
|
|
423
424
|
if ( s.includes('"') === false ) { return `"${s}"`; }
|
|
424
425
|
if ( s.includes('`') === false ) { return `\`${s}\``; }
|
|
@@ -4452,22 +4453,23 @@ StaticNetFilteringEngine.prototype.dnrFromCompiled = function(op, context, ...ar
|
|
|
4452
4453
|
}
|
|
4453
4454
|
|
|
4454
4455
|
// Priority:
|
|
4455
|
-
//
|
|
4456
|
-
//
|
|
4457
|
-
//
|
|
4458
|
-
//
|
|
4459
|
-
//
|
|
4460
|
-
//
|
|
4456
|
+
// Removeparam: 1-4
|
|
4457
|
+
// Block: 10 (default priority)
|
|
4458
|
+
// Redirect: 11-19
|
|
4459
|
+
// Excepted redirect: 21-29
|
|
4460
|
+
// Allow: 30
|
|
4461
|
+
// Block important: 40
|
|
4462
|
+
// Redirect important: 41-49
|
|
4461
4463
|
|
|
4462
4464
|
const realms = new Map([
|
|
4463
|
-
[ BLOCK_REALM, { type: 'block', priority:
|
|
4464
|
-
[ ALLOW_REALM, { type: 'allow', priority:
|
|
4465
|
-
[ REDIRECT_REALM, { type: 'redirect', priority:
|
|
4465
|
+
[ BLOCK_REALM, { type: 'block', priority: 10 } ],
|
|
4466
|
+
[ ALLOW_REALM, { type: 'allow', priority: 30 } ],
|
|
4467
|
+
[ REDIRECT_REALM, { type: 'redirect', priority: 11 } ],
|
|
4466
4468
|
[ REMOVEPARAM_REALM, { type: 'removeparam', priority: 0 } ],
|
|
4467
4469
|
[ CSP_REALM, { type: 'csp', priority: 0 } ],
|
|
4468
4470
|
[ PERMISSIONS_REALM, { type: 'permissions', priority: 0 } ],
|
|
4469
4471
|
[ URLTRANSFORM_REALM, { type: 'uritransform', priority: 0 } ],
|
|
4470
|
-
[ HEADERS_REALM, { type: 'block', priority:
|
|
4472
|
+
[ HEADERS_REALM, { type: 'block', priority: 10 } ],
|
|
4471
4473
|
[ URLSKIP_REALM, { type: 'urlskip', priority: 0 } ],
|
|
4472
4474
|
]);
|
|
4473
4475
|
const partyness = new Map([
|
|
@@ -4605,7 +4607,7 @@ StaticNetFilteringEngine.prototype.dnrFromCompiled = function(op, context, ...ar
|
|
|
4605
4607
|
if ( token !== '' ) {
|
|
4606
4608
|
const match = /:(\d+)$/.exec(token);
|
|
4607
4609
|
if ( match !== null ) {
|
|
4608
|
-
rule.priority
|
|
4610
|
+
rule.priority += Math.min(rule.priority + parseInt(match[1], 10), 9);
|
|
4609
4611
|
token = token.slice(0, match.index);
|
|
4610
4612
|
}
|
|
4611
4613
|
}
|
|
@@ -4623,7 +4625,7 @@ StaticNetFilteringEngine.prototype.dnrFromCompiled = function(op, context, ...ar
|
|
|
4623
4625
|
}
|
|
4624
4626
|
break;
|
|
4625
4627
|
}
|
|
4626
|
-
case 'removeparam':
|
|
4628
|
+
case 'removeparam': {
|
|
4627
4629
|
rule.action.type = 'redirect';
|
|
4628
4630
|
if ( rule.__modifierValue === '|' ) {
|
|
4629
4631
|
rule.__modifierValue = '';
|
|
@@ -4651,20 +4653,52 @@ StaticNetFilteringEngine.prototype.dnrFromCompiled = function(op, context, ...ar
|
|
|
4651
4653
|
};
|
|
4652
4654
|
}
|
|
4653
4655
|
if ( rule.condition.resourceTypes === undefined ) {
|
|
4654
|
-
rule.condition.
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4656
|
+
if ( rule.condition.excludedResourceTypes === undefined ) {
|
|
4657
|
+
rule.condition.resourceTypes = [
|
|
4658
|
+
'main_frame',
|
|
4659
|
+
'sub_frame',
|
|
4660
|
+
'xmlhttprequest',
|
|
4661
|
+
];
|
|
4662
|
+
}
|
|
4663
|
+
}
|
|
4664
|
+
// https://github.com/uBlockOrigin/uBOL-home/issues/140
|
|
4665
|
+
// Mitigate until DNR API flaw is addressed by browser vendors
|
|
4666
|
+
let priority = rule.priority || 1;
|
|
4667
|
+
if ( rule.condition.urlFilter !== undefined ) { priority += 1; }
|
|
4668
|
+
if ( rule.condition.regexFilter !== undefined ) { priority += 1; }
|
|
4669
|
+
if ( rule.condition.initiatorDomains !== undefined ) { priority += 1; }
|
|
4670
|
+
if ( rule.condition.requestDomains !== undefined ) { priority += 1; }
|
|
4671
|
+
if ( priority !== 1 ) {
|
|
4672
|
+
rule.priority = priority;
|
|
4659
4673
|
}
|
|
4660
4674
|
if ( rule.__modifierAction === ALLOW_REALM ) {
|
|
4661
4675
|
dnrAddRuleError(rule, `Unsupported removeparam exception: ${rule.__modifierValue}`);
|
|
4662
4676
|
}
|
|
4663
4677
|
break;
|
|
4678
|
+
}
|
|
4664
4679
|
case 'uritransform': {
|
|
4665
4680
|
dnrAddRuleError(rule, `Incompatible with DNR: uritransform=${rule.__modifierValue}`);
|
|
4666
4681
|
break;
|
|
4667
4682
|
}
|
|
4683
|
+
case 'urlskip': {
|
|
4684
|
+
let urlFilter = rule.condition?.urlFilter;
|
|
4685
|
+
if ( urlFilter === undefined ) { break; }
|
|
4686
|
+
let anchor = 0b000;
|
|
4687
|
+
if ( urlFilter.startsWith('||') ) {
|
|
4688
|
+
anchor |= 0b100;
|
|
4689
|
+
urlFilter = urlFilter.slice(2);
|
|
4690
|
+
} else if ( urlFilter.startsWith('|') ) {
|
|
4691
|
+
anchor |= 0b10;
|
|
4692
|
+
urlFilter = urlFilter.slice(1);
|
|
4693
|
+
}
|
|
4694
|
+
if ( urlFilter.endsWith('|') ) {
|
|
4695
|
+
anchor |= 0b001;
|
|
4696
|
+
urlFilter = urlFilter.slice(0, -1);
|
|
4697
|
+
}
|
|
4698
|
+
rule.condition.urlFilter = undefined;
|
|
4699
|
+
rule.condition.regexFilter = restrFromGenericPattern(urlFilter, anchor);
|
|
4700
|
+
break;
|
|
4701
|
+
}
|
|
4668
4702
|
default:
|
|
4669
4703
|
dnrAddRuleError(rule, `Unsupported modifier ${rule.__modifierType}`);
|
|
4670
4704
|
break;
|
|
@@ -5377,55 +5411,6 @@ StaticNetFilteringEngine.prototype.transformRequest = function(fctxt, out = [])
|
|
|
5377
5411
|
return out;
|
|
5378
5412
|
};
|
|
5379
5413
|
|
|
5380
|
-
/**
|
|
5381
|
-
* @trustedOption urlskip
|
|
5382
|
-
*
|
|
5383
|
-
* @description
|
|
5384
|
-
* Extract a URL from another URL according to one or more transformation steps,
|
|
5385
|
-
* thereby skipping over intermediate network request(s) to remote servers.
|
|
5386
|
-
* Requires a trusted source.
|
|
5387
|
-
*
|
|
5388
|
-
* @param steps
|
|
5389
|
-
* A serie of space-separated directives representing the transformation steps
|
|
5390
|
-
* to perform to extract the final URL to which a network request should be
|
|
5391
|
-
* redirected.
|
|
5392
|
-
*
|
|
5393
|
-
* Supported directives:
|
|
5394
|
-
*
|
|
5395
|
-
* `?name`: extract the value of parameter `name` as the current string.
|
|
5396
|
-
*
|
|
5397
|
-
* `&i`: extract the name of the parameter at position `i` as the current
|
|
5398
|
-
* string. The position is 1-based.
|
|
5399
|
-
*
|
|
5400
|
-
* `/.../`: extract the first capture group of a regex as the current string.
|
|
5401
|
-
*
|
|
5402
|
-
* `+https`: prepend the current string with `https://`.
|
|
5403
|
-
*
|
|
5404
|
-
* `-base64`: decode the current string as a base64-encoded string.
|
|
5405
|
-
*
|
|
5406
|
-
* `-uricomponent`: decode the current string as a URI encoded string.
|
|
5407
|
-
*
|
|
5408
|
-
* `-blocked`: allow the redirection of blocked requests. By default, blocked
|
|
5409
|
-
* requests can't by urlskip'ed.
|
|
5410
|
-
*
|
|
5411
|
-
* At any given step, the currently extracted string may not necessarily be
|
|
5412
|
-
* a valid URL, and more transformation steps may be needed to obtain a valid
|
|
5413
|
-
* URL once all the steps are applied.
|
|
5414
|
-
*
|
|
5415
|
-
* An unsupported step or a failed step will abort the transformation and no
|
|
5416
|
-
* redirection will be performed.
|
|
5417
|
-
*
|
|
5418
|
-
* The final step is expected to yield a valid URL. If the result is not a
|
|
5419
|
-
* valid URL, no redirection will be performed.
|
|
5420
|
-
*
|
|
5421
|
-
* @example
|
|
5422
|
-
* ||example.com/path/to/tracker$urlskip=?url
|
|
5423
|
-
* ||example.com/path/to/tracker$urlskip=?url ?to
|
|
5424
|
-
* ||pixiv.net/jump.php?$urlskip=&1
|
|
5425
|
-
* ||podtrac.com/pts/redirect.mp3/$urlskip=/\/redirect\.mp3\/(.*?\.mp3\b)/ +https
|
|
5426
|
-
*
|
|
5427
|
-
* */
|
|
5428
|
-
|
|
5429
5414
|
StaticNetFilteringEngine.prototype.urlSkip = function(
|
|
5430
5415
|
fctxt,
|
|
5431
5416
|
blocked,
|
|
@@ -5442,7 +5427,7 @@ StaticNetFilteringEngine.prototype.urlSkip = function(
|
|
|
5442
5427
|
const urlin = fctxt.url;
|
|
5443
5428
|
const value = directive.value;
|
|
5444
5429
|
const steps = value.includes(' ') && value.split(/ +/) || [ value ];
|
|
5445
|
-
const urlout = urlSkip(
|
|
5430
|
+
const urlout = urlSkip(urlin, blocked, steps, directive);
|
|
5446
5431
|
if ( urlout === undefined ) { continue; }
|
|
5447
5432
|
if ( urlout === urlin ) { continue; }
|
|
5448
5433
|
fctxt.redirectURL = urlout;
|
|
@@ -5453,79 +5438,6 @@ StaticNetFilteringEngine.prototype.urlSkip = function(
|
|
|
5453
5438
|
return out;
|
|
5454
5439
|
};
|
|
5455
5440
|
|
|
5456
|
-
function urlSkip(directive, url, blocked, steps) {
|
|
5457
|
-
try {
|
|
5458
|
-
let redirectBlocked = false;
|
|
5459
|
-
let urlout = url;
|
|
5460
|
-
for ( const step of steps ) {
|
|
5461
|
-
const urlin = urlout;
|
|
5462
|
-
const c0 = step.charCodeAt(0);
|
|
5463
|
-
// Extract from URL parameter name at position i
|
|
5464
|
-
if ( c0 === 0x26 ) { // &
|
|
5465
|
-
const i = (parseInt(step.slice(1)) || 0) - 1;
|
|
5466
|
-
if ( i < 0 ) { return; }
|
|
5467
|
-
const url = new URL(urlin);
|
|
5468
|
-
if ( i >= url.searchParams.size ) { return; }
|
|
5469
|
-
const params = Array.from(url.searchParams.keys());
|
|
5470
|
-
urlout = decodeURIComponent(params[i]);
|
|
5471
|
-
continue;
|
|
5472
|
-
}
|
|
5473
|
-
// Enforce https
|
|
5474
|
-
if ( c0 === 0x2B && step === '+https' ) {
|
|
5475
|
-
const s = urlin.replace(/^https?:\/\//, '');
|
|
5476
|
-
if ( /^[\w-]:\/\//.test(s) ) { return; }
|
|
5477
|
-
urlout = `https://${s}`;
|
|
5478
|
-
continue;
|
|
5479
|
-
}
|
|
5480
|
-
// Decode
|
|
5481
|
-
if ( c0 === 0x2D ) {
|
|
5482
|
-
// Base64
|
|
5483
|
-
if ( step === '-base64' ) {
|
|
5484
|
-
urlout = self.atob(urlin);
|
|
5485
|
-
continue;
|
|
5486
|
-
}
|
|
5487
|
-
// URI component
|
|
5488
|
-
if ( step === '-uricomponent' ) {
|
|
5489
|
-
urlout = self.decodeURIComponent(urlin);
|
|
5490
|
-
continue;
|
|
5491
|
-
}
|
|
5492
|
-
// Enable skip of blocked requests
|
|
5493
|
-
if ( step === '-blocked' ) {
|
|
5494
|
-
redirectBlocked = true;
|
|
5495
|
-
continue;
|
|
5496
|
-
}
|
|
5497
|
-
}
|
|
5498
|
-
// Regex extraction from first capture group
|
|
5499
|
-
if ( c0 === 0x2F ) { // /
|
|
5500
|
-
if ( directive.cache === null ) {
|
|
5501
|
-
directive.cache = new RegExp(step.slice(1, -1));
|
|
5502
|
-
}
|
|
5503
|
-
const match = directive.cache.exec(urlin);
|
|
5504
|
-
if ( match === null ) { return; }
|
|
5505
|
-
if ( match.length <= 1 ) { return; }
|
|
5506
|
-
urlout = match[1];
|
|
5507
|
-
continue;
|
|
5508
|
-
}
|
|
5509
|
-
// Extract from URL parameter
|
|
5510
|
-
if ( c0 === 0x3F ) { // ?
|
|
5511
|
-
urlout = (new URL(urlin)).searchParams.get(step.slice(1));
|
|
5512
|
-
if ( urlout === null ) { return; }
|
|
5513
|
-
if ( urlout.includes(' ') ) {
|
|
5514
|
-
urlout = urlout.replace(/ /g, '%20');
|
|
5515
|
-
}
|
|
5516
|
-
continue;
|
|
5517
|
-
}
|
|
5518
|
-
// Unknown directive
|
|
5519
|
-
return;
|
|
5520
|
-
}
|
|
5521
|
-
const urlfinal = new URL(urlout);
|
|
5522
|
-
if ( urlfinal.protocol !== 'https:' ) { return; }
|
|
5523
|
-
if ( blocked && redirectBlocked !== true ) { return; }
|
|
5524
|
-
return urlout;
|
|
5525
|
-
} catch(x) {
|
|
5526
|
-
}
|
|
5527
|
-
}
|
|
5528
|
-
|
|
5529
5441
|
/******************************************************************************/
|
|
5530
5442
|
|
|
5531
5443
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/1626
|
|
@@ -969,7 +969,7 @@ const injectCSP = function(fctxt, pageStore, responseHeaders) {
|
|
|
969
969
|
const builtinDirectives = [];
|
|
970
970
|
|
|
971
971
|
if ( pageStore.filterScripting(fctxt, true) === 1 ) {
|
|
972
|
-
builtinDirectives.push(µb.
|
|
972
|
+
builtinDirectives.push(µb.hiddenSettings.noScriptingCSP);
|
|
973
973
|
if ( logger.enabled ) {
|
|
974
974
|
fctxt.setRealm('network').setType('scripting').toLogger();
|
|
975
975
|
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/*******************************************************************************
|
|
2
|
+
|
|
3
|
+
uBlock Origin - a comprehensive, efficient content blocker
|
|
4
|
+
Copyright (C) 2022-present Raymond Hill
|
|
5
|
+
|
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU General Public License as published by
|
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License
|
|
17
|
+
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
|
18
|
+
|
|
19
|
+
Home: https://github.com/gorhill/uBlock
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @trustedOption urlskip
|
|
24
|
+
*
|
|
25
|
+
* @description
|
|
26
|
+
* Extract a URL from another URL according to one or more transformation steps,
|
|
27
|
+
* thereby skipping over intermediate network request(s) to remote servers.
|
|
28
|
+
* Requires a trusted source.
|
|
29
|
+
*
|
|
30
|
+
* @param steps
|
|
31
|
+
* A serie of space-separated directives representing the transformation steps
|
|
32
|
+
* to perform to extract the final URL to which a network request should be
|
|
33
|
+
* redirected.
|
|
34
|
+
*
|
|
35
|
+
* Supported directives:
|
|
36
|
+
*
|
|
37
|
+
* `?name`: extract the value of parameter `name` as the current string.
|
|
38
|
+
*
|
|
39
|
+
* `&i`: extract the name of the parameter at position `i` as the current
|
|
40
|
+
* string. The position is 1-based.
|
|
41
|
+
*
|
|
42
|
+
* `#`: extract the hash as the current string.
|
|
43
|
+
*
|
|
44
|
+
* `/.../`: extract the first capture group of a regex as the current string.
|
|
45
|
+
*
|
|
46
|
+
* `+https`: prepend the current string with `https://`.
|
|
47
|
+
*
|
|
48
|
+
* `-base64`: decode the current string as a base64-encoded string.
|
|
49
|
+
*
|
|
50
|
+
* `-safebase64`: decode the current string as a safe base64-encoded string.
|
|
51
|
+
*
|
|
52
|
+
* `-uricomponent`: decode the current string as a URI encoded string.
|
|
53
|
+
*
|
|
54
|
+
* `-blocked`: allow the redirection of blocked requests. By default, blocked
|
|
55
|
+
* requests can't by urlskip'ed.
|
|
56
|
+
*
|
|
57
|
+
* At any given step, the currently extracted string may not necessarily be
|
|
58
|
+
* a valid URL, and more transformation steps may be needed to obtain a valid
|
|
59
|
+
* URL once all the steps are applied.
|
|
60
|
+
*
|
|
61
|
+
* An unsupported step or a failed step will abort the transformation and no
|
|
62
|
+
* redirection will be performed.
|
|
63
|
+
*
|
|
64
|
+
* The final step is expected to yield a valid URL. If the result is not a
|
|
65
|
+
* valid URL, no redirection will be performed.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ||example.com/path/to/tracker$urlskip=?url
|
|
69
|
+
* ||example.com/path/to/tracker$urlskip=?url ?to
|
|
70
|
+
* ||pixiv.net/jump.php?$urlskip=&1
|
|
71
|
+
* ||podtrac.com/pts/redirect.mp3/$urlskip=/\/redirect\.mp3\/(.*?\.mp3\b)/ +https
|
|
72
|
+
*
|
|
73
|
+
* */
|
|
74
|
+
|
|
75
|
+
export function urlSkip(url, blocked, steps, directive = {}) {
|
|
76
|
+
try {
|
|
77
|
+
let redirectBlocked = false;
|
|
78
|
+
let urlout = url;
|
|
79
|
+
for ( const step of steps ) {
|
|
80
|
+
const urlin = urlout;
|
|
81
|
+
const c0 = step.charCodeAt(0);
|
|
82
|
+
// Extract from hash
|
|
83
|
+
if ( c0 === 0x23 && step === '#' ) { // #
|
|
84
|
+
const pos = urlin.indexOf('#');
|
|
85
|
+
urlout = pos !== -1 ? urlin.slice(pos+1) : '';
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
// Extract from URL parameter name at position i
|
|
89
|
+
if ( c0 === 0x26 ) { // &
|
|
90
|
+
const i = (parseInt(step.slice(1)) || 0) - 1;
|
|
91
|
+
if ( i < 0 ) { return; }
|
|
92
|
+
const url = new URL(urlin);
|
|
93
|
+
if ( i >= url.searchParams.size ) { return; }
|
|
94
|
+
const params = Array.from(url.searchParams.keys());
|
|
95
|
+
urlout = decodeURIComponent(params[i]);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
// Enforce https
|
|
99
|
+
if ( c0 === 0x2B && step === '+https' ) { // +
|
|
100
|
+
const s = urlin.replace(/^https?:\/\//, '');
|
|
101
|
+
if ( /^[\w-]:\/\//.test(s) ) { return; }
|
|
102
|
+
urlout = `https://${s}`;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
// Decode
|
|
106
|
+
if ( c0 === 0x2D ) { // -
|
|
107
|
+
// Base64
|
|
108
|
+
if ( step === '-base64' ) {
|
|
109
|
+
urlout = self.atob(urlin);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
// Safe Base64
|
|
113
|
+
if ( step === '-safebase64' ) {
|
|
114
|
+
if ( urlSkip.safeBase64Replacer === undefined ) {
|
|
115
|
+
urlSkip.safeBase64Map = { '-': '+', '_': '/' };
|
|
116
|
+
urlSkip.safeBase64Replacer = s => urlSkip.safeBase64Map[s];
|
|
117
|
+
}
|
|
118
|
+
urlout = urlin.replace(/[-_]/g, urlSkip.safeBase64Replacer);
|
|
119
|
+
urlout = self.atob(urlout);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
// URI component
|
|
123
|
+
if ( step === '-uricomponent' ) {
|
|
124
|
+
urlout = self.decodeURIComponent(urlin);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
// Enable skip of blocked requests
|
|
128
|
+
if ( step === '-blocked' ) {
|
|
129
|
+
redirectBlocked = true;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Regex extraction from first capture group
|
|
134
|
+
if ( c0 === 0x2F ) { // /
|
|
135
|
+
const re = directive.cache ?? new RegExp(step.slice(1, -1));
|
|
136
|
+
if ( directive.cache === null ) {
|
|
137
|
+
directive.cache = re;
|
|
138
|
+
}
|
|
139
|
+
const match = re.exec(urlin);
|
|
140
|
+
if ( match === null ) { return; }
|
|
141
|
+
if ( match.length <= 1 ) { return; }
|
|
142
|
+
urlout = match[1];
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
// Extract from URL parameter
|
|
146
|
+
if ( c0 === 0x3F ) { // ?
|
|
147
|
+
urlout = (new URL(urlin)).searchParams.get(step.slice(1));
|
|
148
|
+
if ( urlout === null ) { return; }
|
|
149
|
+
if ( urlout.includes(' ') ) {
|
|
150
|
+
urlout = urlout.replace(/ /g, '%20');
|
|
151
|
+
}
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
// Unknown directive
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const urlfinal = new URL(urlout);
|
|
158
|
+
if ( urlfinal.protocol !== 'https:' ) {
|
|
159
|
+
if ( urlfinal.protocol !== 'http:' ) { return; }
|
|
160
|
+
urlout = urlout.replace('http', 'https');
|
|
161
|
+
}
|
|
162
|
+
if ( blocked && redirectBlocked !== true ) { return; }
|
|
163
|
+
return urlout;
|
|
164
|
+
} catch(x) {
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -208,19 +208,43 @@ vAPI.prefetching = (( ) => {
|
|
|
208
208
|
|
|
209
209
|
/******************************************************************************/
|
|
210
210
|
|
|
211
|
-
vAPI.scriptletsInjector = ((
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
211
|
+
vAPI.scriptletsInjector = (( ) => {
|
|
212
|
+
const parts = [
|
|
213
|
+
'(',
|
|
214
|
+
function(details) {
|
|
215
|
+
if ( typeof self.uBO_scriptletsInjected === 'string' ) { return; }
|
|
216
|
+
const doc = document;
|
|
217
|
+
const { location } = doc;
|
|
218
|
+
if ( location === null ) { return; }
|
|
219
|
+
const { hostname } = location;
|
|
220
|
+
if ( hostname !== '' && details.hostname !== hostname ) { return; }
|
|
221
|
+
let script;
|
|
222
|
+
try {
|
|
223
|
+
script = doc.createElement('script');
|
|
224
|
+
script.appendChild(doc.createTextNode(details.scriptlets));
|
|
225
|
+
(doc.head || doc.documentElement).appendChild(script);
|
|
226
|
+
self.uBO_scriptletsInjected = details.filters;
|
|
227
|
+
} catch (ex) {
|
|
228
|
+
}
|
|
229
|
+
if ( script ) {
|
|
230
|
+
script.remove();
|
|
231
|
+
script.textContent = '';
|
|
232
|
+
}
|
|
233
|
+
return 0;
|
|
234
|
+
}.toString(),
|
|
235
|
+
')(',
|
|
236
|
+
'json-slot',
|
|
237
|
+
');',
|
|
238
|
+
];
|
|
239
|
+
const jsonSlot = parts.indexOf('json-slot');
|
|
240
|
+
return (hostname, details) => {
|
|
241
|
+
parts[jsonSlot] = JSON.stringify({
|
|
242
|
+
hostname,
|
|
243
|
+
scriptlets: details.mainWorld,
|
|
244
|
+
filters: details.filters,
|
|
245
|
+
});
|
|
246
|
+
return parts.join('');
|
|
247
|
+
};
|
|
248
|
+
})();
|
|
225
249
|
|
|
226
250
|
/******************************************************************************/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@browserless.io/browserless",
|
|
3
|
-
"version": "2.24.
|
|
3
|
+
"version": "2.24.2",
|
|
4
4
|
"license": "SSPL",
|
|
5
5
|
"description": "The browserless platform",
|
|
6
6
|
"author": "browserless.io",
|
|
@@ -55,18 +55,18 @@
|
|
|
55
55
|
"get-port": "^7.1.0",
|
|
56
56
|
"gradient-string": "^3.0.0",
|
|
57
57
|
"http-proxy": "^1.18.1",
|
|
58
|
-
"lighthouse": "^12.
|
|
58
|
+
"lighthouse": "^12.3.0",
|
|
59
59
|
"micromatch": "^4.0.8",
|
|
60
60
|
"playwright-1.45": "npm:playwright-core@1.45.3",
|
|
61
61
|
"playwright-1.46": "npm:playwright-core@1.46.1",
|
|
62
62
|
"playwright-1.47": "npm:playwright-core@1.47.2",
|
|
63
63
|
"playwright-1.48": "npm:playwright-core@1.48.2",
|
|
64
|
-
"playwright-core": "^1.49.
|
|
65
|
-
"puppeteer-core": "^23.
|
|
64
|
+
"playwright-core": "^1.49.1",
|
|
65
|
+
"puppeteer-core": "^23.11.1",
|
|
66
66
|
"puppeteer-extra": "^3.3.6",
|
|
67
67
|
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
|
68
68
|
"queue": "^7.0.0",
|
|
69
|
-
"systeminformation": "^5.
|
|
69
|
+
"systeminformation": "^5.25.5",
|
|
70
70
|
"tar-fs": "^3.0.6"
|
|
71
71
|
},
|
|
72
72
|
"optionalDependencies": {
|
|
@@ -76,20 +76,20 @@
|
|
|
76
76
|
"@types/http-proxy": "^1.17.15",
|
|
77
77
|
"@types/micromatch": "^4.0.9",
|
|
78
78
|
"@types/mocha": "^10.0.10",
|
|
79
|
-
"@types/node": "^22.10.
|
|
79
|
+
"@types/node": "^22.10.5",
|
|
80
80
|
"@types/sinon": "^17.0.3",
|
|
81
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
82
|
-
"@typescript-eslint/parser": "^8.
|
|
81
|
+
"@typescript-eslint/eslint-plugin": "^8.19.1",
|
|
82
|
+
"@typescript-eslint/parser": "^8.19.1",
|
|
83
83
|
"assert": "^2.0.0",
|
|
84
84
|
"chai": "^5.1.2",
|
|
85
85
|
"cross-env": "^7.0.3",
|
|
86
86
|
"env-cmd": "^10.1.0",
|
|
87
|
-
"esbuild": "^0.24.
|
|
87
|
+
"esbuild": "^0.24.2",
|
|
88
88
|
"esbuild-plugin-polyfill-node": "^0.3.0",
|
|
89
|
-
"eslint": "^9.
|
|
89
|
+
"eslint": "^9.17.0",
|
|
90
90
|
"extract-zip": "^2.0.1",
|
|
91
91
|
"gunzip-maybe": "^1.4.2",
|
|
92
|
-
"marked": "^15.0.
|
|
92
|
+
"marked": "^15.0.6",
|
|
93
93
|
"mocha": "^11.0.1",
|
|
94
94
|
"move-file": "^3.1.0",
|
|
95
95
|
"prettier": "^3.4.2",
|
package/src/browsers/index.ts
CHANGED
|
@@ -538,7 +538,7 @@ export class BrowserManager {
|
|
|
538
538
|
if (
|
|
539
539
|
launchOptions.args &&
|
|
540
540
|
proxyServerArg &&
|
|
541
|
-
req.parsed.pathname.
|
|
541
|
+
req.parsed.pathname.includes('/playwright')
|
|
542
542
|
) {
|
|
543
543
|
(launchOptions as BrowserServerOptions).proxy = {
|
|
544
544
|
server: proxyServerArg.split('=')[1],
|
|
@@ -14,8 +14,11 @@ import {
|
|
|
14
14
|
} from '@browserless.io/browserless';
|
|
15
15
|
import { ServerResponse } from 'http';
|
|
16
16
|
import { createRequire } from 'module';
|
|
17
|
+
import { fileURLToPath } from 'url';
|
|
17
18
|
import path from 'path';
|
|
18
19
|
|
|
20
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
|
|
19
22
|
export interface ResponseSchema {
|
|
20
23
|
/**
|
|
21
24
|
* The semantic version of the Browserless API
|
|
@@ -50,7 +53,9 @@ export interface ResponseSchema {
|
|
|
50
53
|
|
|
51
54
|
const semverReg = /(\*|\^|>|=|<|~)/gi;
|
|
52
55
|
const require = createRequire(import.meta.url);
|
|
53
|
-
const blessPackageJSON = require(
|
|
56
|
+
const blessPackageJSON = require(
|
|
57
|
+
path.join(__dirname, '..', '..', '..', '..', 'package.json'),
|
|
58
|
+
);
|
|
54
59
|
const { browsers } = require(
|
|
55
60
|
path.join(process.cwd(), 'node_modules', 'playwright-core', 'browsers.json'),
|
|
56
61
|
) as {
|
|
@@ -2,6 +2,7 @@ import { Message, mainOptions } from './types.js';
|
|
|
2
2
|
import { fork } from 'child_process';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
|
|
5
|
+
const __dirname = import.meta.dirname;
|
|
5
6
|
const DEFAULT_AUDIT_CONFIG = {
|
|
6
7
|
extends: 'lighthouse:default',
|
|
7
8
|
};
|
|
@@ -13,14 +14,7 @@ export default async ({
|
|
|
13
14
|
timeout,
|
|
14
15
|
}: mainOptions): Promise<unknown> => {
|
|
15
16
|
return new Promise((resolve, reject) => {
|
|
16
|
-
const childPath = path.join(
|
|
17
|
-
'./',
|
|
18
|
-
'build',
|
|
19
|
-
'shared',
|
|
20
|
-
'utils',
|
|
21
|
-
'performance',
|
|
22
|
-
'child.js',
|
|
23
|
-
);
|
|
17
|
+
const childPath = path.join(__dirname, 'child.js');
|
|
24
18
|
|
|
25
19
|
logger.trace(`Starting up child at ${childPath}`);
|
|
26
20
|
|