Preflight raw file requests to get better error messages

This commit is contained in:
calzoneman 2015-05-24 11:06:02 -04:00
parent cd0cc69fd8
commit c4add8f142
1 changed files with 102 additions and 53 deletions

View File

@ -1,6 +1,9 @@
var Logger = require("./logger"); var Logger = require("./logger");
var Config = require("./config"); var Config = require("./config");
var spawn = require("child_process").spawn; var spawn = require("child_process").spawn;
var https = require("https");
var http = require("http");
var urlparse = require("url");
var USE_JSON = true; var USE_JSON = true;
@ -21,6 +24,47 @@ var audioOnlyContainers = {
"mp3": true "mp3": true
}; };
function testUrl(url, cb, redirected) {
var data = urlparse.parse(url);
if (!/https?:/.test(data.protocol)) {
return cb("Video links must start with http:// or https://");
}
if (!data.hostname) {
return cb("Invalid link");
}
var transport = (data.protocol === "https:") ? https : http;
data.method = "HEAD";
var req = transport.request(data, function (res) {
req.abort();
if (res.statusCode === 301 || res.statusCode === 302) {
if (redirected) {
return cb("Too many redirects. Please provide a direct link to the "
"file");
}
return testUrl(res.headers['location'], cb, true);
}
if (res.statusCode !== 200) {
return cb("HTTP " + res.statusCode + " " + res.statusMessage);
}
if (!/^audio|^video/.test(res.headers['content-type'])) {
return cb("Server did not return an audio or video file");
}
cb();
});
req.on("error", function (err) {
cb(err);
});
req.end();
}
function readOldFormat(buf) { function readOldFormat(buf) {
var lines = buf.split("\n"); var lines = buf.split("\n");
var tmp = { tags: {} }; var tmp = { tags: {} };
@ -149,64 +193,69 @@ exports.query = function (filename, cb) {
"or HTTPS"); "or HTTPS");
} }
exports.ffprobe(filename, function (err, data) { testUrl(filename, function (err) {
if (err) { if (err) {
if (err.code && err.code === "ENOENT") { return cb(err);
return cb("Failed to execute `ffprobe`. Set ffmpeg.ffprobe-exec to " + }
"the correct name of the executable in config.yaml. If " +
"you are using Debian or Ubuntu, it is probably avprobe.");
} else if (err.message) {
if (err.message.match(/protocol not found/i))
return cb("Link uses a protocol unsupported by this server's ffmpeg");
var m = err.message.match(/(http error .*)/i); exports.ffprobe(filename, function (err, data) {
if (m) return cb(m[1]); if (err) {
if (err.code && err.code === "ENOENT") {
return cb("Failed to execute `ffprobe`. Set ffmpeg.ffprobe-exec " +
"to the correct name of the executable in config.yaml. " +
"If you are using Debian or Ubuntu, it is probably " +
"avprobe.");
} else if (err.message) {
if (err.message.match(/protocol not found/i))
return cb("Link uses a protocol unsupported by this server's " +
"version of ffmpeg");
Logger.errlog.log(err.stack || err); Logger.errlog.log(err.stack || err);
return cb("Unable to query file data with ffmpeg");
} else {
Logger.errlog.log(err.stack || err);
return cb("Unable to query file data with ffmpeg");
}
}
try {
data = reformatData(data);
} catch (e) {
Logger.errlog.log(e.stack || e);
return cb("Unable to query file data with ffmpeg"); return cb("Unable to query file data with ffmpeg");
}
if (data.medium === "video") {
if (!acceptedCodecs.hasOwnProperty(data.type)) {
return cb("Unsupported video codec " + data.type);
}
data = {
title: data.title || "Raw Video",
duration: data.duration,
bitrate: data.bitrate,
codec: data.type
};
cb(null, data);
} else if (data.medium === "audio") {
if (!acceptedAudioCodecs.hasOwnProperty(data.acodec)) {
return cb("Unsupported audio codec " + data.acodec);
}
data = {
title: data.title || "Raw Audio",
duration: data.duration,
bitrate: data.bitrate,
codec: data.acodec
};
cb(null, data);
} else { } else {
Logger.errlog.log(err.stack || err); return cb("Parsed metadata did not contain a valid video or audio " +
return cb("Unable to query file data with ffmpeg"); "stream. Either the file is invalid or it has a format " +
"unsupported by this server's version of ffmpeg.");
} }
} });
try {
data = reformatData(data);
} catch (e) {
Logger.errlog.log(e.stack || e);
return cb("Unable to query file data with ffmpeg");
}
if (data.medium === "video") {
if (!acceptedCodecs.hasOwnProperty(data.type)) {
return cb("Unsupported video codec " + data.type);
}
data = {
title: data.title || "Raw Video",
duration: data.duration,
bitrate: data.bitrate,
codec: data.type
};
cb(null, data);
} else if (data.medium === "audio") {
if (!acceptedAudioCodecs.hasOwnProperty(data.acodec)) {
return cb("Unsupported audio codec " + data.acodec);
}
data = {
title: data.title || "Raw Audio",
duration: data.duration,
bitrate: data.bitrate,
codec: data.acodec
};
cb(null, data);
} else {
return cb("Parsed metadata did not contain a valid video or audio stream. " +
"Either the file is invalid or it has a format unsupported by " +
"this server's version of ffmpeg.");
}
}); });
}; };