}
Site.prototype.serve_fs = async function(env, pathname) {
- // see serve()
- console.log(
- `${env.parsed_url.host} streaming ${env.parsed_url.pathname}`
- )
-
// see serve_internal()
- env.response.statusCode = 200
// since the file may be huge we need to cache it for as long as reasonable
if (this.options.caching)
env.response.setHeader('Cache-Control', 'max-age=86400')
env.response.setHeader('Content-Type', env.mime_type)
- let stream = fs.createReadStream(pathname);
+ // see https://dev.to/abdisalan_js/how-to-code-a-video-streaming-server-using-nodejs-2o0
+ let stream
+ let range = env.request.headers.range;
+ if (range !== undefined) {
+ let stats
+ try {
+ stats = await fs_stat(pathname)
+ }
+ catch (err) {
+ if (!(err instanceof Error) || err.code !== 'ENOENT')
+ throw err
+ return false
+ }
+
+ // Parse Range
+ // Example: "bytes=32324-"
+ let start = Number(range.replace(/\D/g, ''))
+ let end = Math.min(start + 1048576, stats.size)
+
+ // see serve()
+ console.log(
+ `${env.parsed_url.host} streaming ${env.parsed_url.pathname} partial ${start}-${end}/${stats.size}`
+ )
+
+ // Create headers
+ env.response.statusCode = 206 // partial content
+ env.response.setHeader(
+ 'Content-Range',
+ `bytes ${start}-${end - 1}/${stats.size}`
+ )
+ env.response.setHeader('Accept-Ranges', 'bytes')
+ env.response.setHeader('Content-Length', end - start)
+
+ // create video read stream for this particular chunk
+ stream = fs.createReadStream(pathname, {start: start, end: end - 1})
+ }
+ else {
+ // see serve()
+ console.log(
+ `${env.parsed_url.host} streaming ${env.parsed_url.pathname}`
+ )
+
+ // see serve_internal()
+ env.response.statusCode = 200
+ stream = fs.createReadStream(pathname)
+ }
+
return /*await*/ new Promise(
(resolve, reject) => {
stream.on(