pp-parachute
Version:
Airdrop JS Applications
140 lines (119 loc) • 4.45 kB
JavaScript
var express = require('express');
var path = require('path');
var send = require('send');
var url = require('url');
var bodyParser = require('body-parser');
var httpProxy = require('http-proxy');
var app = express();
app.engine('html', require('./util/html_view_engine'));
app.engine('haml', require('haml-coffee').__express);
app.engine('jade', require('jade').__express);
var config = require('./../shared/config');
var explosives = require('../shared/explosives');
var applicationManager = require('./../shared/manager');
//todo implement an 'onAssetMissing' handler
//todo implement asset concept -- images, json, etc
//todo implement build pipeline
//todo collision check servedAtUrls
//todo handle per - url view files
//todo implement logging framework that can forward to user log handlers['info', 'http', 'error', 'build'] -- would be nice to stream these to client
var proxy = httpProxy.createProxyServer({});
proxy.on('error', function (err, req, res) {
console.log(err);
res.status(500);
res.send('Something went wrong with an HTTP request<br/>' + err + '<br/>' + err.stack);
});
app.use(function (req, res, next) {
explosives.setCharge(next);
applicationManager.setEnvironmentForUrl(req.url);
var currentEnvironment = applicationManager.getCurrentEnvironment();
//redirect to same url + '/' if match but url doesn't have a trailing /
if (!currentEnvironment || !applicationManager.hasExactUrl(req.url)) return next();
applicationManager.serveCurrentEnvironment(req, res, server).then(function (passed) {
if (!res.headersSent) {
if (passed) return next();
defaultBuildFailure(req, res);
}
}).catch(function (e) {
next();
});
});
app.use(function (req, res, next) {
var pathname = url.parse(req.url).pathname;
var matchedUrl = applicationManager.getMatchedUrl();
if (matchedUrl !== pathname && matchedUrl + '/' !== pathname) return next();
var viewData = applicationManager.getViewData(req.url);
app.set('views', viewData.viewDirectory);
app.set('view engine', viewData.viewEngine);
res.render(viewData.viewFile);
});
app.use(function (req, res, next) {
if (!applicationManager.getCurrentEnvironment()) return next();
var assetRoot = applicationManager.getAssetRoot();
var matchedUrl = applicationManager.getMatchedUrl();
var pathname = url.parse(req.url).pathname;
pathname = pathname.substring(matchedUrl.length);
var sendStream = send(req, pathname, {
root: assetRoot,
index: false
});
sendStream.on('directory', function () {
next();
});
sendStream.on('error', function (e) {
console.log('error', e);
next();
});
sendStream.pipe(res);
});
app.post('/__reserved/add_application', function (req, res) {
bodyParser(req, res, function () {
applicationManager.addApplication(req.body.appPath);
res.status(200);
});
});
app.post('/__reserved/remove_application', function (req, res) {
bodyParser(req, res, function () {
applicationManager.removeApplication(req.body.appName);
res.status(200);
});
});
app.post('/__reserved/rename_application', function (req, res) {
bodyParser(req, res, function () {
applicationManager.renameApplication(req.body.appName, req.body.newName);
res.status(200);
});
});
app.get('/__reserved/ping', function (req, res) {
res.status(200);
});
app.use(function (req, res, next) {
proxy.web(req, res, {
target: {
host: config.getProxyHost(),
port: config.getProxyPort()
}
});
});
app.use(function (error, req, res, next) {
res.send(error.stack);
});
process.on('error', function (e) {
console.log(e, 'error');
});
var server = app.listen(config.getPort(), function () {
console.log('Parachute opened at http://%s:%s', config.getHost(), config.getPort());
});
function defaultBuildFailure(req, res) {
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
res.render('build_fail', {
environmentName: applicationManager.getCurrentEnvironment().name,
applicationName: applicationManager.getCurrentEnvironment().getApplication().name,
failedBundlers: applicationManager.getCurrentEnvironment().getFailedBundles()
});
}
process.on('SIGINT', function () {
process.exit();
});
module.exports = server;