Express app.post recibe llamadas varias veces
He estado creando una aplicación de conversión de videos de YouTube que transmite videos de YouTube usando youtube-dl y los guarda, todo funcionaba bien hasta que intenté transmitir un video que duró más de una hora. Cuando la tarea estaba entre 50% y 100% completa o 40-80 segundos, sería cuando todo el bloque de código se volvería a ejecutar, lo que daría lugar a múltiples transmisiones simultáneas. Por lo tanto, la respuesta nunca puede enviarse mientras espera a que termine la tubería. Agregando next (); fuera de la función de flujo permitió que la conversión se completara sin interrupciones o repeticiones del bloque de código, sin embargo, resultó en el siguiente error al intentar enviar la respuesta:
throw new Error('Can\'t set headers after they are sent.');
Este es el bloque de código Node.js en cuestión:
app.post('/convert/', function (req, res, next){
var url = 'http://www.youtube.com/'+req.body.url;
var quality = req.body.quality;
var socketId = req.body.socketId;
stream = youtubedl(url,
['-f ' + quality],
// // Additional options can be given for calling `child_process.execFile()`.
{ cwd: __dirname });
stream.on('info', function(info) {
console.log('Download started');
console.log('filename: ' + info._filename);
console.log('size: ' + info.size);
console.log('format: ' + info.format);
var fileName = info._filename;
var videoId = info.id;
var videoTitle = info.title;
videoTitle = videoTitle.replace(/[^a-zA-Z0-9\s]/g, '');
console.log(videoTitle);
var mp4 = 'downloads/'+videoTitle+'-'+info.format_id+'.mp4';
fs.writeFile(mp4, "file", function(err) {
if(err) {
return console.log(err);
}
console.log("The file was saved!");
var stat = fs.statSync(mp4);
var str = progress({
length: info.size,
time: 100
});
str.on('progress', function(progress) {
io.to(global.socketid).emit('progressVideo',{progress: progress.percentage});
console.log(info.size);
console.log(progress.transferred);
console.log(progress.percentage);
console.log(progress.remaining);
});
var pipe = stream.pipe(str).pipe(fs.createWriteStream(mp4));
pipe.on('finish', function () {
console.log("stream finished.");
res.json(videoTitle+'-'+info.format_id+'.mp4');
});
});
});
// next();
});
Llamado por un código angular.
// Sends youtube link to backend
$scope.getVideo = function(youtubeLink, resolution){
var cleanedLink = youtubeLink.substring(24);
var url = {url: cleanedLink, quality: resolution};
$http.post('/convert/', url).success(function (response){
// Do some stuff
});
}
Confundido sobre por qué se ejecutaba más de una vez, lentamente eliminé más y más código hasta que me quedé con esta simple prueba.
app.post('/convert/', function (req, res, next){
console.log('hello!');
});
El cual fue llamado por un evento ng-click y después de esperar un minuto más o menos, la consola también imprimió dos y luego treshello!
declaraciones. Estoy completamente perdido en cuanto a por qué sucede esto. Si alguien pudiera arrojar algo de luz sobre esto para mí, sería muy apreciado.