1
0
James Ketrenos dca37b1723 Seeding server code from ketr.photos
Signed-off-by: James Ketrenos <james.p.ketrenos@intel.com>
2020-04-20 12:13:22 -07:00

138 lines
4.2 KiB
JavaScript

"use strict";
const express = require('express'),
morgan = require('morgan'),
cookieParser = require('cookie-parser'),
bodyParser = require('body-parser'),
http = require('http'),
config = require('config'),
app = express(),
{ timestamp } = require('./timestamp'),
fs = require('fs'),
util = require('util'),
mkdir = util.promisify(fs.mkdir),
unlink = util.promisify(fs.unlink),
path = require('path'),
fetch = require('node-fetch'),
Promise = require('bluebird'),
url = require('url'),
{ exec } = require('child_process');
fetch.Promise = Promise;
const basePath = "/" + config.get("http.base").replace(/^\/*/, "").replace(/\/*$/, "") + "/",
dataPath = "/" + config.get("dataPath").replace(/^\/*/, "").replace(/\/*$/, "") + "/";
/* */
if (!config.has("auth.idsid") || !config.has("auth.password")) {
console.error("You need to provide credentials to connect to ubit-gfx in config/local.json");
console.error(' "auth": { "idsid": "USERNAME", "password": "PASSWORD" }');
process.exit(-1);
}
app.use(morgan('common'));
app.use(bodyParser.json({
verify: function(req,res,buf) {
req.rawBody = buf;
}
}));
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(cookieParser());
/* Routes:
* /api/v1/publish Publish content to repository
*/
app.get("/*", (req, res, next) => {
/* */
return res.status(400).send({ usage: `POST ${basePath}api/v1/publish/:distro/:releaseStream/:url` });
});
const auth = new Buffer(config.get("auth.idsid") + ":" + config.get("auth.password"), 'ascii').toString('base64');
app.post(basePath + 'api/v1/publish/:distro/:releaseStream/:url', function (req, res, next) {
const distro = req.params.distro,
releaseStream = req.params.releaseStream,
remoteUrl = req.params.url;
let filename;
try {
filename = path.basename(url.parse(remoteUrl).pathname);
} catch (error) {
return res.status(400).send({ error: `Unparsable URL: ${remoteUrl}` });
}
if (distro.match(/\//) || releaseStream.match(/\//)) {
return res.status(400).send({ error: "Neither distro nor releaseStream may contain '/'" });
}
console.log(`POST publish/${distro}-${releaseStream}/${filename}`);
const filepath = `${dataPath}${distro}-${releaseStream}`;
return mkdir(filepath, { recursive: true }, () => {
const pathname = `${filepath}/${filename}`;
if (fs.existsSync(pathname)) {
return res.status(409).send({ message: `'${distro}-${releaseStream}/${filename}' already exists.` });
}
return fetch(remoteUrl, {
method: "GET",
headers: {
'Authorization': `Basic ${auth}`
}
}).then(result => {
const dest = fs.createWriteStream(pathname);
dest.on('finish', () => {
exec(`./update-repository.sh ${distro}-${releaseStream}`, {
cwd: ".." ,
shell: "/bin/bash"
}, (error, stdout, stderr) => {
if (error) {
return unlink(pathname).catch(() => {
console.error(`Unable to remove ${pathname} after update-repository.sh failed.`);
}).then(() => {
return res.status(500).send({ message: "Error while updating aptly database.", error: error, stderr: stderr, stdout: stdout });
});
}
return res.status(200).send({ message: "OK", stdout: stdout || "", stderr: stderr || "" });
});
});
result.body.pipe(dest);
}).catch((error )=> {
const message = `Unable to download ${remoteUrl}: ${error}`;
console.error(message);
return res.status(500).send({ message: message });
});
}).catch((error) => {
const message = `Unable to mkdir ${filepath}: ${error}`;
console.error(message);
return res.status(500).send({ message: message });
});
});
app.post("/*", (req, res, next) => {
/* */
return res.status(400).send({ usage: `POST /${basePath}/api/v1/publish/:distro/:releaseStream/:url` });
});
const server = http.createServer(app),
port = config.has("port") ? config.get("port") : 6543;
server.listen(port);
server.on('listening', function() {
let addr = server.address();
let bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
console.log(timestamp() + ` Now serving ${basePath} on ${bind}`);
});
module.exports = server;