138 lines
4.2 KiB
JavaScript
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;
|