2016-07-18 22:56:27 +00:00
|
|
|
/*
|
|
|
|
Node-OpenDroneMap Node.js App and REST API to access OpenDroneMap.
|
|
|
|
Copyright (C) 2016 Node-OpenDroneMap Contributors
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2016-07-04 20:59:07 +00:00
|
|
|
"use strict";
|
|
|
|
|
2016-07-05 18:06:22 +00:00
|
|
|
let fs = require('fs');
|
2016-07-08 20:44:48 +00:00
|
|
|
let async = require('async');
|
|
|
|
|
2016-07-04 20:59:07 +00:00
|
|
|
let express = require('express');
|
|
|
|
let app = express();
|
|
|
|
|
2016-07-08 20:44:48 +00:00
|
|
|
let addRequestId = require('./libs/expressRequestId')();
|
2016-07-05 18:06:22 +00:00
|
|
|
let multer = require('multer');
|
2016-07-07 22:07:17 +00:00
|
|
|
let bodyParser = require('body-parser');
|
2016-07-08 20:44:48 +00:00
|
|
|
let morgan = require('morgan');
|
2016-07-15 21:19:50 +00:00
|
|
|
let TaskManager = require('./libs/taskManager');
|
2016-07-06 18:44:20 +00:00
|
|
|
let Task = require('./libs/Task');
|
2016-07-26 19:20:37 +00:00
|
|
|
let odmOptions = require('./libs/odmOptions');
|
2016-07-06 18:44:20 +00:00
|
|
|
|
2016-07-08 20:44:48 +00:00
|
|
|
app.use(morgan('tiny'));
|
2016-07-07 22:07:17 +00:00
|
|
|
app.use(bodyParser.urlencoded({extended: true}));
|
|
|
|
app.use(bodyParser.json());
|
2016-07-05 18:06:22 +00:00
|
|
|
app.use(express.static('public'));
|
|
|
|
|
|
|
|
let upload = multer({
|
|
|
|
storage: multer.diskStorage({
|
|
|
|
destination: (req, file, cb) => {
|
|
|
|
let path = `tmp/${req.id}/`;
|
|
|
|
fs.exists(path, exists => {
|
|
|
|
if (!exists){
|
|
|
|
fs.mkdir(path, undefined, () => {
|
|
|
|
cb(null, path);
|
|
|
|
});
|
|
|
|
}else{
|
|
|
|
cb(null, path);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
filename: (req, file, cb) => {
|
|
|
|
cb(null, file.originalname)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
2016-07-08 20:44:48 +00:00
|
|
|
|
2016-07-09 16:58:14 +00:00
|
|
|
app.post('/task/new', addRequestId, upload.array('images'), (req, res) => {
|
2016-07-06 18:44:20 +00:00
|
|
|
if (req.files.length === 0) res.json({error: "Need at least 1 file."});
|
|
|
|
else{
|
2016-07-08 20:44:48 +00:00
|
|
|
async.series([
|
2016-07-26 19:20:37 +00:00
|
|
|
cb => {
|
|
|
|
odmOptions.filterOptions(req.body.options, (err, options) => {
|
|
|
|
if (err) cb(err);
|
|
|
|
else{
|
|
|
|
req.body.options = options;
|
|
|
|
cb(null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
// Move uploads to data dir
|
2016-07-08 20:44:48 +00:00
|
|
|
cb => {
|
|
|
|
fs.stat(`data/${req.id}`, (err, stat) => {
|
|
|
|
if (err && err.code === 'ENOENT') cb();
|
|
|
|
else cb(new Error(`Directory exists (should not have happened: ${err.code})`));
|
|
|
|
});
|
|
|
|
},
|
|
|
|
cb => { fs.mkdir(`data/${req.id}`, undefined, cb); },
|
|
|
|
cb => {
|
|
|
|
fs.rename(`tmp/${req.id}`, `data/${req.id}/images`, err => {
|
2016-07-26 19:20:37 +00:00
|
|
|
if (!err) cb();
|
|
|
|
else cb(new Error("Could not move images folder."))
|
2016-07-07 22:07:17 +00:00
|
|
|
});
|
2016-07-26 19:20:37 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// Create task
|
|
|
|
cb => {
|
|
|
|
new Task(req.id, req.body.name, (err, task) => {
|
|
|
|
if (err) cb(err);
|
|
|
|
else{
|
|
|
|
taskManager.addNew(task);
|
|
|
|
res.json({uuid: req.id, success: true});
|
|
|
|
cb();
|
|
|
|
}
|
|
|
|
}, req.body.options);
|
2016-07-06 18:44:20 +00:00
|
|
|
}
|
2016-07-08 20:44:48 +00:00
|
|
|
], err => {
|
|
|
|
if (err) res.json({error: err.message})
|
2016-07-06 18:44:20 +00:00
|
|
|
});
|
2016-07-05 18:06:22 +00:00
|
|
|
}
|
2016-07-06 18:44:20 +00:00
|
|
|
});
|
|
|
|
|
2016-07-08 20:44:48 +00:00
|
|
|
let getTaskFromUuid = (req, res, next) => {
|
2016-07-06 18:44:20 +00:00
|
|
|
let task = taskManager.find(req.params.uuid);
|
|
|
|
if (task){
|
2016-07-08 20:44:48 +00:00
|
|
|
req.task = task;
|
|
|
|
next();
|
2016-07-06 18:44:20 +00:00
|
|
|
}else res.json({error: `${req.params.uuid} not found`});
|
2016-07-08 20:44:48 +00:00
|
|
|
}
|
|
|
|
|
2016-07-09 16:58:14 +00:00
|
|
|
app.get('/task/:uuid/info', getTaskFromUuid, (req, res) => {
|
2016-07-08 20:44:48 +00:00
|
|
|
res.json(req.task.getInfo());
|
|
|
|
});
|
2016-07-09 16:58:14 +00:00
|
|
|
app.get('/task/:uuid/output', getTaskFromUuid, (req, res) => {
|
|
|
|
res.json(req.task.getOutput(req.query.line));
|
2016-07-04 20:59:07 +00:00
|
|
|
});
|
2016-07-18 21:00:01 +00:00
|
|
|
app.get('/task/:uuid/download/:asset', getTaskFromUuid, (req, res) => {
|
|
|
|
if (!req.params.asset || req.params.asset === "all"){
|
|
|
|
res.download(req.task.getAssetsArchivePath(), "all.zip", err => {
|
|
|
|
if (err) res.json({error: "Asset not ready"});
|
|
|
|
});
|
|
|
|
}else{
|
|
|
|
res.json({error: "Invalid asset"});
|
|
|
|
}
|
|
|
|
});
|
2016-07-04 20:59:07 +00:00
|
|
|
|
2016-07-07 22:07:17 +00:00
|
|
|
let uuidCheck = (req, res, next) => {
|
|
|
|
if (!req.body.uuid) res.json({error: "uuid param missing."});
|
|
|
|
else next();
|
|
|
|
};
|
|
|
|
|
|
|
|
let successHandler = res => {
|
|
|
|
return err => {
|
|
|
|
if (!err) res.json({success: true});
|
|
|
|
else res.json({error: err.message});
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2016-07-09 16:58:14 +00:00
|
|
|
app.post('/task/cancel', uuidCheck, (req, res) => {
|
2016-07-07 22:07:17 +00:00
|
|
|
taskManager.cancel(req.body.uuid, successHandler(res));
|
|
|
|
});
|
|
|
|
|
2016-07-09 16:58:14 +00:00
|
|
|
app.post('/task/remove', uuidCheck, (req, res) => {
|
2016-07-07 22:07:17 +00:00
|
|
|
taskManager.remove(req.body.uuid, successHandler(res));
|
|
|
|
});
|
|
|
|
|
2016-07-09 16:58:14 +00:00
|
|
|
app.post('/task/restart', uuidCheck, (req, res) => {
|
2016-07-07 22:07:17 +00:00
|
|
|
taskManager.restart(req.body.uuid, successHandler(res));
|
|
|
|
});
|
|
|
|
|
2016-07-26 01:10:18 +00:00
|
|
|
app.get('/getOptions', (req, res) => {
|
2016-07-26 19:20:37 +00:00
|
|
|
odmOptions.getOptions((err, options) => {
|
2016-07-26 01:10:18 +00:00
|
|
|
if (err) res.json({error: err.message});
|
|
|
|
else res.json(options);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-07-15 21:19:50 +00:00
|
|
|
let gracefulShutdown = done => {
|
|
|
|
async.series([
|
2016-07-26 19:20:37 +00:00
|
|
|
cb => { taskManager.dumpTaskList(cb); },
|
2016-07-15 21:19:50 +00:00
|
|
|
cb => {
|
|
|
|
console.log("Closing server");
|
|
|
|
server.close();
|
|
|
|
console.log("Exiting...");
|
|
|
|
process.exit(0);
|
|
|
|
}
|
|
|
|
], done);
|
|
|
|
};
|
|
|
|
|
|
|
|
// listen for TERM signal .e.g. kill
|
|
|
|
process.on ('SIGTERM', gracefulShutdown);
|
|
|
|
|
|
|
|
// listen for INT signal e.g. Ctrl-C
|
|
|
|
process.on ('SIGINT', gracefulShutdown);
|
|
|
|
|
|
|
|
// Startup
|
|
|
|
let taskManager;
|
|
|
|
let server;
|
2016-07-26 01:10:18 +00:00
|
|
|
|
2016-07-15 21:19:50 +00:00
|
|
|
async.series([
|
|
|
|
cb => { taskManager = new TaskManager(cb); },
|
|
|
|
cb => { server = app.listen(3000, err => {
|
|
|
|
if (!err) console.log('Server has started on port 3000');
|
|
|
|
cb(err);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
], err => {
|
|
|
|
if (err) console.log("Error during startup: " + err.message);
|
2016-07-26 01:10:18 +00:00
|
|
|
});
|