mirror of
https://github.com/jsbin/jsbin.git
synced 2026-01-18 15:18:04 +00:00
185 lines
5.3 KiB
JavaScript
185 lines
5.3 KiB
JavaScript
var express = require('express'),
|
|
flatten = require('flatten').flatten,
|
|
hogan = require('hogan.js'),
|
|
gobo = require('gobo'),
|
|
path = require('path'),
|
|
fs = require('fs'),
|
|
app = express.createServer(),
|
|
errors = require('./errors'),
|
|
options = require('./config'),
|
|
spike = require('./spike'),
|
|
store = require('./store')(options.store),
|
|
models = require('./models'),
|
|
handlers = require('./handlers'),
|
|
middleware = require('./middleware'),
|
|
binHandler = new handlers.BinHandler(),
|
|
sessionHandler = new handlers.SessionHandler(),
|
|
flattened;
|
|
|
|
app.store = store;
|
|
app.spike = spike;
|
|
app.models = models.createModels(store);
|
|
app.templates = {};
|
|
|
|
app.PRODUCTION = 'production';
|
|
app.DEVELOPMENT = 'development';
|
|
|
|
// Apply the keys from the config file. All nested properties are
|
|
// space delimited to match the express style.
|
|
//
|
|
// For example, app.set('url prefix'); //=> '/'
|
|
flattened = flatten(options, ' ');
|
|
Object.getOwnPropertyNames(flattened).forEach(function (key) {
|
|
app.set(key, flattened[key]);
|
|
});
|
|
|
|
app.set('root', path.resolve(path.join(__dirname, '..')));
|
|
app.set('version', require('../package').version);
|
|
app.set('url prefix', options.url.prefix.replace(/\/$/, ''));
|
|
app.set('url full', (app.set('url ssl') ? 'https://' : 'http://') + app.set('url host') + app.set('url prefix'));
|
|
|
|
// Register all the middleware.
|
|
app.use(express.logger());
|
|
app.use(express.static(path.join(app.set('root'), 'public')));
|
|
app.use(express.cookieParser(app.set('session secret')));
|
|
app.use(express.cookieSession({key: 'jsbin'}));
|
|
app.use(express.bodyParser());
|
|
app.use(express.csrf());
|
|
app.use(middleware.subdomain(app));
|
|
app.use(middleware.noslashes());
|
|
app.use(middleware.ajax());
|
|
app.use(middleware.cors());
|
|
app.use(middleware.jsonp());
|
|
app.use(middleware.helpers(app));
|
|
|
|
// Create a Hogan/Mustache handler for templates.
|
|
app.engine('html', function (path, options, fn) {
|
|
fs.readFile(path, 'utf8', function (err, template) {
|
|
if (err) {
|
|
return fn(err);
|
|
}
|
|
|
|
try {
|
|
var compiled = app.templates[path];
|
|
if (!compiled) {
|
|
compiled = app.templates[path] = hogan.compile(template);
|
|
}
|
|
|
|
fn(null, compiled.render(options));
|
|
} catch (error) {
|
|
fn(error);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Events
|
|
|
|
binHandler.on('updated', spike.ping.bind(spike));
|
|
binHandler.on('render-scripts', spike.appendScripts.bind(spike));
|
|
|
|
// Configure the template engine.
|
|
app.set('view engine', 'html');
|
|
app.set('views', path.join(app.set('root'), 'views'));
|
|
|
|
// Define some generic template variables.
|
|
app.locals({
|
|
version: app.set('version')
|
|
});
|
|
|
|
// Load the bin from the store when encountered in the url. Also handles the
|
|
// "latest" url action.
|
|
app.param('bin', binHandler.loadBin);
|
|
|
|
// Set up the routes.
|
|
app.get('/', binHandler.getDefault);
|
|
|
|
// Login/Create account.
|
|
app.post('/sethome', sessionHandler.loadUser, sessionHandler.loginUser, sessionHandler.createUser);
|
|
app.post('/logout', sessionHandler.logoutUser);
|
|
|
|
// List
|
|
app.get('/list', binHandler.getUserBins);
|
|
|
|
// Latest
|
|
app.get('/:bin/latest((.|\/):format)?', binHandler.redirectToLatest);
|
|
app.get('/:bin/latest/edit', binHandler.redirectToLatest);
|
|
|
|
// Edit
|
|
app.get('/:bin/:rev?/edit', binHandler.getBin);
|
|
|
|
// Save
|
|
app.post('/save', binHandler.createBin);
|
|
app.post('/:bin/:rev?/save', binHandler.createRevision);
|
|
|
|
// Download
|
|
app.get('/:bin/:rev?/download', binHandler.downloadBin);
|
|
|
|
// Source
|
|
app.get('/:bin/:rev?/source', binHandler.getBinSource);
|
|
app.get('/:bin/:rev?.:format(js|json|css|html)', binHandler.getBinSourceFile);
|
|
app.get('/:bin/:rev?/:format(js)', function (req, res) {
|
|
// Redirect legacy /js suffix to the new .js extension.
|
|
res.redirect(301, req.path.replace(/\/js$/, '.js'));
|
|
});
|
|
|
|
// Log
|
|
app.get('/:bin/:rev/log', spike.getLog);
|
|
app.post('/:bin/:rev/log', spike.postLog);
|
|
|
|
// Preview
|
|
app.get('/:bin/:quiet(quiet)?', binHandler.getBinPreview);
|
|
app.get('/:bin/:rev?/:quiet(quiet)?', spike.getStream, binHandler.getBinPreview);
|
|
|
|
// Serve the concatenated JavaScript.
|
|
app.get('/js/debug/jsbin.js', function (req, res) {
|
|
var js = path.join(app.set('root'), 'public', 'js');
|
|
gobo(path.join(js, 'jsbin.js'), 'vendor', function (content) {
|
|
res.contentType('js');
|
|
res.send(content);
|
|
});
|
|
});
|
|
|
|
// Error handler.
|
|
app.use(function (err, req, res, next) {
|
|
if (err instanceof errors.NotFound) {
|
|
return binHandler.notFound(req, res);
|
|
}
|
|
next(err);
|
|
});
|
|
|
|
// Final connect in error handler. Ideally should never hit this.
|
|
app.use(express.errorHandler({showStack: true, dumpExceptions: true}));
|
|
|
|
// Export the application to allow it to be included.
|
|
module.exports = app;
|
|
if (app.set('url prefix') !== '/') {
|
|
// If we have a prefix then mount the app within another
|
|
// express app to save us hacking around with the routes.
|
|
module.exports = express().use(app.set('url prefix'), app);
|
|
}
|
|
|
|
// Run a local development server if this file is called directly.
|
|
if (require.main === module) {
|
|
store.connect(function (err) {
|
|
if (err) {
|
|
throw err;
|
|
}
|
|
|
|
var port = process.env.PORT;
|
|
if (!port) {
|
|
options.url.host.replace(/\:(\d+)$/, function (m, p) {
|
|
if (p.length) {
|
|
port = p;
|
|
}
|
|
});
|
|
}
|
|
|
|
if (!port) {
|
|
port = 80;
|
|
}
|
|
|
|
process.stdout.write('Running jsbin on port ' + port + '\n');
|
|
module.exports.listen(port);
|
|
});
|
|
}
|