Skip to content

Instantly share code, notes, and snippets.

@theunforgiven
Last active January 20, 2021 17:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theunforgiven/40bc7b02b86dd66aa40e7866bdbe5b84 to your computer and use it in GitHub Desktop.
Save theunforgiven/40bc7b02b86dd66aa40e7866bdbe5b84 to your computer and use it in GitHub Desktop.
// This is a replacement for the express.js serve-static middleware
// so we can decrypt the segments/playlists on request.
const _ = require('lodash')
const fs = require('fs')
const parseUrl = require('parseurl')
const resolve = require('path').resolve
const send = require('send');
const Cache = require('./cache')
const Logger = require('./logger')
const log = new Logger('servestaticencrypted')
const path = require('path');
const RecheckTickInterval = 50;
const RecheckMaxTimeMs = 10000;
function pollUntilFileExists(resolvedPath, onSuccess, onFailure) {
let timePassed = 0;
const recheckInterval = setInterval(function () {
timePassed += RecheckTickInterval;
if (fs.existsSync(resolvedPath)) {
clearInterval(recheckInterval);
return onSuccess();
}
if (timePassed >= RecheckMaxTimeMs) {
clearInterval(recheckInterval);
return onFailure()
}
}, RecheckTickInterval);
}
function serveStaticEncrypted(root, fe, options) {
if (!root) {
throw new Error('root path required')
}
if (typeof root !== 'string') {
throw new Error('root path must be a string')
}
// copy options object
let opts = Object.create(options || null)
// fall-though
let fallthrough = opts.fallthrough !== false
// headers listener
let setHeaders = opts.setHeaders
if (setHeaders && typeof setHeaders !== 'function') {
throw new Error('option setHeaders must be function')
}
return function serveStaticEncrypted(req, res, next) {
if (req.method !== 'GET' && req.method !== 'HEAD') {
if (fallthrough) {
return next()
}
// method not allowed
res.statusCode = 405
res.setHeader('Allow', 'GET, HEAD')
res.setHeader('Content-Length', '0')
res.end()
return
}
let forwardError = !fallthrough
let originalUrl = parseUrl.original(req)
let urlPath = parseUrl(req).pathname
if (urlPath === '/' && originalUrl.pathname.substr(-1) !== '/') {
urlPath = ''
}
const resolvedPath = path.join(resolve(root), urlPath);
if (Cache.PlaylistCache[resolvedPath] !== undefined) {
setHeaders(resolvedPath);
res.send(Cache.PlaylistCache[resolvedPath]).end();
return next()
}
if (!fs.existsSync(resolvedPath)) {
log.info("missing cached file on disk polling till found: " + resolvedPath)
res.sendStatus(404, 'missing cache file: ' + resolvedPath);
return next();
}
// res.setHeader("Content-Type", "application/octet-stream");
// res.status(200).send(fs.readFileSync(resolvedPath));
// var s = fs.createReadStream(resolvedPath);
// s.on('open', function () {
// log.info("Sending response: " + res.headersSent)
// res.set('Content-Type', "video/mp2t");
// s.pipe(res);
// });
// s.on('error', function () {
// res.set('Content-Type', 'text/plain');
// res.status(404).end('Not found');
// });
// var readStream = fs.createReadStream(resolvedPath);
// readStream.on('data', (data) => {
// log.info("Writing data " + _.size(data));
// res.write(data);
// });
// readStream.on('end', (data) => {
// log.info("wrote data");
// res.status(200).send();
// });
// return next();
let readStream = fs.createReadStream(resolvedPath)
// const senddd = send(req, resolvedPath);
// senddd.on('error', (err) => {
// log.error("HOLY SHIT", err);
// });
// senddd.on('end', () => {
// log.info('file send done');
// next();
// });
// senddd.on('stream', () => {
// log.info('file send start');
// });
// senddd.on('file', (path, stat) => {
// log.info('stating file ' + path + ' ' + stat);
// });
// senddd.on('end', () => {
// res.end();
// });
// senddd.pipe(res);
// return;
readStream.on('open', function () {
log.info("Sending file " + resolvedPath);
readStream.pipe(res);
});
readStream.on('end', function () {
log.info("Sent file " + resolvedPath);
});
readStream.on('error', function () {
res.set('Content-Type', 'text/plain');
res.status(404).end('Not found');
});
// readStream.pipe(res);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment