1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
module.exports = Server
var debug = require('debug')('webtorrent:server')
var http = require('http')
var mime = require('mime')
var prettyBytes = require('pretty-bytes')
var pump = require('pump')
var rangeParser = require('range-parser')
var url = require('url')
function Server (torrent, opts) {
var server = http.createServer(opts)
var sockets = []
server.on('connection', function (socket) {
socket.setTimeout(36000000)
sockets.push(socket)
socket.on('close', function () {
var index = sockets.indexOf(socket)
if (index >= 0) sockets.splice(index, 1)
})
})
server.destroy = function (cb) {
sockets.forEach(function (socket) {
socket.destroy()
})
server.close(cb)
}
server.on('request', function (req, res) {
debug('onRequest')
// Allow CORS requests to specify arbitrary headers, e.g. 'Range',
// by responding to the OPTIONS preflight request with the specified
// origin and requested headers.
if (req.method === 'OPTIONS' && req.headers['access-control-request-headers']) {
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
res.setHeader(
'Access-Control-Allow-Headers',
req.headers['access-control-request-headers']
)
res.setHeader('Access-Control-Max-Age', '1728000')
return res.end()
}
if (req.headers.origin) {
res.setHeader('Access-Control-Allow-Origin', req.headers.origin)
}
var pathname = url.parse(req.url).pathname
if (pathname === '/favicon.ico') return res.end()
if (torrent.ready) onReady()
else torrent.once('ready', onReady)
function onReady () {
if (pathname === '/') {
res.setHeader('Content-Type', 'text/html')
var listHtml = torrent.files.map(function (file, i) {
return '<li><a download="' + file.name + '" href="/' + i + '">' + file.path + '</a> ' +
'(' + prettyBytes(file.length) + ')</li>'
}).join('<br>')
var html = '<h1>' + torrent.name + '</h1><ol>' + listHtml + '</ol>'
return res.end(html)
}
var index = Number(pathname.slice(1))
if (Number.isNaN(index) || index >= torrent.files.length) {
res.statusCode = 404
return res.end('404 Not Found')
}
var file = torrent.files[index]
res.setHeader('Accept-Ranges', 'bytes')
res.setHeader('Content-Type', mime.lookup(file.name))
res.statusCode = 200
// Support DLNA streaming
res.setHeader('transferMode.dlna.org', 'Streaming')
res.setHeader(
'contentFeatures.dlna.org',
'DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000'
)
var range
if (req.headers.range) {
res.statusCode = 206
// no support for multi-range reqs
range = rangeParser(file.length, req.headers.range)[0]
debug('range %s', JSON.stringify(range))
res.setHeader(
'Content-Range',
'bytes ' + range.start + '-' + range.end + '/' + file.length
)
res.setHeader('Content-Length', range.end - range.start + 1)
} else {
res.setHeader('Content-Length', file.length)
}
if (req.method === 'HEAD') res.end()
pump(file.createReadStream(range), res)
}
})
return server
}
|