Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/webtorrent/webtorrent.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCas <6506529+ThaUnknown@users.noreply.github.com>2021-08-20 00:41:34 +0300
committerGitHub <noreply@github.com>2021-08-20 00:41:34 +0300
commit604943e325c68721251a71c29d94e6a07ce0b31c (patch)
treed6728521ed5d4f13e5a3484f7d670756e89a832b /lib/file.js
parenta46a7a51d9fd8efef86533c5868a2d23b1346b6e (diff)
feat: add service worker server as an alternative to renderMedia (#2098)
* feat: add service worker server as an alternative to renderMedia * code QL * thanks gh auto merge Co-authored-by: Diego Rodríguez Baquero <github@diegorbaquero.com>
Diffstat (limited to 'lib/file.js')
-rw-r--r--lib/file.js76
1 files changed, 76 insertions, 0 deletions
diff --git a/lib/file.js b/lib/file.js
index fd9ac7c..f3de744 100644
--- a/lib/file.js
+++ b/lib/file.js
@@ -7,6 +7,9 @@ const streamToBlobURL = require('stream-to-blob-url')
const streamToBuffer = require('stream-with-known-length-to-buffer')
const FileStream = require('./file-stream')
const queueMicrotask = require('queue-microtask')
+const rangeParser = require('range-parser')
+const mime = require('mime')
+const eos = require('end-of-stream')
class File extends EventEmitter {
constructor (torrent, file) {
@@ -33,6 +36,8 @@ class File extends EventEmitter {
this.done = true
this.emit('done')
}
+
+ this._serviceWorker = torrent.client.serviceWorker
}
get downloaded () {
@@ -144,6 +149,77 @@ class File extends EventEmitter {
render.render(this, elem, opts, cb)
}
+ _serve (req) {
+ const res = {
+ status: 200,
+ headers: {
+ // Support range-requests
+ 'Accept-Ranges': 'bytes',
+ 'Content-Type': mime.getType(this.name),
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
+ Expires: '0'
+ },
+ body: req.method === 'HEAD' ? '' : 'STREAM'
+ }
+ // force the browser to download the file if if it's opened in a new tab
+ if (req.destination === 'document') {
+ res.headers['Content-Type'] = 'application/octet-stream'
+ res.headers['Content-Disposition'] = 'attachment'
+ res.body = 'DOWNLOAD'
+ }
+
+ // `rangeParser` returns an array of ranges, or an error code (number) if
+ // there was an error parsing the range.
+ let range = rangeParser(this.length, req.headers.range || '')
+
+ if (range.constructor === Array) {
+ res.status = 206 // indicates that range-request was understood
+
+ // no support for multi-range request, just use the first range
+ range = range[0]
+
+ res.headers['Content-Range'] = `bytes ${range.start}-${range.end}/${this.length}`
+ res.headers['Content-Length'] = `${range.end - range.start + 1}`
+ } else {
+ res.headers['Content-Length'] = this.length
+ }
+
+ const stream = req.method === 'GET' && this.createReadStream(range)
+
+ let pipe = null
+ if (stream) {
+ this.emit('stream', { stream, req, file: this }, piped => {
+ pipe = piped
+
+ // piped stream might not close the original filestream on close/error, this is agressive but necessary
+ eos(piped, () => {
+ if (piped) piped.destroy()
+ stream.destroy()
+ })
+ })
+ }
+
+ return [res, pipe || stream, pipe && stream]
+ }
+
+ getStreamURL (cb = () => {}) {
+ if (typeof window === 'undefined') throw new Error('browser-only method')
+ if (!this._serviceWorker) throw new Error('No worker registered')
+ if (this._serviceWorker.state !== 'activated') throw new Error('Worker isn\'t activated')
+ const workerPath = this._serviceWorker.scriptURL.substr(0, this._serviceWorker.scriptURL.lastIndexOf('/') + 1).slice(window.location.origin.length)
+ const url = `${workerPath}webtorrent/${this._torrent.infoHash}/${encodeURI(this.path)}`
+ cb(null, url)
+ }
+
+ streamTo (elem, cb = () => {}) {
+ if (typeof window === 'undefined') throw new Error('browser-only method')
+ if (!this._serviceWorker) throw new Error('No worker registered')
+ if (this._serviceWorker.state !== 'activated') throw new Error('Worker isn\'t activated')
+ const workerPath = this._serviceWorker.scriptURL.substr(0, this._serviceWorker.scriptURL.lastIndexOf('/') + 1).slice(window.location.origin.length)
+ elem.src = `${workerPath}webtorrent/${this._torrent.infoHash}/${encodeURI(this.path)}`
+ cb(null, elem)
+ }
+
_getMimeType () {
return render.mime[path.extname(this.name).toLowerCase()]
}