This commit is contained in:
1 parent
4bd2088edd
commit
608164dfdd
6 files changed
+155
-29
No files matched your search
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xtream-proxy",
|
||||
"version": "2.0.0",
|
||||
"version": "3.0.0",
|
||||
"private": true,
|
||||
"description": "Proxies the fastest available upstream from a list of Xtream Codes credentials",
|
||||
"scripts": {
|
||||
|
||||
@@ -20,37 +20,65 @@ function readConfigEntries() {
|
||||
|
||||
const entries = [];
|
||||
data.forEach((item, index) => {
|
||||
const label = `Config entry #${index + 1}`;
|
||||
if (!item || typeof item !== 'object' || Array.isArray(item)) {
|
||||
console.warn(`Config entry #${index + 1}: not an object, skipping`);
|
||||
console.warn(`${label}: not an object, skipping`);
|
||||
return;
|
||||
}
|
||||
const { url, username, password } = item;
|
||||
if (typeof url !== 'string' || !url.trim()) {
|
||||
console.warn(`Config entry #${index + 1}: missing url, skipping`);
|
||||
|
||||
if (item.url !== undefined) {
|
||||
console.warn(`${label}: "url" is no longer supported and is ignored, use "urls"`);
|
||||
}
|
||||
|
||||
const { urls, username, password } = item;
|
||||
if (!Array.isArray(urls) || urls.length === 0) {
|
||||
console.warn(`${label}: missing non-empty urls array, skipping`);
|
||||
return;
|
||||
}
|
||||
if (typeof username !== 'string' || !username) {
|
||||
console.warn(`Config entry #${index + 1}: missing username, skipping`);
|
||||
console.warn(`${label}: missing username, skipping`);
|
||||
return;
|
||||
}
|
||||
if (typeof password !== 'string' || !password) {
|
||||
console.warn(`Config entry #${index + 1}: missing password, skipping`);
|
||||
console.warn(`${label}: missing password, skipping`);
|
||||
return;
|
||||
}
|
||||
|
||||
let parsed;
|
||||
try {
|
||||
parsed = new URL(url);
|
||||
} catch {
|
||||
console.warn(`Config entry #${index + 1}: invalid url, skipping`);
|
||||
return;
|
||||
}
|
||||
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
||||
console.warn(`Config entry #${index + 1}: url must be http(s), skipping`);
|
||||
const validUrls = [];
|
||||
const seenUrls = new Set();
|
||||
urls.forEach((rawUrl, urlIndex) => {
|
||||
const urlLabel = `${label} url #${urlIndex + 1}`;
|
||||
if (typeof rawUrl !== 'string' || !rawUrl.trim()) {
|
||||
console.warn(`${urlLabel}: missing url, skipping`);
|
||||
return;
|
||||
}
|
||||
|
||||
const url = rawUrl.trim();
|
||||
let parsed;
|
||||
try {
|
||||
parsed = new URL(url);
|
||||
} catch {
|
||||
console.warn(`${urlLabel}: invalid url, skipping`);
|
||||
return;
|
||||
}
|
||||
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
||||
console.warn(`${urlLabel}: url must be http(s), skipping`);
|
||||
return;
|
||||
}
|
||||
if (seenUrls.has(url)) return;
|
||||
|
||||
seenUrls.add(url);
|
||||
validUrls.push(url);
|
||||
});
|
||||
|
||||
if (validUrls.length === 0) {
|
||||
console.warn(`${label}: no valid urls, skipping`);
|
||||
return;
|
||||
}
|
||||
|
||||
entries.push({ url, username, password });
|
||||
for (const url of validUrls) {
|
||||
entries.push({ url, username, password });
|
||||
}
|
||||
});
|
||||
return entries;
|
||||
}
|
||||
@@ -78,7 +106,7 @@ function reloadConfig() {
|
||||
const removed = upstreams.filter((u) => !seen.has(u.key)).length;
|
||||
const added = next.filter((u) => !previous.has(u.key)).length;
|
||||
if (added || removed) {
|
||||
console.log(`Config reloaded: ${next.length} upstream(s), +${added} / -${removed}`);
|
||||
console.log(`Config reloaded: ${next.length} upstream URL(s), +${added} / -${removed}`);
|
||||
}
|
||||
|
||||
upstreams = next;
|
||||
|
||||
@@ -21,7 +21,7 @@ const settings = {
|
||||
),
|
||||
rejectUnauthorized: process.env.PROXY_INSECURE_TLS !== '1',
|
||||
allowBusyFallback: process.env.ALLOW_BUSY_FALLBACK !== '0',
|
||||
userAgent: process.env.USER_AGENT || 'xtream-proxy/2.0',
|
||||
userAgent: process.env.USER_AGENT || 'xtream-proxy/3.0',
|
||||
};
|
||||
|
||||
function validate() {
|
||||
|
||||
@@ -70,7 +70,7 @@ function describeUpstream(upstream) {
|
||||
|
||||
function logProbeResults(snapshot) {
|
||||
if (snapshot.length === 0) {
|
||||
console.warn(`No upstreams configured in ${settings.configFile}`);
|
||||
console.warn(`No upstream URLs configured in ${settings.configFile}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
#
|
||||
# Every entry must point to an Xtream-compatible panel that serves the same
|
||||
# content. The proxy probes each entry via /player_api.php and picks the
|
||||
# fastest one that is not at its connection limit.
|
||||
#
|
||||
# The URL may include a path prefix, e.g. https://example.com/portal
|
||||
#
|
||||
[
|
||||
{
|
||||
"url": "http://panel1.example.com:8080",
|
||||
"urls": [
|
||||
"http://panel1.example.com:8080",
|
||||
"https://panel1.example.com"
|
||||
],
|
||||
"username": "user1",
|
||||
"password": "pass1"
|
||||
},
|
||||
{
|
||||
"url": "https://panel2.example.com",
|
||||
"urls": [
|
||||
"https://panel2.example.com"
|
||||
],
|
||||
"username": "user2",
|
||||
"password": "pass2"
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user