Fix DDownload downloads failing due to SSL certificate verification

DDownload's storage servers (dstorage.org) use certificates that fail
Node.js TLS verification. Add skipTlsVerify flag to UnrestrictedLink
and temporarily disable TLS verification for the download fetch when
the flag is set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sucukdeluxe 2026-03-05 02:32:59 +01:00
parent 068da94e2a
commit 6db03f05a9
4 changed files with 19 additions and 6 deletions

View File

@ -1,6 +1,6 @@
{
"name": "real-debrid-downloader",
"version": "1.6.37",
"version": "1.6.38",
"description": "Desktop downloader",
"main": "build/main/main/main.js",
"author": "Sucukdeluxe",

View File

@ -1053,7 +1053,8 @@ class DdownloadClient {
fileName: filenameFromUrl(directUrl) || filenameFromUrl(link),
directUrl,
fileSize: null,
retriesUsed: attempt - 1
retriesUsed: attempt - 1,
skipTlsVerify: true
};
}
}
@ -1102,7 +1103,8 @@ class DdownloadClient {
fileName: fileName || filenameFromUrl(directUrl),
directUrl,
fileSize: null,
retriesUsed: attempt - 1
retriesUsed: attempt - 1,
skipTlsVerify: true
};
}
}
@ -1115,7 +1117,8 @@ class DdownloadClient {
fileName,
directUrl: directMatch[0],
fileSize: null,
retriesUsed: attempt - 1
retriesUsed: attempt - 1,
skipTlsVerify: true
};
}

View File

@ -4717,7 +4717,7 @@ export class DownloadManager extends EventEmitter {
item.updatedAt = nowMs();
this.emitState();
}
const result = await this.downloadToFile(active, unrestricted.directUrl, item.targetPath, item.totalBytes);
const result = await this.downloadToFile(active, unrestricted.directUrl, item.targetPath, item.totalBytes, unrestricted.skipTlsVerify);
active.resumable = result.resumable;
if (!active.resumable && !active.nonResumableCounted) {
active.nonResumableCounted = true;
@ -5102,7 +5102,8 @@ export class DownloadManager extends EventEmitter {
active: ActiveTask,
directUrl: string,
targetPath: string,
knownTotal: number | null
knownTotal: number | null,
skipTlsVerify?: boolean
): Promise<{ resumable: boolean }> {
const item = this.session.items[active.itemId];
if (!item) {
@ -5148,12 +5149,16 @@ export class DownloadManager extends EventEmitter {
const connectTimeoutMs = getDownloadConnectTimeoutMs();
let connectTimer: NodeJS.Timeout | null = null;
const connectAbortController = new AbortController();
const prevTlsReject = process.env.NODE_TLS_REJECT_UNAUTHORIZED;
try {
if (connectTimeoutMs > 0) {
connectTimer = setTimeout(() => {
connectAbortController.abort("connect_timeout");
}, connectTimeoutMs);
}
if (skipTlsVerify) {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
}
response = await fetch(directUrl, {
method: "GET",
headers,
@ -5173,6 +5178,10 @@ export class DownloadManager extends EventEmitter {
}
throw error;
} finally {
if (skipTlsVerify) {
if (prevTlsReject === undefined) delete process.env.NODE_TLS_REJECT_UNAUTHORIZED;
else process.env.NODE_TLS_REJECT_UNAUTHORIZED = prevTlsReject;
}
if (connectTimer) {
clearTimeout(connectTimer);
}

View File

@ -8,6 +8,7 @@ export interface UnrestrictedLink {
directUrl: string;
fileSize: number | null;
retriesUsed: number;
skipTlsVerify?: boolean;
}
function shouldRetryStatus(status: number): boolean {