diff --git a/client.js b/client.js index fabbf63..75bdf26 100644 --- a/client.js +++ b/client.js @@ -86,7 +86,7 @@ class Client extends EventEmitter { .map(announceUrl => { let parsedUrl try { - parsedUrl = new URL(announceUrl) + parsedUrl = common.parseUrl(announceUrl) } catch (err) { nextTickWarn(new Error(`Invalid tracker URL: ${announceUrl}`)) return null diff --git a/lib/client/udp-tracker.js b/lib/client/udp-tracker.js index 0f4c0e4..093ed4c 100644 --- a/lib/client/udp-tracker.js +++ b/lib/client/udp-tracker.js @@ -74,20 +74,7 @@ class UDPTracker extends Tracker { const self = this if (!opts) opts = {} - // HACK: Fix for WHATWG URL object not parsing non-standard URL schemes like - // 'udp:'. Just replace it with 'http:' since we only need the `hostname` - // and `port` properties. - // - // Note: Only affects Chrome and Firefox. Works fine in Node.js, Safari, and - // Edge. - // - // Note: UDP trackers aren't used in the normal browser build, but they are - // used in a Chrome App build (i.e. by Brave Browser). - // - // Bug reports: - // - Chrome: https://bugs.chromium.org/p/chromium/issues/detail?id=734880 - // - Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1374505 - let { hostname, port } = new URL(this.announceUrl.replace(/^udp:/, 'http:')) + let { hostname, port } = common.parseUrl(this.announceUrl) if (port === '') port = 80 let transactionId = genTransactionId() diff --git a/lib/common.js b/lib/common.js index 4e0e039..f6c9f1e 100644 --- a/lib/common.js +++ b/lib/common.js @@ -19,5 +19,36 @@ exports.hexToBinary = function (str) { return Buffer.from(str, 'hex').toString('binary') } +// HACK: Fix for WHATWG URL object not parsing non-standard URL schemes like +// 'udp:'. Just replace it with 'http:' since we only need a few properties. +// +// Note: Only affects Chrome and Firefox. Works fine in Node.js, Safari, and +// Edge. +// +// Note: UDP trackers aren't used in the normal browser build, but they are +// used in a Chrome App build (i.e. by Brave Browser). +// +// Bug reports: +// - Chrome: https://bugs.chromium.org/p/chromium/issues/detail?id=734880 +// - Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1374505 +exports.parseUrl = function (str) { + const isUDP = str.match(/^udp:/) + const parsedUrl = (isUDP) ? new URL(str.replace(/^udp:/, 'http:')) : new URL(str) + + return { + hash: parsedUrl.hash, + host: parsedUrl.host, + hostname: parsedUrl.hostname, + href: isUDP ? parsedUrl.href.replace(/^http:/, 'udp:') : parsedUrl.href, + origin: isUDP ? parsedUrl.origin.replace(/^http:/, 'udp:') : parsedUrl.origin, + password: parsedUrl.password, + pathname: parsedUrl.pathname, + port: parsedUrl.port, + protocol: isUDP ? 'udp:' : parsedUrl.protocol, + search: parsedUrl.search, + username: parsedUrl.username + } +} + const config = require('./common-node') Object.assign(exports, config) diff --git a/test/client.js b/test/client.js index 829574d..c34a27b 100644 --- a/test/client.js +++ b/test/client.js @@ -534,10 +534,34 @@ test('http: invalid tracker port', function (t) { testUnsupportedTracker(t, 'http://127.0.0.1:69691337/announce') }) +test('http: invalid tracker url', function (t) { + testUnsupportedTracker(t, 'http:') +}) + +test('http: invalid tracker url with slash', function (t) { + testUnsupportedTracker(t, 'http://') +}) + test('udp: invalid tracker port', function (t) { testUnsupportedTracker(t, 'udp://127.0.0.1:69691337') }) +test('udp: invalid tracker url', function (t) { + testUnsupportedTracker(t, 'udp:') +}) + +test('udp: invalid tracker url with slash', function (t) { + testUnsupportedTracker(t, 'udp://') +}) + test('ws: invalid tracker port', function (t) { testUnsupportedTracker(t, 'ws://127.0.0.1:69691337') }) + +test('ws: invalid tracker url', function (t) { + testUnsupportedTracker(t, 'ws:') +}) + +test('ws: invalid tracker url with slash', function (t) { + testUnsupportedTracker(t, 'ws://') +})