Skip to content

Commit bce64e1

Browse files
authored
feat(major): drop simple-get (#443)
BREAKING CHANGE: drop simple-get * perf: drop simple-get * feat: undici agent and socks * fix: undici as dev dependency * feat: require user passed proxy objects for http and ws * chore: include undici for tests
1 parent e14738b commit bce64e1

File tree

7 files changed

+242
-230
lines changed

7 files changed

+242
-230
lines changed

README.md

Lines changed: 19 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,16 @@ npm install bittorrent-tracker
5555
To connect to a tracker, just do this:
5656

5757
```js
58-
var Client = require('bittorrent-tracker')
58+
import Client from 'bittorrent-tracker'
5959

60-
var requiredOpts = {
60+
const requiredOpts = {
6161
infoHash: new Buffer('012345678901234567890'), // hex string or Buffer
6262
peerId: new Buffer('01234567890123456789'), // hex string or Buffer
6363
announce: [], // list of tracker server urls
6464
port: 6881 // torrent client port, (in browser, optional)
6565
}
6666

67-
var optionalOpts = {
67+
const optionalOpts = {
6868
// RTCPeerConnection config object (only used in browser)
6969
rtcConfig: {},
7070
// User-Agent header for http requests
@@ -81,47 +81,24 @@ var optionalOpts = {
8181
customParam: 'blah' // custom parameters supported
8282
}
8383
},
84-
// Proxy config object
84+
// Proxy options (used to proxy requests in node)
8585
proxyOpts: {
86-
// Socks proxy options (used to proxy requests in node)
87-
socksProxy: {
88-
// Configuration from socks module (https://github.com/JoshGlazebrook/socks)
89-
proxy: {
90-
// IP Address of Proxy (Required)
91-
ipaddress: "1.2.3.4",
92-
// TCP Port of Proxy (Required)
93-
port: 1080,
94-
// Proxy Type [4, 5] (Required)
95-
// Note: 4 works for both 4 and 4a.
96-
// Type 4 does not support UDP association relay
97-
type: 5,
98-
99-
// SOCKS 4 Specific:
100-
101-
// UserId used when making a SOCKS 4/4a request. (Optional)
102-
userid: "someuserid",
103-
104-
// SOCKS 5 Specific:
105-
106-
// Authentication used for SOCKS 5 (when it's required) (Optional)
107-
authentication: {
108-
username: "Josh",
109-
password: "somepassword"
110-
}
111-
},
112-
113-
// Amount of time to wait for a connection to be established. (Optional)
114-
// - defaults to 10000ms (10 seconds)
115-
timeout: 10000
116-
},
117-
// NodeJS HTTP agents (used to proxy HTTP and Websocket requests in node)
118-
// Populated with Socks.Agent if socksProxy is provided
119-
httpAgent: {},
120-
httpsAgent: {}
86+
// For WSS trackers this is always a http.Agent
87+
// For UDP trackers this is an object of options for the Socks Connection
88+
// For HTTP trackers this is either an undici Agent if using Node16 or later, or http.Agent if using versions prior to Node 16, ex:
89+
// import Socks from 'socks'
90+
// proxyOpts.socksProxy = new Socks.Agent(optionsObject, isHttps)
91+
// or if using Node 16 or later
92+
// import { socksDispatcher } from 'fetch-socks'
93+
// proxyOpts.socksProxy = socksDispatcher(optionsObject)
94+
socksProxy: new SocksProxy(socksOptionsObject),
95+
// Populated with socksProxy if it's provided
96+
httpAgent: new http.Agent(agentOptionsObject),
97+
httpsAgent: new https.Agent(agentOptionsObject)
12198
},
12299
}
123100

124-
var client = new Client(requiredOpts)
101+
const client = new Client(requiredOpts)
125102

126103
client.on('error', function (err) {
127104
// fatal client error!
@@ -182,7 +159,7 @@ client.on('scrape', function (data) {
182159
To start a BitTorrent tracker server to track swarms of peers:
183160

184161
```js
185-
const Server = require('bittorrent-tracker').Server
162+
import { Server } from 'bittorrent-tracker'
186163

187164
const server = new Server({
188165
udp: true, // enable udp server? [default=true]
@@ -289,7 +266,7 @@ The http server will handle requests for the following paths: `/announce`, `/scr
289266
Scraping multiple torrent info is possible with a static `Client.scrape` method:
290267

291268
```js
292-
var Client = require('bittorrent-tracker')
269+
import Client from 'bittorrent-tracker'
293270
Client.scrape({ announce: announceUrl, infoHash: [ infoHash1, infoHash2 ]}, function (err, results) {
294271
results[infoHash1].announce
295272
results[infoHash1].infoHash

lib/client/http-tracker.js

Lines changed: 58 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import arrayRemove from 'unordered-array-remove'
22
import bencode from 'bencode'
3-
import clone from 'clone'
43
import Debug from 'debug'
5-
import get from 'simple-get'
6-
import Socks from 'socks'
4+
import fetch from 'cross-fetch-ponyfill'
75
import { bin2hex, hex2bin, arr2text, text2arr, arr2hex } from 'uint8-util'
86

97
import common from '../common.js'
@@ -13,6 +11,14 @@ import compact2string from 'compact2string'
1311
const debug = Debug('bittorrent-tracker:http-tracker')
1412
const HTTP_SCRAPE_SUPPORT = /\/(announce)[^/]*$/
1513

14+
function abortTimeout (ms) {
15+
const controller = new AbortController()
16+
setTimeout(() => {
17+
controller.abort()
18+
}, ms).unref?.()
19+
return controller
20+
}
21+
1622
/**
1723
* HTTP torrent tracker client (for an individual tracker)
1824
*
@@ -112,70 +118,72 @@ class HTTPTracker extends Tracker {
112118
}
113119
}
114120

115-
_request (requestUrl, params, cb) {
116-
const self = this
121+
async _request (requestUrl, params, cb) {
117122
const parsedUrl = new URL(requestUrl + (requestUrl.indexOf('?') === -1 ? '?' : '&') + common.querystringStringify(params))
118123
let agent
119124
if (this.client._proxyOpts) {
120125
agent = parsedUrl.protocol === 'https:' ? this.client._proxyOpts.httpsAgent : this.client._proxyOpts.httpAgent
121126
if (!agent && this.client._proxyOpts.socksProxy) {
122-
agent = new Socks.Agent(clone(this.client._proxyOpts.socksProxy), (parsedUrl.protocol === 'https:'))
127+
agent = this.client._proxyOpts.socksProxy
123128
}
124129
}
125130

126-
this.cleanupFns.push(cleanup)
127-
128-
let request = get.concat({
129-
url: parsedUrl.toString(),
130-
agent,
131-
timeout: common.REQUEST_TIMEOUT,
132-
headers: {
133-
'user-agent': this.client._userAgent || ''
134-
}
135-
}, onResponse)
136-
137-
function cleanup () {
138-
if (request) {
139-
arrayRemove(self.cleanupFns, self.cleanupFns.indexOf(cleanup))
140-
request.abort()
141-
request = null
131+
const cleanup = () => {
132+
if (!controller.signal.aborted) {
133+
arrayRemove(this.cleanupFns, this.cleanupFns.indexOf(cleanup))
134+
controller.abort()
135+
controller = null
142136
}
143-
if (self.maybeDestroyCleanup) self.maybeDestroyCleanup()
137+
if (this.maybeDestroyCleanup) this.maybeDestroyCleanup()
144138
}
145139

146-
function onResponse (err, res, data) {
147-
cleanup()
148-
if (self.destroyed) return
140+
this.cleanupFns.push(cleanup)
149141

142+
let res
143+
let controller = abortTimeout(common.REQUEST_TIMEOUT)
144+
try {
145+
res = await fetch(parsedUrl.toString(), {
146+
agent,
147+
signal: controller.signal,
148+
dispatcher: agent,
149+
headers: {
150+
'user-agent': this.client._userAgent || ''
151+
}
152+
})
153+
} catch (err) {
150154
if (err) return cb(err)
151-
if (res.statusCode !== 200) {
152-
return cb(new Error(`Non-200 response code ${res.statusCode} from ${self.announceUrl}`))
153-
}
154-
if (!data || data.length === 0) {
155-
return cb(new Error(`Invalid tracker response from${self.announceUrl}`))
156-
}
157-
158-
try {
159-
data = bencode.decode(data)
160-
} catch (err) {
161-
return cb(new Error(`Error decoding tracker response: ${err.message}`))
162-
}
163-
const failure = data['failure reason'] && arr2text(data['failure reason'])
164-
if (failure) {
165-
debug(`failure from ${requestUrl} (${failure})`)
166-
return cb(new Error(failure))
167-
}
155+
}
156+
let data = new Uint8Array(await res.arrayBuffer())
157+
cleanup()
158+
if (this.destroyed) return
168159

169-
const warning = data['warning message'] && arr2text(data['warning message'])
170-
if (warning) {
171-
debug(`warning from ${requestUrl} (${warning})`)
172-
self.client.emit('warning', new Error(warning))
173-
}
160+
if (res.status !== 200) {
161+
return cb(new Error(`Non-200 response code ${res.statusCode} from ${this.announceUrl}`))
162+
}
163+
if (!data || data.length === 0) {
164+
return cb(new Error(`Invalid tracker response from${this.announceUrl}`))
165+
}
174166

175-
debug(`response from ${requestUrl}`)
167+
try {
168+
data = bencode.decode(data)
169+
} catch (err) {
170+
return cb(new Error(`Error decoding tracker response: ${err.message}`))
171+
}
172+
const failure = data['failure reason'] && arr2text(data['failure reason'])
173+
if (failure) {
174+
debug(`failure from ${requestUrl} (${failure})`)
175+
return cb(new Error(failure))
176+
}
176177

177-
cb(null, data)
178+
const warning = data['warning message'] && arr2text(data['warning message'])
179+
if (warning) {
180+
debug(`warning from ${requestUrl} (${warning})`)
181+
this.client.emit('warning', new Error(warning))
178182
}
183+
184+
debug(`response from ${requestUrl}`)
185+
186+
cb(null, data)
179187
}
180188

181189
_onAnnounceResponse (data) {

lib/client/websocket-tracker.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import clone from 'clone'
21
import Debug from 'debug'
32
import Peer from '@thaunknown/simple-peer/lite.js'
43
import Socket from '@thaunknown/simple-websocket'
5-
import Socks from 'socks'
64
import { arr2text, arr2hex, hex2bin, bin2hex, randomBytes } from 'uint8-util'
75

86
import common from '../common.js'
@@ -185,7 +183,7 @@ class WebSocketTracker extends Tracker {
185183
if (this.client._proxyOpts) {
186184
agent = parsedUrl.protocol === 'wss:' ? this.client._proxyOpts.httpsAgent : this.client._proxyOpts.httpAgent
187185
if (!agent && this.client._proxyOpts.socksProxy) {
188-
agent = new Socks.Agent(clone(this.client._proxyOpts.socksProxy), (parsedUrl.protocol === 'wss:'))
186+
agent = this.client._proxyOpts.socksProxy
189187
}
190188
}
191189
this.socket = socketPool[this.announceUrl] = new Socket({ url: this.announceUrl, agent })

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"chrome-dgram": "^3.0.6",
3535
"clone": "^2.0.0",
3636
"compact2string": "^1.4.1",
37+
"cross-fetch-ponyfill": "^1.0.1",
3738
"debug": "^4.1.1",
3839
"ip": "^1.1.5",
3940
"lru": "^3.1.0",
@@ -43,7 +44,6 @@
4344
"random-iterate": "^1.0.1",
4445
"run-parallel": "^1.2.0",
4546
"run-series": "^1.1.9",
46-
"simple-get": "^4.0.0",
4747
"socks": "^2.0.0",
4848
"string2compact": "^2.0.0",
4949
"uint8-util": "^2.1.9",
@@ -57,6 +57,7 @@
5757
"semantic-release": "21.1.2",
5858
"standard": "*",
5959
"tape": "5.7.2",
60+
"undici": "^5.27.0",
6061
"webtorrent-fixtures": "2.0.2",
6162
"wrtc": "0.4.7"
6263
},

test/client.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import http from 'http'
44
import fixtures from 'webtorrent-fixtures'
55
import net from 'net'
66
import test from 'tape'
7+
import undici from 'undici'
78

89
const peerId1 = Buffer.from('01234567890123456789')
910
const peerId2 = Buffer.from('12345678901234567890')
@@ -572,12 +573,29 @@ function testClientStartHttpAgent (t, serverType) {
572573
t.plan(5)
573574

574575
common.createServer(t, serverType, function (server, announceUrl) {
575-
const agent = new http.Agent()
576-
let agentUsed = false
577-
agent.createConnection = function (opts, fn) {
578-
agentUsed = true
579-
return net.createConnection(opts, fn)
576+
let agent
577+
if (global.fetch && serverType !== 'ws') {
578+
const connector = undici.buildConnector({ rejectUnauthorized: false })
579+
agent = new undici.Agent({
580+
connect (opts, cb) {
581+
agentUsed = true
582+
connector(opts, (err, socket) => {
583+
if (err) {
584+
cb(err, null)
585+
} else {
586+
cb(null, socket)
587+
}
588+
})
589+
}
590+
})
591+
} else {
592+
agent = new http.Agent()
593+
agent.createConnection = function (opts, fn) {
594+
agentUsed = true
595+
return net.createConnection(opts, fn)
596+
}
580597
}
598+
let agentUsed = false
581599
const client = new Client({
582600
infoHash: fixtures.leaves.parsedTorrent.infoHash,
583601
announce: announceUrl,

0 commit comments

Comments
 (0)