fix: UDP url parsing

This commit is contained in:
Alex 2021-05-20 21:38:51 +02:00
parent 2a12b75204
commit 8e24a8c97b
4 changed files with 57 additions and 15 deletions

View File

@ -86,7 +86,7 @@ class Client extends EventEmitter {
.map(announceUrl => { .map(announceUrl => {
let parsedUrl let parsedUrl
try { try {
parsedUrl = new URL(announceUrl) parsedUrl = common.parseUrl(announceUrl)
} catch (err) { } catch (err) {
nextTickWarn(new Error(`Invalid tracker URL: ${announceUrl}`)) nextTickWarn(new Error(`Invalid tracker URL: ${announceUrl}`))
return null return null

View File

@ -74,20 +74,7 @@ class UDPTracker extends Tracker {
const self = this const self = this
if (!opts) opts = {} if (!opts) opts = {}
// HACK: Fix for WHATWG URL object not parsing non-standard URL schemes like let { hostname, port } = common.parseUrl(this.announceUrl)
// '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:'))
if (port === '') port = 80 if (port === '') port = 80
let transactionId = genTransactionId() let transactionId = genTransactionId()

View File

@ -19,5 +19,36 @@ exports.hexToBinary = function (str) {
return Buffer.from(str, 'hex').toString('binary') 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') const config = require('./common-node')
Object.assign(exports, config) Object.assign(exports, config)

View File

@ -534,10 +534,34 @@ test('http: invalid tracker port', function (t) {
testUnsupportedTracker(t, 'http://127.0.0.1:69691337/announce') 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) { test('udp: invalid tracker port', function (t) {
testUnsupportedTracker(t, 'udp://127.0.0.1:69691337') 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) { test('ws: invalid tracker port', function (t) {
testUnsupportedTracker(t, 'ws://127.0.0.1:69691337') 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://')
})