mirror of
https://github.com/webtorrent/bittorrent-tracker.git
synced 2025-01-18 04:01:35 +00:00
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
This commit is contained in:
parent
e14738bd84
commit
bce64e155d
61
README.md
61
README.md
@ -55,16 +55,16 @@ npm install bittorrent-tracker
|
||||
To connect to a tracker, just do this:
|
||||
|
||||
```js
|
||||
var Client = require('bittorrent-tracker')
|
||||
import Client from 'bittorrent-tracker'
|
||||
|
||||
var requiredOpts = {
|
||||
const requiredOpts = {
|
||||
infoHash: new Buffer('012345678901234567890'), // hex string or Buffer
|
||||
peerId: new Buffer('01234567890123456789'), // hex string or Buffer
|
||||
announce: [], // list of tracker server urls
|
||||
port: 6881 // torrent client port, (in browser, optional)
|
||||
}
|
||||
|
||||
var optionalOpts = {
|
||||
const optionalOpts = {
|
||||
// RTCPeerConnection config object (only used in browser)
|
||||
rtcConfig: {},
|
||||
// User-Agent header for http requests
|
||||
@ -81,47 +81,24 @@ var optionalOpts = {
|
||||
customParam: 'blah' // custom parameters supported
|
||||
}
|
||||
},
|
||||
// Proxy config object
|
||||
// Proxy options (used to proxy requests in node)
|
||||
proxyOpts: {
|
||||
// Socks proxy options (used to proxy requests in node)
|
||||
socksProxy: {
|
||||
// Configuration from socks module (https://github.com/JoshGlazebrook/socks)
|
||||
proxy: {
|
||||
// IP Address of Proxy (Required)
|
||||
ipaddress: "1.2.3.4",
|
||||
// TCP Port of Proxy (Required)
|
||||
port: 1080,
|
||||
// Proxy Type [4, 5] (Required)
|
||||
// Note: 4 works for both 4 and 4a.
|
||||
// Type 4 does not support UDP association relay
|
||||
type: 5,
|
||||
|
||||
// SOCKS 4 Specific:
|
||||
|
||||
// UserId used when making a SOCKS 4/4a request. (Optional)
|
||||
userid: "someuserid",
|
||||
|
||||
// SOCKS 5 Specific:
|
||||
|
||||
// Authentication used for SOCKS 5 (when it's required) (Optional)
|
||||
authentication: {
|
||||
username: "Josh",
|
||||
password: "somepassword"
|
||||
}
|
||||
},
|
||||
|
||||
// Amount of time to wait for a connection to be established. (Optional)
|
||||
// - defaults to 10000ms (10 seconds)
|
||||
timeout: 10000
|
||||
},
|
||||
// NodeJS HTTP agents (used to proxy HTTP and Websocket requests in node)
|
||||
// Populated with Socks.Agent if socksProxy is provided
|
||||
httpAgent: {},
|
||||
httpsAgent: {}
|
||||
// For WSS trackers this is always a http.Agent
|
||||
// For UDP trackers this is an object of options for the Socks Connection
|
||||
// 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:
|
||||
// import Socks from 'socks'
|
||||
// proxyOpts.socksProxy = new Socks.Agent(optionsObject, isHttps)
|
||||
// or if using Node 16 or later
|
||||
// import { socksDispatcher } from 'fetch-socks'
|
||||
// proxyOpts.socksProxy = socksDispatcher(optionsObject)
|
||||
socksProxy: new SocksProxy(socksOptionsObject),
|
||||
// Populated with socksProxy if it's provided
|
||||
httpAgent: new http.Agent(agentOptionsObject),
|
||||
httpsAgent: new https.Agent(agentOptionsObject)
|
||||
},
|
||||
}
|
||||
|
||||
var client = new Client(requiredOpts)
|
||||
const client = new Client(requiredOpts)
|
||||
|
||||
client.on('error', function (err) {
|
||||
// fatal client error!
|
||||
@ -182,7 +159,7 @@ client.on('scrape', function (data) {
|
||||
To start a BitTorrent tracker server to track swarms of peers:
|
||||
|
||||
```js
|
||||
const Server = require('bittorrent-tracker').Server
|
||||
import { Server } from 'bittorrent-tracker'
|
||||
|
||||
const server = new Server({
|
||||
udp: true, // enable udp server? [default=true]
|
||||
@ -289,7 +266,7 @@ The http server will handle requests for the following paths: `/announce`, `/scr
|
||||
Scraping multiple torrent info is possible with a static `Client.scrape` method:
|
||||
|
||||
```js
|
||||
var Client = require('bittorrent-tracker')
|
||||
import Client from 'bittorrent-tracker'
|
||||
Client.scrape({ announce: announceUrl, infoHash: [ infoHash1, infoHash2 ]}, function (err, results) {
|
||||
results[infoHash1].announce
|
||||
results[infoHash1].infoHash
|
||||
|
@ -1,9 +1,7 @@
|
||||
import arrayRemove from 'unordered-array-remove'
|
||||
import bencode from 'bencode'
|
||||
import clone from 'clone'
|
||||
import Debug from 'debug'
|
||||
import get from 'simple-get'
|
||||
import Socks from 'socks'
|
||||
import fetch from 'cross-fetch-ponyfill'
|
||||
import { bin2hex, hex2bin, arr2text, text2arr, arr2hex } from 'uint8-util'
|
||||
|
||||
import common from '../common.js'
|
||||
@ -13,6 +11,14 @@ import compact2string from 'compact2string'
|
||||
const debug = Debug('bittorrent-tracker:http-tracker')
|
||||
const HTTP_SCRAPE_SUPPORT = /\/(announce)[^/]*$/
|
||||
|
||||
function abortTimeout (ms) {
|
||||
const controller = new AbortController()
|
||||
setTimeout(() => {
|
||||
controller.abort()
|
||||
}, ms).unref?.()
|
||||
return controller
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP torrent tracker client (for an individual tracker)
|
||||
*
|
||||
@ -112,70 +118,72 @@ class HTTPTracker extends Tracker {
|
||||
}
|
||||
}
|
||||
|
||||
_request (requestUrl, params, cb) {
|
||||
const self = this
|
||||
async _request (requestUrl, params, cb) {
|
||||
const parsedUrl = new URL(requestUrl + (requestUrl.indexOf('?') === -1 ? '?' : '&') + common.querystringStringify(params))
|
||||
let agent
|
||||
if (this.client._proxyOpts) {
|
||||
agent = parsedUrl.protocol === 'https:' ? this.client._proxyOpts.httpsAgent : this.client._proxyOpts.httpAgent
|
||||
if (!agent && this.client._proxyOpts.socksProxy) {
|
||||
agent = new Socks.Agent(clone(this.client._proxyOpts.socksProxy), (parsedUrl.protocol === 'https:'))
|
||||
agent = this.client._proxyOpts.socksProxy
|
||||
}
|
||||
}
|
||||
|
||||
const cleanup = () => {
|
||||
if (!controller.signal.aborted) {
|
||||
arrayRemove(this.cleanupFns, this.cleanupFns.indexOf(cleanup))
|
||||
controller.abort()
|
||||
controller = null
|
||||
}
|
||||
if (this.maybeDestroyCleanup) this.maybeDestroyCleanup()
|
||||
}
|
||||
|
||||
this.cleanupFns.push(cleanup)
|
||||
|
||||
let request = get.concat({
|
||||
url: parsedUrl.toString(),
|
||||
agent,
|
||||
timeout: common.REQUEST_TIMEOUT,
|
||||
headers: {
|
||||
'user-agent': this.client._userAgent || ''
|
||||
}
|
||||
}, onResponse)
|
||||
|
||||
function cleanup () {
|
||||
if (request) {
|
||||
arrayRemove(self.cleanupFns, self.cleanupFns.indexOf(cleanup))
|
||||
request.abort()
|
||||
request = null
|
||||
}
|
||||
if (self.maybeDestroyCleanup) self.maybeDestroyCleanup()
|
||||
}
|
||||
|
||||
function onResponse (err, res, data) {
|
||||
cleanup()
|
||||
if (self.destroyed) return
|
||||
|
||||
let res
|
||||
let controller = abortTimeout(common.REQUEST_TIMEOUT)
|
||||
try {
|
||||
res = await fetch(parsedUrl.toString(), {
|
||||
agent,
|
||||
signal: controller.signal,
|
||||
dispatcher: agent,
|
||||
headers: {
|
||||
'user-agent': this.client._userAgent || ''
|
||||
}
|
||||
})
|
||||
} catch (err) {
|
||||
if (err) return cb(err)
|
||||
if (res.statusCode !== 200) {
|
||||
return cb(new Error(`Non-200 response code ${res.statusCode} from ${self.announceUrl}`))
|
||||
}
|
||||
if (!data || data.length === 0) {
|
||||
return cb(new Error(`Invalid tracker response from${self.announceUrl}`))
|
||||
}
|
||||
|
||||
try {
|
||||
data = bencode.decode(data)
|
||||
} catch (err) {
|
||||
return cb(new Error(`Error decoding tracker response: ${err.message}`))
|
||||
}
|
||||
const failure = data['failure reason'] && arr2text(data['failure reason'])
|
||||
if (failure) {
|
||||
debug(`failure from ${requestUrl} (${failure})`)
|
||||
return cb(new Error(failure))
|
||||
}
|
||||
|
||||
const warning = data['warning message'] && arr2text(data['warning message'])
|
||||
if (warning) {
|
||||
debug(`warning from ${requestUrl} (${warning})`)
|
||||
self.client.emit('warning', new Error(warning))
|
||||
}
|
||||
|
||||
debug(`response from ${requestUrl}`)
|
||||
|
||||
cb(null, data)
|
||||
}
|
||||
let data = new Uint8Array(await res.arrayBuffer())
|
||||
cleanup()
|
||||
if (this.destroyed) return
|
||||
|
||||
if (res.status !== 200) {
|
||||
return cb(new Error(`Non-200 response code ${res.statusCode} from ${this.announceUrl}`))
|
||||
}
|
||||
if (!data || data.length === 0) {
|
||||
return cb(new Error(`Invalid tracker response from${this.announceUrl}`))
|
||||
}
|
||||
|
||||
try {
|
||||
data = bencode.decode(data)
|
||||
} catch (err) {
|
||||
return cb(new Error(`Error decoding tracker response: ${err.message}`))
|
||||
}
|
||||
const failure = data['failure reason'] && arr2text(data['failure reason'])
|
||||
if (failure) {
|
||||
debug(`failure from ${requestUrl} (${failure})`)
|
||||
return cb(new Error(failure))
|
||||
}
|
||||
|
||||
const warning = data['warning message'] && arr2text(data['warning message'])
|
||||
if (warning) {
|
||||
debug(`warning from ${requestUrl} (${warning})`)
|
||||
this.client.emit('warning', new Error(warning))
|
||||
}
|
||||
|
||||
debug(`response from ${requestUrl}`)
|
||||
|
||||
cb(null, data)
|
||||
}
|
||||
|
||||
_onAnnounceResponse (data) {
|
||||
|
@ -1,8 +1,6 @@
|
||||
import clone from 'clone'
|
||||
import Debug from 'debug'
|
||||
import Peer from '@thaunknown/simple-peer/lite.js'
|
||||
import Socket from '@thaunknown/simple-websocket'
|
||||
import Socks from 'socks'
|
||||
import { arr2text, arr2hex, hex2bin, bin2hex, randomBytes } from 'uint8-util'
|
||||
|
||||
import common from '../common.js'
|
||||
@ -185,7 +183,7 @@ class WebSocketTracker extends Tracker {
|
||||
if (this.client._proxyOpts) {
|
||||
agent = parsedUrl.protocol === 'wss:' ? this.client._proxyOpts.httpsAgent : this.client._proxyOpts.httpAgent
|
||||
if (!agent && this.client._proxyOpts.socksProxy) {
|
||||
agent = new Socks.Agent(clone(this.client._proxyOpts.socksProxy), (parsedUrl.protocol === 'wss:'))
|
||||
agent = this.client._proxyOpts.socksProxy
|
||||
}
|
||||
}
|
||||
this.socket = socketPool[this.announceUrl] = new Socket({ url: this.announceUrl, agent })
|
||||
|
@ -34,6 +34,7 @@
|
||||
"chrome-dgram": "^3.0.6",
|
||||
"clone": "^2.0.0",
|
||||
"compact2string": "^1.4.1",
|
||||
"cross-fetch-ponyfill": "^1.0.1",
|
||||
"debug": "^4.1.1",
|
||||
"ip": "^1.1.5",
|
||||
"lru": "^3.1.0",
|
||||
@ -43,7 +44,6 @@
|
||||
"random-iterate": "^1.0.1",
|
||||
"run-parallel": "^1.2.0",
|
||||
"run-series": "^1.1.9",
|
||||
"simple-get": "^4.0.0",
|
||||
"socks": "^2.0.0",
|
||||
"string2compact": "^2.0.0",
|
||||
"uint8-util": "^2.1.9",
|
||||
@ -57,6 +57,7 @@
|
||||
"semantic-release": "21.1.2",
|
||||
"standard": "*",
|
||||
"tape": "5.7.2",
|
||||
"undici": "^5.27.0",
|
||||
"webtorrent-fixtures": "2.0.2",
|
||||
"wrtc": "0.4.7"
|
||||
},
|
||||
|
@ -4,6 +4,7 @@ import http from 'http'
|
||||
import fixtures from 'webtorrent-fixtures'
|
||||
import net from 'net'
|
||||
import test from 'tape'
|
||||
import undici from 'undici'
|
||||
|
||||
const peerId1 = Buffer.from('01234567890123456789')
|
||||
const peerId2 = Buffer.from('12345678901234567890')
|
||||
@ -572,12 +573,29 @@ function testClientStartHttpAgent (t, serverType) {
|
||||
t.plan(5)
|
||||
|
||||
common.createServer(t, serverType, function (server, announceUrl) {
|
||||
const agent = new http.Agent()
|
||||
let agentUsed = false
|
||||
agent.createConnection = function (opts, fn) {
|
||||
agentUsed = true
|
||||
return net.createConnection(opts, fn)
|
||||
let agent
|
||||
if (global.fetch && serverType !== 'ws') {
|
||||
const connector = undici.buildConnector({ rejectUnauthorized: false })
|
||||
agent = new undici.Agent({
|
||||
connect (opts, cb) {
|
||||
agentUsed = true
|
||||
connector(opts, (err, socket) => {
|
||||
if (err) {
|
||||
cb(err, null)
|
||||
} else {
|
||||
cb(null, socket)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
agent = new http.Agent()
|
||||
agent.createConnection = function (opts, fn) {
|
||||
agentUsed = true
|
||||
return net.createConnection(opts, fn)
|
||||
}
|
||||
}
|
||||
let agentUsed = false
|
||||
const client = new Client({
|
||||
infoHash: fixtures.leaves.parsedTorrent.infoHash,
|
||||
announce: announceUrl,
|
||||
|
@ -3,7 +3,7 @@ import Client from '../index.js'
|
||||
import common from './common.js'
|
||||
import commonLib from '../lib/common.js'
|
||||
import fixtures from 'webtorrent-fixtures'
|
||||
import get from 'simple-get'
|
||||
import fetch from 'cross-fetch-ponyfill'
|
||||
import test from 'tape'
|
||||
import { hex2bin } from 'uint8-util'
|
||||
|
||||
@ -151,44 +151,47 @@ test('udp: MULTI scrape using Client.scrape static method', t => {
|
||||
})
|
||||
|
||||
test('server: multiple info_hash scrape (manual http request)', t => {
|
||||
t.plan(13)
|
||||
t.plan(12)
|
||||
|
||||
const binaryInfoHash1 = hex2bin(fixtures.leaves.parsedTorrent.infoHash)
|
||||
const binaryInfoHash2 = hex2bin(fixtures.alice.parsedTorrent.infoHash)
|
||||
|
||||
common.createServer(t, 'http', (server, announceUrl) => {
|
||||
common.createServer(t, 'http', async (server, announceUrl) => {
|
||||
const scrapeUrl = announceUrl.replace('/announce', '/scrape')
|
||||
|
||||
const url = `${scrapeUrl}?${commonLib.querystringStringify({
|
||||
info_hash: [binaryInfoHash1, binaryInfoHash2]
|
||||
})}`
|
||||
|
||||
get.concat(url, (err, res, data) => {
|
||||
let res
|
||||
try {
|
||||
res = await fetch(url)
|
||||
} catch (err) {
|
||||
t.error(err)
|
||||
}
|
||||
let data = Buffer.from(await res.arrayBuffer())
|
||||
|
||||
t.equal(res.statusCode, 200)
|
||||
t.equal(res.status, 200)
|
||||
|
||||
data = bencode.decode(data)
|
||||
t.ok(data.files)
|
||||
t.equal(Object.keys(data.files).length, 2)
|
||||
data = bencode.decode(data)
|
||||
t.ok(data.files)
|
||||
t.equal(Object.keys(data.files).length, 2)
|
||||
|
||||
t.ok(data.files[binaryInfoHash1])
|
||||
t.equal(typeof data.files[binaryInfoHash1].complete, 'number')
|
||||
t.equal(typeof data.files[binaryInfoHash1].incomplete, 'number')
|
||||
t.equal(typeof data.files[binaryInfoHash1].downloaded, 'number')
|
||||
t.ok(data.files[binaryInfoHash1])
|
||||
t.equal(typeof data.files[binaryInfoHash1].complete, 'number')
|
||||
t.equal(typeof data.files[binaryInfoHash1].incomplete, 'number')
|
||||
t.equal(typeof data.files[binaryInfoHash1].downloaded, 'number')
|
||||
|
||||
t.ok(data.files[binaryInfoHash2])
|
||||
t.equal(typeof data.files[binaryInfoHash2].complete, 'number')
|
||||
t.equal(typeof data.files[binaryInfoHash2].incomplete, 'number')
|
||||
t.equal(typeof data.files[binaryInfoHash2].downloaded, 'number')
|
||||
t.ok(data.files[binaryInfoHash2])
|
||||
t.equal(typeof data.files[binaryInfoHash2].complete, 'number')
|
||||
t.equal(typeof data.files[binaryInfoHash2].incomplete, 'number')
|
||||
t.equal(typeof data.files[binaryInfoHash2].downloaded, 'number')
|
||||
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
})
|
||||
|
||||
test('server: all info_hash scrape (manual http request)', t => {
|
||||
t.plan(10)
|
||||
t.plan(9)
|
||||
|
||||
const binaryInfoHash = hex2bin(fixtures.leaves.parsedTorrent.infoHash)
|
||||
|
||||
@ -207,24 +210,28 @@ test('server: all info_hash scrape (manual http request)', t => {
|
||||
|
||||
client.start()
|
||||
|
||||
server.once('start', () => {
|
||||
server.once('start', async () => {
|
||||
// now do a scrape of everything by omitting the info_hash param
|
||||
get.concat(scrapeUrl, (err, res, data) => {
|
||||
let res
|
||||
try {
|
||||
res = await fetch(scrapeUrl)
|
||||
} catch (err) {
|
||||
t.error(err)
|
||||
}
|
||||
let data = Buffer.from(await res.arrayBuffer())
|
||||
|
||||
t.equal(res.statusCode, 200)
|
||||
data = bencode.decode(data)
|
||||
t.ok(data.files)
|
||||
t.equal(Object.keys(data.files).length, 1)
|
||||
t.equal(res.status, 200)
|
||||
data = bencode.decode(data)
|
||||
t.ok(data.files)
|
||||
t.equal(Object.keys(data.files).length, 1)
|
||||
|
||||
t.ok(data.files[binaryInfoHash])
|
||||
t.equal(typeof data.files[binaryInfoHash].complete, 'number')
|
||||
t.equal(typeof data.files[binaryInfoHash].incomplete, 'number')
|
||||
t.equal(typeof data.files[binaryInfoHash].downloaded, 'number')
|
||||
t.ok(data.files[binaryInfoHash])
|
||||
t.equal(typeof data.files[binaryInfoHash].complete, 'number')
|
||||
t.equal(typeof data.files[binaryInfoHash].incomplete, 'number')
|
||||
t.equal(typeof data.files[binaryInfoHash].downloaded, 'number')
|
||||
|
||||
client.destroy(() => { t.pass('client destroyed') })
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
client.destroy(() => { t.pass('client destroyed') })
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
183
test/stats.js
183
test/stats.js
@ -1,7 +1,7 @@
|
||||
import Client from '../index.js'
|
||||
import commonTest from './common.js'
|
||||
import fixtures from 'webtorrent-fixtures'
|
||||
import get from 'simple-get'
|
||||
import fetch from 'cross-fetch-ponyfill'
|
||||
import test from 'tape'
|
||||
|
||||
const peerId = Buffer.from('-WW0091-4ea5886ce160')
|
||||
@ -30,89 +30,94 @@ function parseHtml (html) {
|
||||
}
|
||||
|
||||
test('server: get empty stats', t => {
|
||||
t.plan(11)
|
||||
t.plan(10)
|
||||
|
||||
commonTest.createServer(t, 'http', (server, announceUrl) => {
|
||||
commonTest.createServer(t, 'http', async (server, announceUrl) => {
|
||||
const url = announceUrl.replace('/announce', '/stats')
|
||||
|
||||
get.concat(url, (err, res, data) => {
|
||||
let res
|
||||
try {
|
||||
res = await fetch(url)
|
||||
} catch (err) {
|
||||
t.error(err)
|
||||
}
|
||||
const data = Buffer.from(await res.arrayBuffer())
|
||||
|
||||
const stats = parseHtml(data.toString())
|
||||
t.equal(res.statusCode, 200)
|
||||
t.equal(stats.torrents, 0)
|
||||
t.equal(stats.activeTorrents, 0)
|
||||
t.equal(stats.peersAll, 0)
|
||||
t.equal(stats.peersSeederOnly, 0)
|
||||
t.equal(stats.peersLeecherOnly, 0)
|
||||
t.equal(stats.peersSeederAndLeecher, 0)
|
||||
t.equal(stats.peersIPv4, 0)
|
||||
t.equal(stats.peersIPv6, 0)
|
||||
const stats = parseHtml(data.toString())
|
||||
t.equal(res.status, 200)
|
||||
t.equal(stats.torrents, 0)
|
||||
t.equal(stats.activeTorrents, 0)
|
||||
t.equal(stats.peersAll, 0)
|
||||
t.equal(stats.peersSeederOnly, 0)
|
||||
t.equal(stats.peersLeecherOnly, 0)
|
||||
t.equal(stats.peersSeederAndLeecher, 0)
|
||||
t.equal(stats.peersIPv4, 0)
|
||||
t.equal(stats.peersIPv6, 0)
|
||||
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
})
|
||||
|
||||
test('server: get empty stats with json header', t => {
|
||||
t.plan(11)
|
||||
t.plan(10)
|
||||
|
||||
commonTest.createServer(t, 'http', (server, announceUrl) => {
|
||||
commonTest.createServer(t, 'http', async (server, announceUrl) => {
|
||||
const opts = {
|
||||
url: announceUrl.replace('/announce', '/stats'),
|
||||
headers: {
|
||||
accept: 'application/json'
|
||||
},
|
||||
json: true
|
||||
}
|
||||
}
|
||||
|
||||
get.concat(opts, (err, res, stats) => {
|
||||
let res
|
||||
try {
|
||||
res = await fetch(announceUrl.replace('/announce', '/stats'), opts)
|
||||
} catch (err) {
|
||||
t.error(err)
|
||||
}
|
||||
const stats = await res.json()
|
||||
|
||||
t.equal(res.statusCode, 200)
|
||||
t.equal(stats.torrents, 0)
|
||||
t.equal(stats.activeTorrents, 0)
|
||||
t.equal(stats.peersAll, 0)
|
||||
t.equal(stats.peersSeederOnly, 0)
|
||||
t.equal(stats.peersLeecherOnly, 0)
|
||||
t.equal(stats.peersSeederAndLeecher, 0)
|
||||
t.equal(stats.peersIPv4, 0)
|
||||
t.equal(stats.peersIPv6, 0)
|
||||
t.equal(res.status, 200)
|
||||
t.equal(stats.torrents, 0)
|
||||
t.equal(stats.activeTorrents, 0)
|
||||
t.equal(stats.peersAll, 0)
|
||||
t.equal(stats.peersSeederOnly, 0)
|
||||
t.equal(stats.peersLeecherOnly, 0)
|
||||
t.equal(stats.peersSeederAndLeecher, 0)
|
||||
t.equal(stats.peersIPv4, 0)
|
||||
t.equal(stats.peersIPv6, 0)
|
||||
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
})
|
||||
|
||||
test('server: get empty stats on stats.json', t => {
|
||||
t.plan(11)
|
||||
t.plan(10)
|
||||
|
||||
commonTest.createServer(t, 'http', (server, announceUrl) => {
|
||||
const opts = {
|
||||
url: announceUrl.replace('/announce', '/stats.json'),
|
||||
json: true
|
||||
}
|
||||
|
||||
get.concat(opts, (err, res, stats) => {
|
||||
commonTest.createServer(t, 'http', async (server, announceUrl) => {
|
||||
let res
|
||||
try {
|
||||
res = await fetch(announceUrl.replace('/announce', '/stats.json'))
|
||||
} catch (err) {
|
||||
t.error(err)
|
||||
}
|
||||
const stats = await res.json()
|
||||
|
||||
t.equal(res.statusCode, 200)
|
||||
t.equal(stats.torrents, 0)
|
||||
t.equal(stats.activeTorrents, 0)
|
||||
t.equal(stats.peersAll, 0)
|
||||
t.equal(stats.peersSeederOnly, 0)
|
||||
t.equal(stats.peersLeecherOnly, 0)
|
||||
t.equal(stats.peersSeederAndLeecher, 0)
|
||||
t.equal(stats.peersIPv4, 0)
|
||||
t.equal(stats.peersIPv6, 0)
|
||||
t.equal(res.status, 200)
|
||||
t.equal(stats.torrents, 0)
|
||||
t.equal(stats.activeTorrents, 0)
|
||||
t.equal(stats.peersAll, 0)
|
||||
t.equal(stats.peersSeederOnly, 0)
|
||||
t.equal(stats.peersLeecherOnly, 0)
|
||||
t.equal(stats.peersSeederAndLeecher, 0)
|
||||
t.equal(stats.peersIPv4, 0)
|
||||
t.equal(stats.peersIPv6, 0)
|
||||
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
})
|
||||
|
||||
test('server: get leecher stats.json', t => {
|
||||
t.plan(11)
|
||||
t.plan(10)
|
||||
|
||||
commonTest.createServer(t, 'http', (server, announceUrl) => {
|
||||
// announce a torrent to the tracker
|
||||
@ -127,33 +132,32 @@ test('server: get leecher stats.json', t => {
|
||||
|
||||
client.start()
|
||||
|
||||
server.once('start', () => {
|
||||
const opts = {
|
||||
url: announceUrl.replace('/announce', '/stats.json'),
|
||||
json: true
|
||||
}
|
||||
|
||||
get.concat(opts, (err, res, stats) => {
|
||||
server.once('start', async () => {
|
||||
let res
|
||||
try {
|
||||
res = await fetch(announceUrl.replace('/announce', '/stats.json'))
|
||||
} catch (err) {
|
||||
t.error(err)
|
||||
}
|
||||
const stats = await res.json()
|
||||
|
||||
t.equal(res.statusCode, 200)
|
||||
t.equal(stats.torrents, 1)
|
||||
t.equal(stats.activeTorrents, 1)
|
||||
t.equal(stats.peersAll, 1)
|
||||
t.equal(stats.peersSeederOnly, 0)
|
||||
t.equal(stats.peersLeecherOnly, 1)
|
||||
t.equal(stats.peersSeederAndLeecher, 0)
|
||||
t.equal(stats.clients.WebTorrent['0.91'], 1)
|
||||
t.equal(res.status, 200)
|
||||
t.equal(stats.torrents, 1)
|
||||
t.equal(stats.activeTorrents, 1)
|
||||
t.equal(stats.peersAll, 1)
|
||||
t.equal(stats.peersSeederOnly, 0)
|
||||
t.equal(stats.peersLeecherOnly, 1)
|
||||
t.equal(stats.peersSeederAndLeecher, 0)
|
||||
t.equal(stats.clients.WebTorrent['0.91'], 1)
|
||||
|
||||
client.destroy(() => { t.pass('client destroyed') })
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
client.destroy(() => { t.pass('client destroyed') })
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test('server: get leecher stats.json (unknown peerId)', t => {
|
||||
t.plan(11)
|
||||
t.plan(10)
|
||||
|
||||
commonTest.createServer(t, 'http', (server, announceUrl) => {
|
||||
// announce a torrent to the tracker
|
||||
@ -168,27 +172,26 @@ test('server: get leecher stats.json (unknown peerId)', t => {
|
||||
|
||||
client.start()
|
||||
|
||||
server.once('start', () => {
|
||||
const opts = {
|
||||
url: announceUrl.replace('/announce', '/stats.json'),
|
||||
json: true
|
||||
}
|
||||
|
||||
get.concat(opts, (err, res, stats) => {
|
||||
server.once('start', async () => {
|
||||
let res
|
||||
try {
|
||||
res = await fetch(announceUrl.replace('/announce', '/stats.json'))
|
||||
} catch (err) {
|
||||
t.error(err)
|
||||
}
|
||||
const stats = await res.json()
|
||||
|
||||
t.equal(res.statusCode, 200)
|
||||
t.equal(stats.torrents, 1)
|
||||
t.equal(stats.activeTorrents, 1)
|
||||
t.equal(stats.peersAll, 1)
|
||||
t.equal(stats.peersSeederOnly, 0)
|
||||
t.equal(stats.peersLeecherOnly, 1)
|
||||
t.equal(stats.peersSeederAndLeecher, 0)
|
||||
t.equal(stats.clients.unknown['01234567'], 1)
|
||||
t.equal(res.status, 200)
|
||||
t.equal(stats.torrents, 1)
|
||||
t.equal(stats.activeTorrents, 1)
|
||||
t.equal(stats.peersAll, 1)
|
||||
t.equal(stats.peersSeederOnly, 0)
|
||||
t.equal(stats.peersLeecherOnly, 1)
|
||||
t.equal(stats.peersSeederAndLeecher, 0)
|
||||
t.equal(stats.clients.unknown['01234567'], 1)
|
||||
|
||||
client.destroy(() => { t.pass('client destroyed') })
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
client.destroy(() => { t.pass('client destroyed') })
|
||||
server.close(() => { t.pass('server closed') })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user