Add support for outgoing request proxying Closes #2824

ab06aa4bf53fb3cd28242413e07a3526869106a0

Cohee <18619528+Cohee1207@users.noreply.github.com>

5 files changed, +549 -2Showing whitespace changes
default/config.yaml+10 -0
@@ -37,6 +37,16 @@ basicAuthUser:
3737 password: "password"
3838# Enables CORS proxy middleware
3939enableCorsProxy: false
40+# -- REQUEST PROXY CONFIGURATION --
41+requestProxy:
42+ # If a proxy is enabled, all outgoing HTTP/HTTPS requests will be routed through it.
43+ enabled: false
44+ # Proxy URL. Possible protocols: http, https, socks, socks5, socks4, pac
45+ url: "socks5://username:password@example.com:1080"
46+ # Proxy bypass list. Requests to these hosts won't be routed through the proxy.
47+ bypass:
48+ - localhost
49+ - 127.0.0.1
4050# Enable multi-user mode
4151enableUserAccounts: false
4252# Enable discreet login mode: hides user list on the login screen
package-lock.json+482 -2
@@ -40,6 +40,7 @@
4040 "png-chunk-text": "^1.0.0",
4141 "png-chunks-encode": "^1.0.0",
4242 "png-chunks-extract": "^1.0.0",
43+ "proxy-agent": "^6.4.0",
4344 "rate-limiter-flexible": "^5.0.0",
4445 "response-time": "^2.3.2",
4546 "sanitize-filename": "^1.6.3",
@@ -941,6 +942,12 @@
941942 "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
942943 "license": "MIT"
943944 },
945+ "node_modules/@tootallnate/quickjs-emscripten": {
946+ "version": "0.23.0",
947+ "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
948+ "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
949+ "license": "MIT"
950+ },
944951 "node_modules/@types/cacheable-request": {
945952 "version": "6.0.3",
946953 "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
@@ -1080,6 +1087,41 @@
10801087 "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
10811088 }
10821089 },
1090+ "node_modules/agent-base": {
1091+ "version": "7.1.1",
1092+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
1093+ "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
1094+ "license": "MIT",
1095+ "dependencies": {
1096+ "debug": "^4.3.4"
1097+ },
1098+ "engines": {
1099+ "node": ">= 14"
1100+ }
1101+ },
1102+ "node_modules/agent-base/node_modules/debug": {
1103+ "version": "4.3.7",
1104+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
1105+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
1106+ "license": "MIT",
1107+ "dependencies": {
1108+ "ms": "^2.1.3"
1109+ },
1110+ "engines": {
1111+ "node": ">=6.0"
1112+ },
1113+ "peerDependenciesMeta": {
1114+ "supports-color": {
1115+ "optional": true
1116+ }
1117+ }
1118+ },
1119+ "node_modules/agent-base/node_modules/ms": {
1120+ "version": "2.1.3",
1121+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1122+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1123+ "license": "MIT"
1124+ },
10831125 "node_modules/agentkeepalive": {
10841126 "version": "4.5.0",
10851127 "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
@@ -1382,6 +1424,18 @@
13821424 "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
13831425 "license": "MIT"
13841426 },
1427+ "node_modules/ast-types": {
1428+ "version": "0.13.4",
1429+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
1430+ "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
1431+ "license": "MIT",
1432+ "dependencies": {
1433+ "tslib": "^2.0.1"
1434+ },
1435+ "engines": {
1436+ "node": ">=4"
1437+ }
1438+ },
13851439 "node_modules/async": {
13861440 "version": "3.2.5",
13871441 "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
@@ -1445,6 +1499,15 @@
14451499 ],
14461500 "license": "MIT"
14471501 },
1502+ "node_modules/basic-ftp": {
1503+ "version": "5.0.5",
1504+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
1505+ "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
1506+ "license": "MIT",
1507+ "engines": {
1508+ "node": ">=10.0.0"
1509+ }
1510+ },
14481511 "node_modules/bing-translate-api": {
14491512 "version": "2.9.1",
14501513 "resolved": "https://registry.npmjs.org/bing-translate-api/-/bing-translate-api-2.9.1.tgz",
@@ -2250,6 +2313,15 @@
22502313 "url": "https://github.com/sponsors/fb55"
22512314 }
22522315 },
2316+ "node_modules/data-uri-to-buffer": {
2317+ "version": "6.0.2",
2318+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
2319+ "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
2320+ "license": "MIT",
2321+ "engines": {
2322+ "node": ">= 14"
2323+ }
2324+ },
22532325 "node_modules/debug": {
22542326 "version": "2.6.9",
22552327 "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -2316,6 +2388,20 @@
23162388 "node": ">=8"
23172389 }
23182390 },
2391+ "node_modules/degenerator": {
2392+ "version": "5.0.1",
2393+ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
2394+ "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
2395+ "license": "MIT",
2396+ "dependencies": {
2397+ "ast-types": "^0.13.4",
2398+ "escodegen": "^2.1.0",
2399+ "esprima": "^4.0.1"
2400+ },
2401+ "engines": {
2402+ "node": ">= 14"
2403+ }
2404+ },
23192405 "node_modules/delayed-stream": {
23202406 "version": "1.0.0",
23212407 "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -2528,6 +2614,27 @@
25282614 "node": ">=0.8.0"
25292615 }
25302616 },
2617+ "node_modules/escodegen": {
2618+ "version": "2.1.0",
2619+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
2620+ "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
2621+ "license": "BSD-2-Clause",
2622+ "dependencies": {
2623+ "esprima": "^4.0.1",
2624+ "estraverse": "^5.2.0",
2625+ "esutils": "^2.0.2"
2626+ },
2627+ "bin": {
2628+ "escodegen": "bin/escodegen.js",
2629+ "esgenerate": "bin/esgenerate.js"
2630+ },
2631+ "engines": {
2632+ "node": ">=6.0"
2633+ },
2634+ "optionalDependencies": {
2635+ "source-map": "~0.6.1"
2636+ }
2637+ },
25312638 "node_modules/eslint": {
25322639 "version": "8.57.0",
25332640 "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
@@ -2683,6 +2790,19 @@
26832790 "url": "https://opencollective.com/eslint"
26842791 }
26852792 },
2793+ "node_modules/esprima": {
2794+ "version": "4.0.1",
2795+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
2796+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
2797+ "license": "BSD-2-Clause",
2798+ "bin": {
2799+ "esparse": "bin/esparse.js",
2800+ "esvalidate": "bin/esvalidate.js"
2801+ },
2802+ "engines": {
2803+ "node": ">=4"
2804+ }
2805+ },
26862806 "node_modules/esquery": {
26872807 "version": "1.5.0",
26882808 "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
@@ -2713,7 +2833,6 @@
27132833 "version": "5.3.0",
27142834 "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
27152835 "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
2716- "dev": true,
27172836 "license": "BSD-2-Clause",
27182837 "engines": {
27192838 "node": ">=4.0"
@@ -2723,7 +2842,6 @@
27232842 "version": "2.0.3",
27242843 "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
27252844 "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
2726- "dev": true,
27272845 "license": "BSD-2-Clause",
27282846 "engines": {
27292847 "node": ">=0.10.0"
@@ -3071,6 +3189,20 @@
30713189 "node": ">= 0.6"
30723190 }
30733191 },
3192+ "node_modules/fs-extra": {
3193+ "version": "11.2.0",
3194+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
3195+ "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
3196+ "license": "MIT",
3197+ "dependencies": {
3198+ "graceful-fs": "^4.2.0",
3199+ "jsonfile": "^6.0.1",
3200+ "universalify": "^2.0.0"
3201+ },
3202+ "engines": {
3203+ "node": ">=14.14"
3204+ }
3205+ },
30743206 "node_modules/fs.realpath": {
30753207 "version": "1.0.0",
30763208 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -3130,6 +3262,44 @@
31303262 "url": "https://github.com/sponsors/sindresorhus"
31313263 }
31323264 },
3265+ "node_modules/get-uri": {
3266+ "version": "6.0.3",
3267+ "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz",
3268+ "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==",
3269+ "license": "MIT",
3270+ "dependencies": {
3271+ "basic-ftp": "^5.0.2",
3272+ "data-uri-to-buffer": "^6.0.2",
3273+ "debug": "^4.3.4",
3274+ "fs-extra": "^11.2.0"
3275+ },
3276+ "engines": {
3277+ "node": ">= 14"
3278+ }
3279+ },
3280+ "node_modules/get-uri/node_modules/debug": {
3281+ "version": "4.3.7",
3282+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
3283+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
3284+ "license": "MIT",
3285+ "dependencies": {
3286+ "ms": "^2.1.3"
3287+ },
3288+ "engines": {
3289+ "node": ">=6.0"
3290+ },
3291+ "peerDependenciesMeta": {
3292+ "supports-color": {
3293+ "optional": true
3294+ }
3295+ }
3296+ },
3297+ "node_modules/get-uri/node_modules/ms": {
3298+ "version": "2.1.3",
3299+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
3300+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
3301+ "license": "MIT"
3302+ },
31333303 "node_modules/gifwrap": {
31343304 "version": "0.10.1",
31353305 "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz",
@@ -3369,6 +3539,42 @@
33693539 "node": ">= 0.8"
33703540 }
33713541 },
3542+ "node_modules/http-proxy-agent": {
3543+ "version": "7.0.2",
3544+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
3545+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
3546+ "license": "MIT",
3547+ "dependencies": {
3548+ "agent-base": "^7.1.0",
3549+ "debug": "^4.3.4"
3550+ },
3551+ "engines": {
3552+ "node": ">= 14"
3553+ }
3554+ },
3555+ "node_modules/http-proxy-agent/node_modules/debug": {
3556+ "version": "4.3.7",
3557+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
3558+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
3559+ "license": "MIT",
3560+ "dependencies": {
3561+ "ms": "^2.1.3"
3562+ },
3563+ "engines": {
3564+ "node": ">=6.0"
3565+ },
3566+ "peerDependenciesMeta": {
3567+ "supports-color": {
3568+ "optional": true
3569+ }
3570+ }
3571+ },
3572+ "node_modules/http-proxy-agent/node_modules/ms": {
3573+ "version": "2.1.3",
3574+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
3575+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
3576+ "license": "MIT"
3577+ },
33723578 "node_modules/http2-wrapper": {
33733579 "version": "1.0.3",
33743580 "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
@@ -3382,6 +3588,42 @@
33823588 "node": ">=10.19.0"
33833589 }
33843590 },
3591+ "node_modules/https-proxy-agent": {
3592+ "version": "7.0.5",
3593+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
3594+ "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
3595+ "license": "MIT",
3596+ "dependencies": {
3597+ "agent-base": "^7.0.2",
3598+ "debug": "4"
3599+ },
3600+ "engines": {
3601+ "node": ">= 14"
3602+ }
3603+ },
3604+ "node_modules/https-proxy-agent/node_modules/debug": {
3605+ "version": "4.3.7",
3606+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
3607+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
3608+ "license": "MIT",
3609+ "dependencies": {
3610+ "ms": "^2.1.3"
3611+ },
3612+ "engines": {
3613+ "node": ">=6.0"
3614+ },
3615+ "peerDependenciesMeta": {
3616+ "supports-color": {
3617+ "optional": true
3618+ }
3619+ }
3620+ },
3621+ "node_modules/https-proxy-agent/node_modules/ms": {
3622+ "version": "2.1.3",
3623+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
3624+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
3625+ "license": "MIT"
3626+ },
33853627 "node_modules/humanize-ms": {
33863628 "version": "1.2.1",
33873629 "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
@@ -3485,6 +3727,19 @@
34853727 "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
34863728 "license": "ISC"
34873729 },
3730+ "node_modules/ip-address": {
3731+ "version": "9.0.5",
3732+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
3733+ "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
3734+ "license": "MIT",
3735+ "dependencies": {
3736+ "jsbn": "1.1.0",
3737+ "sprintf-js": "^1.1.3"
3738+ },
3739+ "engines": {
3740+ "node": ">= 12"
3741+ }
3742+ },
34883743 "node_modules/ip-matching": {
34893744 "version": "2.1.2",
34903745 "resolved": "https://registry.npmjs.org/ip-matching/-/ip-matching-2.1.2.tgz",
@@ -3669,6 +3924,12 @@
36693924 "js-yaml": "bin/js-yaml.js"
36703925 }
36713926 },
3927+ "node_modules/jsbn": {
3928+ "version": "1.1.0",
3929+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
3930+ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
3931+ "license": "MIT"
3932+ },
36723933 "node_modules/json-buffer": {
36733934 "version": "3.0.1",
36743935 "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
@@ -3761,6 +4022,18 @@
37614022 "dev": true,
37624023 "license": "MIT"
37634024 },
4025+ "node_modules/jsonfile": {
4026+ "version": "6.1.0",
4027+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
4028+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
4029+ "license": "MIT",
4030+ "dependencies": {
4031+ "universalify": "^2.0.0"
4032+ },
4033+ "optionalDependencies": {
4034+ "graceful-fs": "^4.1.6"
4035+ }
4036+ },
37644037 "node_modules/keygrip": {
37654038 "version": "1.1.0",
37664039 "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
@@ -4053,6 +4326,15 @@
40534326 "node": ">= 0.6"
40544327 }
40554328 },
4329+ "node_modules/netmask": {
4330+ "version": "2.0.2",
4331+ "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
4332+ "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
4333+ "license": "MIT",
4334+ "engines": {
4335+ "node": ">= 0.4.0"
4336+ }
4337+ },
40564338 "node_modules/node-domexception": {
40574339 "version": "1.0.0",
40584340 "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
@@ -4323,6 +4605,61 @@
43234605 "url": "https://github.com/sponsors/sindresorhus"
43244606 }
43254607 },
4608+ "node_modules/pac-proxy-agent": {
4609+ "version": "7.0.2",
4610+ "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz",
4611+ "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==",
4612+ "license": "MIT",
4613+ "dependencies": {
4614+ "@tootallnate/quickjs-emscripten": "^0.23.0",
4615+ "agent-base": "^7.0.2",
4616+ "debug": "^4.3.4",
4617+ "get-uri": "^6.0.1",
4618+ "http-proxy-agent": "^7.0.0",
4619+ "https-proxy-agent": "^7.0.5",
4620+ "pac-resolver": "^7.0.1",
4621+ "socks-proxy-agent": "^8.0.4"
4622+ },
4623+ "engines": {
4624+ "node": ">= 14"
4625+ }
4626+ },
4627+ "node_modules/pac-proxy-agent/node_modules/debug": {
4628+ "version": "4.3.7",
4629+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
4630+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
4631+ "license": "MIT",
4632+ "dependencies": {
4633+ "ms": "^2.1.3"
4634+ },
4635+ "engines": {
4636+ "node": ">=6.0"
4637+ },
4638+ "peerDependenciesMeta": {
4639+ "supports-color": {
4640+ "optional": true
4641+ }
4642+ }
4643+ },
4644+ "node_modules/pac-proxy-agent/node_modules/ms": {
4645+ "version": "2.1.3",
4646+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
4647+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
4648+ "license": "MIT"
4649+ },
4650+ "node_modules/pac-resolver": {
4651+ "version": "7.0.1",
4652+ "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
4653+ "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
4654+ "license": "MIT",
4655+ "dependencies": {
4656+ "degenerator": "^5.0.0",
4657+ "netmask": "^2.0.2"
4658+ },
4659+ "engines": {
4660+ "node": ">= 14"
4661+ }
4662+ },
43264663 "node_modules/pako": {
43274664 "version": "1.0.11",
43284665 "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
@@ -4618,6 +4955,57 @@
46184955 "node": ">= 0.10"
46194956 }
46204957 },
4958+ "node_modules/proxy-agent": {
4959+ "version": "6.4.0",
4960+ "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz",
4961+ "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==",
4962+ "license": "MIT",
4963+ "dependencies": {
4964+ "agent-base": "^7.0.2",
4965+ "debug": "^4.3.4",
4966+ "http-proxy-agent": "^7.0.1",
4967+ "https-proxy-agent": "^7.0.3",
4968+ "lru-cache": "^7.14.1",
4969+ "pac-proxy-agent": "^7.0.1",
4970+ "proxy-from-env": "^1.1.0",
4971+ "socks-proxy-agent": "^8.0.2"
4972+ },
4973+ "engines": {
4974+ "node": ">= 14"
4975+ }
4976+ },
4977+ "node_modules/proxy-agent/node_modules/debug": {
4978+ "version": "4.3.7",
4979+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
4980+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
4981+ "license": "MIT",
4982+ "dependencies": {
4983+ "ms": "^2.1.3"
4984+ },
4985+ "engines": {
4986+ "node": ">=6.0"
4987+ },
4988+ "peerDependenciesMeta": {
4989+ "supports-color": {
4990+ "optional": true
4991+ }
4992+ }
4993+ },
4994+ "node_modules/proxy-agent/node_modules/lru-cache": {
4995+ "version": "7.18.3",
4996+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
4997+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
4998+ "license": "ISC",
4999+ "engines": {
5000+ "node": ">=12"
5001+ }
5002+ },
5003+ "node_modules/proxy-agent/node_modules/ms": {
5004+ "version": "2.1.3",
5005+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
5006+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
5007+ "license": "MIT"
5008+ },
46215009 "node_modules/proxy-from-env": {
46225010 "version": "1.1.0",
46235011 "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -5165,6 +5553,83 @@
51655553 "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==",
51665554 "license": "MIT"
51675555 },
5556+ "node_modules/smart-buffer": {
5557+ "version": "4.2.0",
5558+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
5559+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
5560+ "license": "MIT",
5561+ "engines": {
5562+ "node": ">= 6.0.0",
5563+ "npm": ">= 3.0.0"
5564+ }
5565+ },
5566+ "node_modules/socks": {
5567+ "version": "2.8.3",
5568+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
5569+ "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
5570+ "license": "MIT",
5571+ "dependencies": {
5572+ "ip-address": "^9.0.5",
5573+ "smart-buffer": "^4.2.0"
5574+ },
5575+ "engines": {
5576+ "node": ">= 10.0.0",
5577+ "npm": ">= 3.0.0"
5578+ }
5579+ },
5580+ "node_modules/socks-proxy-agent": {
5581+ "version": "8.0.4",
5582+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz",
5583+ "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==",
5584+ "license": "MIT",
5585+ "dependencies": {
5586+ "agent-base": "^7.1.1",
5587+ "debug": "^4.3.4",
5588+ "socks": "^2.8.3"
5589+ },
5590+ "engines": {
5591+ "node": ">= 14"
5592+ }
5593+ },
5594+ "node_modules/socks-proxy-agent/node_modules/debug": {
5595+ "version": "4.3.7",
5596+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
5597+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
5598+ "license": "MIT",
5599+ "dependencies": {
5600+ "ms": "^2.1.3"
5601+ },
5602+ "engines": {
5603+ "node": ">=6.0"
5604+ },
5605+ "peerDependenciesMeta": {
5606+ "supports-color": {
5607+ "optional": true
5608+ }
5609+ }
5610+ },
5611+ "node_modules/socks-proxy-agent/node_modules/ms": {
5612+ "version": "2.1.3",
5613+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
5614+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
5615+ "license": "MIT"
5616+ },
5617+ "node_modules/source-map": {
5618+ "version": "0.6.1",
5619+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
5620+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
5621+ "license": "BSD-3-Clause",
5622+ "optional": true,
5623+ "engines": {
5624+ "node": ">=0.10.0"
5625+ }
5626+ },
5627+ "node_modules/sprintf-js": {
5628+ "version": "1.1.3",
5629+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
5630+ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
5631+ "license": "BSD-3-Clause"
5632+ },
51685633 "node_modules/statuses": {
51695634 "version": "2.0.1",
51705635 "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
@@ -5378,6 +5843,12 @@
53785843 "utf8-byte-length": "^1.0.1"
53795844 }
53805845 },
5846+ "node_modules/tslib": {
5847+ "version": "2.7.0",
5848+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
5849+ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
5850+ "license": "0BSD"
5851+ },
53815852 "node_modules/tsscmp": {
53825853 "version": "1.0.6",
53835854 "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
@@ -5437,6 +5908,15 @@
54375908 "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
54385909 "license": "MIT"
54395910 },
5911+ "node_modules/universalify": {
5912+ "version": "2.0.1",
5913+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
5914+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
5915+ "license": "MIT",
5916+ "engines": {
5917+ "node": ">= 10.0.0"
5918+ }
5919+ },
54405920 "node_modules/unpipe": {
54415921 "version": "1.0.0",
54425922 "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
package.json+1 -0
@@ -30,6 +30,7 @@
3030 "png-chunk-text": "^1.0.0",
3131 "png-chunks-encode": "^1.0.0",
3232 "png-chunks-extract": "^1.0.0",
33+ "proxy-agent": "^6.4.0",
3334 "rate-limiter-flexible": "^5.0.0",
3435 "response-time": "^2.3.2",
3536 "sanitize-filename": "^1.6.3",
server.js+4 -0
@@ -37,6 +37,7 @@ util.inspect.defaultOptions.depth = 4;
3737const userModule = require('./src/users');
3838const basicAuthMiddleware = require('./src/middleware/basicAuth');
3939const whitelistMiddleware = require('./src/middleware/whitelist');
40+const initRequestProxy = require('./src/request-proxy');
4041const contentManager = require('./src/endpoints/content-manager');
4142const {
4243 getVersion,
@@ -662,6 +663,9 @@ const preSetupTasks = async function () {
662663 console.error('Uncaught exception:', err);
663664 exitProcess();
664665 });
666+
667+ // Add request proxy.
668+ initRequestProxy();
665669};
666670
667671/**
src/request-proxy.js+52 -0
@@ -0,0 +1,52 @@
1+const http = require('node:http');
2+const https = require('node:https');
3+
4+const { getConfigValue, isValidUrl, color } = require('./util.js');
5+
6+const LOG_HEADER = '[Request Proxy]';
7+
8+function initRequestProxy() {
9+ try {
10+ const { ProxyAgent } = require('proxy-agent');
11+ const proxyEnabled = getConfigValue('requestProxy.enabled', false);
12+
13+ // No proxy is enabled, so return
14+ if (!proxyEnabled) {
15+ return;
16+ }
17+
18+ const proxyUrl = getConfigValue('requestProxy.url', '');
19+
20+ if (!proxyUrl) {
21+ console.error(color.red(LOG_HEADER), 'No proxy URL provided');
22+ return;
23+ }
24+
25+ if (!isValidUrl(proxyUrl)) {
26+ console.error(color.red(LOG_HEADER), 'Invalid proxy URL provided');
27+ return;
28+ }
29+
30+ // ProxyAgent uses proxy-from-env under the hood
31+ // Reference: https://github.com/Rob--W/proxy-from-env
32+ process.env.all_proxy = proxyUrl;
33+
34+ const proxyBypass = getConfigValue('requestProxy.bypass', []);
35+
36+ if (Array.isArray(proxyBypass) && proxyBypass.length > 0) {
37+ process.env.no_proxy = proxyBypass.join(',');
38+ }
39+
40+ const proxyAgent = new ProxyAgent();
41+ http.globalAgent = proxyAgent;
42+ https.globalAgent = proxyAgent;
43+
44+ console.log();
45+ console.log(color.green(LOG_HEADER), 'Proxy URL is used:', color.blue(proxyUrl));
46+ console.log();
47+ } catch (error) {
48+ console.error(color.red(LOG_HEADER), 'Failed to initialize request proxy:', error);
49+ }
50+}
51+
52+module.exports = initRequestProxy;