"xml": "text/xml" }; var cfg = { ssl: false, port: 8060, ssl_key: '/home/janson/projects/nodejs/ws/examples/tmp/privatekey.pem', ssl_cert: '/home/janson/projects/nodejs/ws/examples/tmp/certificate.pem' }; var http = null; var app = null; if(cfg.ssl) { http = require("https"); app = express.createServer({ key: fileSystem.readFileSync( cfg.ssl_key ), cert: fileSystem.readFileSync( cfg.ssl_cert ) }); } else { http = require("http"); app = express.createServer(); } var userMap = new HashMap(); var userMgrMax = 512; var protocolHeaderLen = 16; //负责处理Web请求 var httpProcessor = (function () { function HttpProcessor(req, res, seq) { this.req = req; this.res = res;
* Please see the LICENSE file for more information. * */ /** * web server/service to wrap interactions w/ GitHub API */ var fs = require('fs'), url = require('url'), express = require('express'), connect = require('connect'), request = require('request'), dbox = require('dropbox').DropboxClient, app = express.createServer( connect.bodyParser(), connect.cookieParser()), locker = require('../../Common/node/locker.js'), lfs = require('../../Common/node/lfs.js'); var me; app.set('views', __dirname); app.get('/', handleIndex); var dapp=false; function handleIndex(req, res) { res.writeHead(200, {'Content-Type': 'text/html'}); if(dapp) { res.end(fs.readFileSync(__dirname + '/ui/index.html'));
* Ukážková real-time webová aplikácia pre bakalársku prácu s témou real-time webové aplikácie * určená k demonštrácii real-time komunikácie klienta so serverom transporným spôsobom uvedeným vyššie. * * Aplikácia má implementované iba dve funkcie - pridanie novej úlohy a získanie úloh zo servera. * Aplikácia neobsahuje všetky potrebné prvky, ktoré by boli pokryté v produkčnej aplikácii, * ako overovanie hodnôt získaných od užívateľa a podobne. * * Pozn. úlohy nie sú ukladané do databázy preto je ich životnosť iba po dobu spustenia aplikácie. * * @author Matej Paulech <*****@*****.**> */ // Závislosti (moduly) var express = require('express'); var app = module.exports = express.createServer(); var Todo = require('./todo'); var Todos = require('./todos'); // Vytvorenie objektu so zoznamom úloh a pridanie 2 ukážkových úloh var todos = new Todos(); todos.add('Nakúpiť mlieko'); todos.add('Dopísať bakalárku'); // Nastavenia // Funkcia pre vlastný formátu času v logoch express.logger.format('date', function () { var date = new Date(); return date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
exports.createServer = function () { var app = express.createServer(); global.backend = require('./backend'); global.io = socket.listen(app); // TODO: move to the right position var RedisStore = require('connect-redis')(express); // Configuration app.configure(function() { app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.set('view options', { layout : false }); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(express.cookieParser()); // TODO: move to the right position - use a general way with the given backend app.use(express.session({ store: new RedisStore({ client: global.db }), secret: 'UsMohsaEkB14iwuterECSv29HEbJ407h' })); app.use(app.router); app.use(express.static(__dirname + '/public', { maxAge: 24*60*60*1000 })); }); app.configure('development', function(){ app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.configure('production', function(){ app.use(express.errorHandler()); }); // Routes var routes = require('./routes'); app.setStart = function(path) { app.get('/', function(req,res) { res.redirect(path); }); } app.addViewer = function () { app.get('/projector', function(req, res) { res.render('showProjector', {}); }); app.get('/timer', function(req, res) { res.render('showTimer', {}); }); global.projectorSocket = io.registerProjector(); global.timerSocket = io.registerTimers(); global.agendaSocket = io.registerAgenda(); global.motionSocket = io.registerMotions(); global.electionSocket = io.registerElections(); global.ballotSocket = io.registerBallots(); global.votesSocket = io.registerVotes(); } // callback is temporary out of usage. will fix this later app.addAdmin = function(callback) { function generateCallback(route) { return route; } app.get('/admin', generateCallback(function (req, res) { res.render('admin'); })); app.get('/votes', generateCallback(function (req, res) { res.render('postVotes'); })); app.post('/votes', generateCallback(routes.votes.setVotes)); app.post('/identify-projectors', generateCallback(routes.projectors.identify) ); app.put('/agenda/:slideid/save', generateCallback(routes.agenda.save) ); app.post('/agenda/:slideid/delete', generateCallback(routes.agenda.delete) ); app.post('/agenda/:slideid/move', generateCallback(routes.agenda.move) ); app.put('/projectors', generateCallback(routes.projectors.setDefault) ); app.put('/projectors/:projectorid/save', generateCallback(routes.projectors.save) ); app.post('/projectors/:projectorid/delete', generateCallback(routes.projectors.delete) ); app.post('/projectors/:projectorid/showtimer', generateCallback(routes.projectors.showTimer) ); app.post('/projectors/:projectorid/hidetimer', generateCallback(routes.projectors.hideTimer) ); app.post('/projectors/:projectorid/flash', generateCallback(routes.projectors.flash) ); app.put('/timers/:timerid/save', generateCallback(routes.timers.save) ); app.post('/timers/:timerid/delete', generateCallback(routes.timers.delete) ); app.post('/timers/:timerid/start', generateCallback(routes.timers.start) ); app.post('/timers/:timerid/pause', generateCallback(routes.timers.pause) ); app.post('/timers/:timerid/stop', generateCallback(routes.timers.stop) ); app.put('/motionclasses/:motionclassid/save', generateCallback(routes.motionclasses.save) ); app.post('/motionclasses/:motionclassid/delete', generateCallback(routes.motionclasses.delete) ); app.post('/motionclasses/:motionclassid/move', generateCallback(routes.motionclasses.move) ); app.put('/motions/:motionid/save', generateCallback(routes.motions.save) ); app.post('/motions/:motionid/delete', generateCallback(routes.motions.delete) ); app.post('/motions/:motionid/move', generateCallback(routes.motions.move) ); app.put('/motions/:motionid/addBallot', generateCallback(routes.motions.addBallot) ); app.post('/motions/:motionid/deleteBallot', generateCallback(routes.motions.deleteBallot) ); app.put('/elections/:electionid/save', generateCallback(routes.elections.save) ); app.post('/elections/:electionid/delete', generateCallback(routes.elections.delete) ); app.put('/elections/:electionid/addBallot', generateCallback(routes.elections.addBallot) ); app.post('/elections/:electionid/deleteBallot', generateCallback(routes.elections.deleteBallot) ); app.put('/ballots/:ballotid/save', generateCallback(routes.ballots.save) ); app.put('/ballots/:ballotid/addOption', generateCallback(routes.ballots.addOption) ); app.post('/ballots/:ballotid/moveOption', generateCallback(routes.ballots.moveOption) ); app.post('/ballots/:ballotid/deleteOption', generateCallback(routes.ballots.deleteOption) ); app.put('/options/:optionid/save', generateCallback(routes.options.save) ); app.put('/pollsites/:pollsiteid/save', generateCallback(routes.pollsites.save) ); app.post('/pollsites/:pollsiteid/delete', generateCallback(routes.pollsites.delete) ); global.pollsiteSocket = io.registerPollsites(); } // Showtime! app.start = function() { new compressor.minify({ type: 'no-compress', fileIn: [ "public/libs/jquery-miniColors/jquery.miniColors.css", "public/libs/bootstrap/css/bootstrap.min.css", "public/libs/bootstrap/css/bootstrap-responsive.min.css", "public/stylesheets/admin.css" ], fileOut: "public/min/admin.css" }); new compressor.minify({ type: 'no-compress', fileIn: [ "public/libs/jquery-1.7.2.min.js", "public/libs/jquery-ui-1.8.21.custom.min.js", "public/libs/jquery.mjs.nestedSortable.js", "public/libs/jquery-miniColors/jquery.miniColors.min.js", "public/libs/jquery.cookie.js", "public/libs/treeTable.js", "public/libs/sortedList.js", "public/libs/viewerOptions.js", "public/javascript/admin/selectProjector.js", "public/libs/bootstrap/js/bootstrap.min.js", "public/apiClient/timerClient.js", "public/apiClient/index.js", "public/apiClient/projectors.js", "public/apiClient/agenda.js", "public/apiClient/timers.js", "public/apiClient/motionclasses.js", "public/apiClient/motions.js", "public/apiClient/pollsites.js", "public/apiClient/elections.js", "public/apiClient/ballots.js", "public/apiClient/options.js", "public/apiClient/votes.js", "public/javascript/admin/index.js", "public/javascript/admin/navigation.js", "public/javascript/admin/projectors.js", "public/javascript/admin/flashmessages.js", "public/javascript/admin/agenda.js", "public/javascript/admin/timers.js", "public/javascript/admin/motions.js", "public/javascript/admin/pollsites.js", "public/javascript/admin/elections.js", "public/javascript/admin/ballots.js" ], fileOut: "public/min/admin.js" }); new compressor.minify({ type: 'no-compress', fileIn: [ "public/stylesheets/showProjector.css" ], fileOut: "public/min/showProjector.css" }); new compressor.minify({ type: 'no-compress', fileIn: [ "public/libs/jquery-1.7.2.min.js", "public/libs/jquery-ui-1.8.21.custom.min.js", "public/libs/jquery.properMenu.js", "public/libs/sortedList.js", "public/libs/viewerOptions.js", "public/apiClient/index.js", "public/apiClient/projectors.js", "public/apiClient/agenda.js", "public/apiClient/timers.js", "public/apiClient/motionclasses.js", "public/apiClient/motions.js", "public/apiClient/elections.js", "public/apiClient/ballots.js", "public/apiClient/options.js", "public/apiClient/timerClient.js", "public/apiClient/votes.js", "public/javascript/viewer/index.js", "public/javascript/viewer/navigation.js", "public/javascript/viewer/viewerdata.js", "public/javascript/viewer/currenttime.js", "public/javascript/viewer/defaultprojector.js", "public/javascript/viewer/projectors.js", "public/javascript/viewer/agenda.js", "public/javascript/viewer/motions.js", "public/javascript/viewer/elections.js", "public/javascript/viewer/ballots.js" ], fileOut: "public/min/showProjector.js" }); new compressor.minify({ type: 'no-compress', fileIn: [ "public/stylesheets/showTimer.css" ], fileOut: "public/min/showTimer.css" }); new compressor.minify({ type: 'no-compress', fileIn: [ "public/libs/jquery-1.7.2.min.js", "public/libs/jquery-ui-1.8.21.custom.min.js", "public/libs/viewerOptions.js", "public/apiClient/index.js", "public/apiClient/projectors.js", "public/apiClient/agenda.js", "public/apiClient/timers.js", "public/apiClient/motionclasses.js", "public/apiClient/motions.js", "public/apiClient/elections.js", "public/apiClient/ballots.js", "public/apiClient/options.js", "public/apiClient/timerClient.js", "public/apiClient/votes.js", "public/javascript/showTimer/index.js", "public/javascript/showTimer/navigation.js", "public/javascript/showTimer/currenttime.js", "public/javascript/showTimer/defaultprojector.js", "public/javascript/showTimer/projectors.js", "public/javascript/showTimer/timers.js" ], fileOut: "public/min/showTimer.js" }); new compressor.minify({ type: 'no-compress', fileIn: [ "public/libs/jquery-1.7.2.min.js", "public/libs/jquery-ui-1.8.21.custom.min.js", "public/apiClient/timerClient.js", "public/apiClient/index.js", "public/apiClient/projectors.js", "public/apiClient/agenda.js", "public/apiClient/timers.js", "public/apiClient/motionclasses.js", "public/apiClient/motions.js", "public/apiClient/pollsites.js", "public/apiClient/elections.js", "public/apiClient/ballots.js", "public/apiClient/options.js", "public/apiClient/votes.js", "public/javascript/postVotes/index.js" ], fileOut: "public/min/postVotes.js" }); app.listen(config.port, config.host, function() { if (process.getuid() == 0) { process.setgid(config.setgid); process.setuid(config.setuid); } }); console.log("Express server listening on http://%s:%d/ in mode %s", config.host || "localhost", config.port, app.settings.env); } return app; }
db.init(function() { db.ensureUser('*****@*****.**', 'benny'); db.ensureUser('*****@*****.**', 'johnny'); db.ensureUser('*****@*****.**', 'terry'); db.ensureUser('*****@*****.**', 'sheerun'); db.ensureFollower('*****@*****.**', '*****@*****.**'); db.ensureFollower('*****@*****.**', '*****@*****.**'); db.ensureFollower('*****@*****.**', '*****@*****.**'); db.ensureFollower('*****@*****.**', '*****@*****.**'); var err = function(err) { console.log(err); }; db.getUserByEmail('*****@*****.**', function(user) { if (user) { db.addTweet(user.id, 'Johhny says hi @' + new Date(), function() { console.log("Added tweet " + user.email); }, err); } }, err); db.getUserByEmail('*****@*****.**', function(user) { if (user) { db.addTweet(user.id, 'Benny says hi @' + new Date(), function() { console.log("Added tweet " + user.email); }, err); } }, err); db.getUserByEmail('*****@*****.**', function(user) { if (user) { db.addTweet(user.id, 'Terry says hi @' + new Date(), function() { console.log("Added tweet " + user.email); }, err); } }, err); var app = module.exports = express.createServer(); app.configure(function(){ app.set('views', __dirname + '/views'); app.set('view engine', 'ejs'); app.use(express.cookieParser()); app.use(express.session({ secret: "muhahahahah" })); app.use(express.static(__dirname + '/public')); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); }); app.configure('development', function(){ app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.configure('production', function(){ app.use(express.errorHandler()); }); // Routes app.all('*', function(req, res, next){ var errorFlashes = []; var infoFlashes = []; var parentRender = res.render; res.render = function(tpl, data) { arguments[1] = arguments[1] || {}; arguments[1].error = (function() { var errors = req.flash('error'); if (errors.length) { errorFlashes.push.apply(errorFlashes, errors); } return errorFlashes.join('<br/>'); })(); if (!arguments[1].error.length) { delete arguments[1].error; } arguments[1].info = (function(){ var infos = req.flash('info'); if (infos.length) { infoFlashes.push.apply(infoFlashes, infos); } return infoFlashes.join('<br/>'); })(); if (!arguments[1].info.length) { delete arguments[1].info; } return parentRender.apply(res,_.toArray(arguments)); } if(req.session && req.session.userid) { db.getUserById(req.session.userid, function(user) { res.local('user', user); next(); }); } else { if (req.url !== '/login') { res.redirect('/login'); return; } next(); } }); app.get('/', function(req, res, next) { var user = res.local('user'); var followed = user.followed; followed.push(user.id); db.getTweetsOfUsers(followed, 10, function(tweets) { ; res.render('tweets', { title: 'Tweets', tweets: tweets }); }, function(err) { next(err); }); }); app.get('/logout', function(req, res){ delete req.session.userid; res.redirect('/'); }); app.get('/login', function(req, res, next){ var tplData = { title: 'Twitter - Get the f**k sign in' }; res.render('login', tplData); }); app.post('/login', function(req, res, next){ var tplData = { title: 'Twitter - Get the f**k sign in', content: 'Foobar' }; var email = req.param('email'); var password = req.param('password'); if (email && password && email.length && password.length && email.indexOf('@') !== -1 && email.indexOf('@') !== 0 && email.indexOf('@') !== (email.length - 1)) { tplData.email = email; db.getUserByEmail(email, function(user) { if (user === null) { db.addUser(email, password, function(user_id) { req.session.userid = user_id; req.flash('info', 'Hello mrs. "' + email + '" :)'); res.redirect('/'); }, function(err) { next(err); }); return; } if (user.password !== password) { req.flash('error', 'Bad password bitch!'); res.render('login', tplData); return; } req.session.userid = user.id; req.flash('info', 'Hello mrs. "'+user.email+'" :)'); res.redirect('/'); }, function(){ req.flash('error', 'WAA!!! Everything crash!') }); } else { res.render('login', tplData); } }); app.get('/tweets', function(req, res){ db.getAllTweets(100, function (tweets) { res.render("tweets", { tweets: tweets, title: "Tweets" }); }, function () { res.redirect('/500'); }); }); app.post('/tweet', function(req, res){ var new_tweet = sanitizer.sanitize(req.body.body); if (new_tweet.trim().length == 0) { req.flash('error', "Tweet is empty."); res.redirect('/'); return; } db.addTweet(res.local("user").id, new_tweet, function () { req.flash('info', 'n***a has been appended to farm'); res.redirect('/'); }, function () { req.flash('error', "We're sorry, but posting your tweet was unsuccessful"); res.redirect('/'); }); }); app.get('/user/:user_id', function(req, res){ db.getUserById(req.params.user_id, function(user) { db.getTweetsOfUser(req.params.user_id, 100, function (tweets) { res.render("tweets", { tweets: tweets, can_follow: res.local('user').followed.indexOf(user.id) === -1, title: "Tweets", current_user: user }); }, function () { res.redirect('/500'); }); }); }); app.get('/user/:followee_id/follow', function(req, res){ if (res.local("user").followed.some ( function (id) { return id == req.params.followee_id } )) { req.flash('info', "You're already following this user."); res.redirect('/user/' + req.params.followee_id); return; } db.followUser(res.local("user").id, req.params.followee_id, function () { req.flash('info', 'Watching n***a at work BEGIN!'); res.redirect('/user/' + req.params.followee_id); }, function () { req.flash('error', "We're sorry, but attempt to follow '" + req.params.followee_id + "' was unsuccessful"); res.redirect('/user/' + req.params.followee_id); }); }); app.get('/user/:followee_id/unfollow', function(req, res){ if (!res.local("user").followed.some ( function (id) { return id == req.params.followee_id } )) { req.flash('info', "You have already stopped following this user."); res.redirect('/user/' + req.params.followee_id); return; } db.unfollowUser(res.local("user").id, req.params.followee_id, function () { req.flash('info', 'Stopping watching n***a at work BEGIN!'); res.redirect('/user/' + req.params.followee_id); }, function () { req.flash('error', "We're sorry, but attempt to unfollow '" + req.params.followee_id + "' was unsuccessful"); res.redirect('/user/' + req.params.followee_id); }); }); app.listen(3000); console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env); }, function(error) {
var Monitor = module.exports = function Monitor(options) { this.options = options || {port: 8081, stats: {}, path: '/'}; this.stats = this.options.stats; var app = express.createServer(); var self = this; app.set('views', __dirname + '/../public/views'); app.use(express.static(__dirname + '/../public')); app.set('view engine', 'html'); app.get(this.options.path, function (req, res) { var accept = (req.headers || {}).accept || ''; if(accept.search('json') > 0) { res.contentType('application/json'); res.send(JSON.stringify(getStats(self.stats, req.connection))); } else { res.render('index.ejs', getStats(self.stats, req.connection)); } }); app.get(/^\/logs?(?:\/(\d+)(?:\.\.(\d+))?)?/, function (req, res) { var root, paths, logs, stats; var file = process.cwd() + req.url; if(req.url === '/logs') { root = process.cwd() + '/logs'; paths = fs.readdirSync(root); logs = []; paths.forEach(function (filename) { stats = fs.statSync(root + '/' + filename); logs.push({ filename: filename, stats: stats }) }); var data = getStats(self.stats, req.connection); data.logs = logs; res.render('logs.ejs', data); } else { var stat = fs.statSync(file); res.writeHead(200, { 'Content-Type': 'text/plain', 'Content-Length': stat.size }); var readStream = fs.createReadStream(file); util.pump(readStream, res, function (e) { if(e) { console.log(e.stack || e); } res.end(); }); } }); app.get('/deps', function(req, res) { npm.load({}, function() { npm.commands.ls({}, true, function(e, data) { res.writeHead(200, { 'Content-Type': 'application/json' }); var seen = []; var out = JSON.stringify(data, function (k, o) { if(typeof o === "object") { if(-1 !== seen.indexOf(o)) return '[Circular]'; seen.push(o); } return o; }, 2); res.end(out); }); }); }); return app; }
var connect = require('connect'); var logger = require('logger').logger('worker'); var taskman = require('taskman'); var ijod = require('ijod'); var lconfig = require('lconfig'); var lutil = require('lutil'); var dal = require('dal'); var os = require('os'); var tstarted; var SOURCE_VERSION = 'Unknown'; var CONFIG_VERSION = 'Unknown'; var worker = express.createServer( connect.bodyParser(), connect.cookieParser() ); worker.get('/', function(req, res) { var cnt = 0; var tot = 0; taskman.stats().last.forEach(function(task) { cnt++; tot += (task.tdone - task.tstart); }); var ret = { sourceVersion: SOURCE_VERSION, configVersion: CONFIG_VERSION, active: Object.keys(taskman.stats().workers).length,
// Node.js Endpoint for ProjectRazor Image Service var razor_bin = __dirname + "/razor"; // Set project_razor.rb path var execFile = require("child_process").execFile; // create our execFile object var express = require('express'); // include our express libs var mime = require('mime'); var fs = require('fs'); var path = require('path'); var http_range_req = require('./http_range_req.js'); var common = require('./common.js'); var InvalidURIPathError = common.InvalidURIPathError; var urlDecode = common.urlDecode; var returnError = common.returnError; var image_svc_path; app = express.createServer(); // our express server app.get('/razor/image/*', function(req, res) { try { var args = req.path.split('/'); args.splice(0, 3); if (args.length > 0) { if (args[args.length - 1] == '') // Path ended with slash. Just skip this one args.pop(); for ( var i = 0; i < args.length; ++i) args[i] = urlDecode(args[i]); } var absPath = path.resolve(image_svc_path + args.join('/')); if(absPath.indexOf(image_svc_path) != 0) throw new InvalidURIPathError("Illegal path: '" + path + "'");
.signingKey(nconf.get("azure:signingKey")) .realm(nconf.get("azure:realm")) .homeRealm('') // if you want to use a default idp (like google/liveid) .tokenFormat('swt') // only swt supported for now .findOrCreateUser(function(session, userMetadata) { var promise = this.Promise(); users.findOrCreateUser(userMetadata, promise); return promise; }) .redirectPath('/'); var app = express.createServer( express.bodyParser(), express.static(__dirname + "/public"), express.cookieParser(), express.session( {secret: nconf.get("sessionKey")}), everyauth.middleware() ); app.set('view engine', 'jade'); app.get('/', function(req, res) { res.render('main.jade', {req: req, everyauth: everyauth}); }); app.get('/getLanguages', function(req, res) { var term = req.query.term; languages.findMatchingLanguages(term, res); }); var port = nconf.get("port");
var express = require('express'), path = require('path'), MongoClient = require('mongodb').MongoClient, app = module.exports = express.createServer(); /* зачем здесь это? "module.exports" ты ничего не экспортишь */ // Configuration app.configure(function(){ app.set('views', __dirname + '/views'); app.set('view engine', 'html'); /* раз уж это написал, тогда в срт. 40 res.render('./public/index'); */ app.use(express.bodyParser()); /* не используется нигде, пока что)) */ app.use(express.static(__dirname + '/public')); app.use(express.static(__dirname + '/node_modules')); /* не хорошо что у тебя все зависимости в одном, для фронта нужно ставить отдельно, в publick'е */ }); /** * Заварачивать весь сервак в коллбек монги плохая идея, тк. если нет соединения, сервер просто не стартонет, а должен сохранить весь функционал, просто не отображать никаких данных * в идеале отправлять ошибку, при запросе, типа "нет соединения с БД". */ MongoClient.connect('mongodb://localhost:27017/TravelList', function(err, db){ if (err){ throw err; }else var collection = db.collection('travelTask'), tasks; /* обьявил, но не инициализировал, непонятно что за тип данных */ collection.find().toArray(function(err, docs){ if (err) { throw err;
d = d.toString(16); while (d.length < digits) { d = '0' + d; } return d; } function h2d(h) { return parseInt(h,16); } /******************* END UTFGrid Functions ******************/ var app = Express.createServer(); app.use(Connect.compress()); // compression app.get('/', function(req, res){ res.send(fs.readFileSync('./views/leaflet.html', 'utf8')); }); app.get('/sf_tile.jsonp', function(req, res){ res.send(fs.readFileSync('./views/sf_tile.jsonp', 'utf8')); }); app.get('/tiles/:zoom/:col/:row', tile); app.get('/utfgrids/:zoom/:col/:row', utfgrid); app.listen(port);
//initalize the http server function (callback) { //create server var app = express.createServer(); //load modules that needs a initalized db readOnlyManager = require("./db/ReadOnlyManager"); exporthtml = require("./utils/ExportHtml"); exportHandler = require('./handler/ExportHandler'); importHandler = require('./handler/ImportHandler'); apiHandler = require('./handler/APIHandler'); padManager = require('./db/PadManager'); securityManager = require('./db/SecurityManager'); socketIORouter = require("./handler/SocketIORouter"); //install logging var httpLogger = log4js.getLogger("http"); app.configure(function() { // If the log level specified in the config file is WARN or ERROR the application server never starts listening to requests as reported in issue #158. // Not installing the log4js connect logger when the log level has a higher severity than INFO since it would not log at that level anyway. if (!(settings.loglevel === "WARN" || settings.loglevel == "ERROR")) app.use(log4js.connectLogger(httpLogger, { level: log4js.levels.INFO, format: ':status, :method :url'})); app.use(express.cookieParser()); }); //serve static files app.get('/static/*', function(req, res) { res.header("Server", serverName); var filePath = path.normalize(__dirname + "/.." + req.url.replace(/\.\./g, '').split("?")[0]); res.sendfile(filePath, { maxAge: exports.maxAge }); }); //serve minified files app.get('/minified/:id', function(req, res, next) { res.header("Server", serverName); var id = req.params.id; if(id == "pad.js" || id == "timeslider.js") { minify.minifyJS(req,res,id); } else { next(); } }); //checks for padAccess function hasPadAccess(req, res, callback) { securityManager.checkAccess(req.params.pad, req.cookies.sessionid, req.cookies.token, req.cookies.password, function(err, accessObj) { if(err) throw err; //there is access, continue if(accessObj.accessStatus == "grant") { callback(); } //no access else { res.send("403 - Can't touch this", 403); } }); } //serve read only pad app.get('/ro/:id', function(req, res) { res.header("Server", serverName); var html; var padId; var pad; async.series([ //translate the read only pad to a padId function(callback) { readOnlyManager.getPadId(req.params.id, function(err, _padId) { padId = _padId; //we need that to tell hasPadAcess about the pad req.params.pad = padId; callback(err); }); }, //render the html document function(callback) { //return if the there is no padId if(padId == null) { callback("notfound"); return; } hasPadAccess(req, res, function() { //render the html document exporthtml.getPadHTMLDocument(padId, null, false, function(err, _html) { html = _html; callback(err); }); }); } ], function(err) { //throw any unexpected error if(err && err != "notfound") throw err; if(err == "notfound") res.send('404 - Not Found', 404); else res.send(html); }); }); //serve pad.html under /p app.get('/p/:pad', function(req, res, next) { //ensure the padname is valid and the url doesn't end with a / if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url)) { res.send('Such a padname is forbidden', 404); return; } res.header("Server", serverName); var filePath = path.normalize(__dirname + "/../static/pad.html"); res.sendfile(filePath, { maxAge: exports.maxAge }); }); //serve timeslider.html under /p/$padname/timeslider app.get('/p/:pad/timeslider', function(req, res, next) { //ensure the padname is valid and the url doesn't end with a / if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url)) { res.send('Such a padname is forbidden', 404); return; } res.header("Server", serverName); var filePath = path.normalize(__dirname + "/../static/timeslider.html"); res.sendfile(filePath, { maxAge: exports.maxAge }); }); //serve timeslider.html under /p/$padname/timeslider app.get('/p/:pad/export/:type', function(req, res, next) { //ensure the padname is valid and the url doesn't end with a / if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url)) { res.send('Such a padname is forbidden', 404); return; } var types = ["pdf", "doc", "txt", "html", "odt"]; //send a 404 if we don't support this filetype if(types.indexOf(req.params.type) == -1) { next(); return; } //if abiword is disabled, and this is a format we only support with abiword, output a message if(settings.abiword == null && req.params.type != "html" && req.params.type != "txt" ) { res.send("Abiword is not enabled at this Etherpad Lite instance. Set the path to Abiword in settings.json to enable this feature"); return; } res.header("Access-Control-Allow-Origin", "*"); res.header("Server", serverName); hasPadAccess(req, res, function() { exportHandler.doExport(req, res, req.params.pad, req.params.type); }); }); //handle import requests app.post('/p/:pad/import', function(req, res, next) { //ensure the padname is valid and the url doesn't end with a / if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url)) { res.send('Such a padname is forbidden', 404); return; } //if abiword is disabled, skip handling this request if(settings.abiword == null) { next(); return; } res.header("Server", serverName); hasPadAccess(req, res, function() { importHandler.doImport(req, res, req.params.pad); }); }); var apiLogger = log4js.getLogger("API"); //This is a api call, collect all post informations and pass it to the apiHandler app.get('/api/1/:func', function(req, res) { res.header("Server", serverName); res.header("Content-Type", "application/json; charset=utf-8"); apiLogger.info("REQUEST, " + req.params.func + ", " + JSON.stringify(req.query)); //wrap the send function so we can log the response res._send = res.send; res.send = function(response) { response = JSON.stringify(response); apiLogger.info("RESPONSE, " + req.params.func + ", " + response); //is this a jsonp call, if yes, add the function call if(req.query.jsonp) response = req.query.jsonp + "(" + response + ")"; res._send(response); } //call the api handler apiHandler.handle(req.params.func, req.query, req, res); }); //The Etherpad client side sends information about how a disconnect happen app.post('/ep/pad/connection-diagnostic-info', function(req, res) { new formidable.IncomingForm().parse(req, function(err, fields, files) { console.log("DIAGNOSTIC-INFO: " + fields.diagnosticInfo); res.end("OK"); }); }); //The Etherpad client side sends information about client side javscript errors app.post('/jserror', function(req, res) { new formidable.IncomingForm().parse(req, function(err, fields, files) { console.error("CLIENT SIDE JAVASCRIPT ERROR: " + fields.errorInfo); res.end("OK"); }); }); //serve index.html under / app.get('/', function(req, res) { res.header("Server", serverName); var filePath = path.normalize(__dirname + "/../static/index.html"); res.sendfile(filePath, { maxAge: exports.maxAge }); }); //serve robots.txt app.get('/robots.txt', function(req, res) { res.header("Server", serverName); var filePath = path.normalize(__dirname + "/../static/robots.txt"); res.sendfile(filePath, { maxAge: exports.maxAge }); }); //serve favicon.ico app.get('/favicon.ico', function(req, res) { res.header("Server", serverName); var filePath = path.normalize(__dirname + "/../static/custom/favicon.ico"); res.sendfile(filePath, { maxAge: exports.maxAge }, function(err) { //there is no custom favicon, send the default favicon if(err) { filePath = path.normalize(__dirname + "/../static/favicon.ico"); res.sendfile(filePath, { maxAge: exports.maxAge }); } }); }); //let the server listen app.listen(settings.port, settings.ip); console.log("Server is listening at " + settings.ip + ":" + settings.port); var onShutdown = false; var gracefulShutdown = function(err) { if(err && err.stack) { console.error(err.stack); } else if(err) { console.error(err); } //ensure there is only one graceful shutdown running if(onShutdown) return; onShutdown = true; console.log("graceful shutdown..."); //stop the http server app.close(); //do the db shutdown db.db.doShutdown(function() { console.log("db sucessfully closed."); process.exit(0); }); setTimeout(function(){ process.exit(1); }, 3000); } //connect graceful shutdown with sigint and uncaughtexception if(os.type().indexOf("Windows") == -1) { //sigint is so far not working on windows //https://github.com/joyent/node/issues/1553 process.on('SIGINT', gracefulShutdown); } process.on('uncaughtException', gracefulShutdown); //init socket.io and redirect all requests to the MessageHandler var io = socketio.listen(app); //this is only a workaround to ensure it works with all browers behind a proxy //we should remove this when the new socket.io version is more stable io.set('transports', ['xhr-polling']); var socketIOLogger = log4js.getLogger("socket.io"); io.set('logger', { debug: function (str) { socketIOLogger.debug(str); }, info: function (str) { socketIOLogger.info(str); }, warn: function (str) { socketIOLogger.warn(str); }, error: function (str) { socketIOLogger.error(str); }, }); //minify socket.io javascript if(settings.minify) io.enable('browser client minification'); var padMessageHandler = require("./handler/PadMessageHandler"); var timesliderMessageHandler = require("./handler/TimesliderMessageHandler"); //Initalize the Socket.IO Router socketIORouter.setSocketIO(io); socketIORouter.addComponent("pad", padMessageHandler); socketIORouter.addComponent("timeslider", timesliderMessageHandler); callback(null); }
express.createServer(function (request, response) { //app.get('/', function(request, response) { console.log('GET request at: '+ request.url); var rootPath = './angular', defaultPath = './angular/default.html', filePath = request.url ==="/"? defaultPath : rootPath + request.url; fs.exists(filePath, function(exists) { console.log('exists '+ filePath); if (exists) { fs.readFile(filePath, function(error, content) { if (error) { console.log('500 '+ filePath); response.send(500); } else { console.log('mime '+ filePath); var contentType = mimeLookup.lookup(filePath); // response.set('Content-Type',contentType); // response.send(200,content); console.log('200 '+ filePath); response.writeHead(200, { 'Content-Type': contentType }); response.end(content, 'utf-8'); } }); } else { console.log('404 '+ filePath); response.status(404).send('Not found'); //response.send(404, filePath); } }); }).listen(port);
RedisStore = require('socket.io/lib/stores/redis'), redis = require('heroku-redis-client'); var ObjectID = mongodb.ObjectID; var port = process.env.PORT || 8080, sessionSecret = process.env.SESSION_SECRET || "fdasfkjlsadfkljsdah"; // Express var app = express.createServer( express.logger(), express.static(__dirname + '/public'), express.bodyParser(), express.cookieParser(), express.session({ secret: sessionSecret, store: new ConnectRedisStore({ client: redis.createClient() }) }) ); app.register('.haml', require('hamljs')); // Socket.io var io = require('socket.io').listen(app); io.set('store', new RedisStore({ redisPub: redis.createClient(), redisSub: redis.createClient(), redisClient: redis.createClient() }));
var facebook = require(__dirname + '/../lib/facebook-wrapper'); var express = require('express'); var fs = require('fs'); var config_file = __dirname + '/config.json'; var options = JSON.parse(fs.readFileSync(config_file)); var server = express.createServer( express.logger(), express.bodyParser(), express.cookieParser(), express.session({ secret: process.env.SESSION_SECRET || 'secret123' }), facebook.auth(options) ); server.post('/*', function (req, res) { res.writeHead(200, {'Content-Type': 'text/html'}); req.facebook.graph('/me?fields=id', function (id) { id = id.id; req.facebook.fql('select name, pic_small from user where uid=me()', function (data) { data = data[0]; res.end('Hello, ' + data.name + ' (' + id + '). Have a picture of yourself: <img src=\"' + data.pic_small + '\" />'); }); }); }); server.listen(8000); console.log('All is well');
//setup Dependencies var connect = require('connect') , express = require('express') , io = require('socket.io') , port = (process.env.PORT || 8081); //Setup Express var server = express.createServer(); server.configure(function(){ server.set('views', __dirname + '/views'); server.set('view options', { layout: false }); server.use(connect.bodyParser()); server.use(express.cookieParser()); server.use(express.session({ secret: "shhhhhhhhh!"})); server.use(connect.static(__dirname + '/static')); server.use(server.router); }); //setup the errors server.error(function(err, req, res, next){ if (err instanceof NotFound) { res.render('404.jade', { locals: { title : '404 - Not Found' ,description: '' ,author: '' ,analyticssiteid: 'XXXXXXX' },status: 404 }); } else { res.render('500.jade', { locals: { title : 'The Server Encountered an Error' ,description: ''
db.connect({}, function(err) { var useHTTPS = _(config).has('key'), useBounce = _(config).has('bounce') && config.bounce, app, io, bounce, dialbackClient, requestLogger = function(log) { return function(req, res, next) { var weblog = log.child({"req_id": uuid.v4(), component: "web"}); var end = res.end, startTime = Date.now(); req.log = weblog; res.end = function(chunk, encoding) { var rec, endTime; res.end = end; res.end(chunk, encoding); endTime = Date.now(); rec = {req: req, res: res, serverTime: endTime - startTime}; if (_(req).has("principal")) { rec.principal = req.principal; } if (_(req).has("client")) { rec.client = req.client; } weblog.info(rec); }; next(); }; }; if (err) { log.error(err); callback(err, null); return; } if (useHTTPS) { log.info("Setting up HTTPS server."); app = express.createServer({key: fs.readFileSync(config.key), cert: fs.readFileSync(config.cert)}); if (useBounce) { log.info("Setting up micro-HTTP server to bounce to HTTPS."); bounce = express.createServer(function(req, res, next) { var host = req.header('Host'); res.redirect('https://'+host+req.url, 301); }); } } else { log.info("Setting up HTTP server."); app = express.createServer(); } app.config = config; if (config.smtpserver) { // harmless flag config.haveEmail = true; Mailer.setup(config, log); } var cleanup = config.cleanup || 600000; var dbstore = new DatabankStore(db, log, cleanup); if (!_(config).has("noweb") || !config.noweb) { app.session = express.session({secret: (_(config).has('sessionSecret')) ? config.sessionSecret : "insecure", store: dbstore}); } // Configuration app.configure(function() { var serverVersion = 'pump.io/'+version + ' express/'+express.version + ' node.js/'+process.version, versionStamp = function(req, res, next) { res.setHeader('Server', serverVersion); next(); }, canonicalHost = function(req, res, next) { var host = req.header('Host'), urlHost, addressHost; if (!config.redirectToCanonical || !host) { next(); return; } urlHost = URLMaker.makeHost(); if (host == urlHost) { next(); return; } if (!config.redirectAddressToCanonical) { addressHost = URLMaker.makeHost(address, port); if (host == addressHost) { next(); return; } } res.redirect(URLMaker.makeURL(req.url), 301); }; // Templates are in public app.set("views", __dirname + "/../public/template"); app.set("view engine", "utml"); app.use(requestLogger(log)); if (config.redirectToCanonical) { app.use(canonicalHost); } app.use(rawBody); app.use(express.bodyParser()); app.use(express.cookieParser()); app.use(express.query()); app.use(express.methodOverride()); app.use(express.favicon()); if (config.compress) { app.use(express.compress()); } app.use(versionStamp); app.provider = new Provider(log, config.clients); // Initialize scripts _.each(config.plugins, function(pluginName) { var script; if (_.isFunction(plugins[pluginName].getScript)) { script = plugins[pluginName].getScript(); log.info({plugin: pluginName, script: script}, "Adding script"); config.scripts.push(script); } }); app.use(function(req, res, next) { res.local("config", config); res.local("data", {}); res.local("page", {url: req.originalUrl}); res.local("template", {}); // Initialize null res.local("principalUser", null); res.local("principal", null); res.local("user", null); res.local("client", null); res.local("nologin", false); res.local("version", version); res.local("messages", {items: []}); res.local("notifications", {items: []}); next(); }); app.use(auth([auth.Oauth({name: "client", realm: "OAuth", oauth_provider: app.provider, oauth_protocol: (useHTTPS) ? 'https' : 'http', authenticate_provider: null, authorize_provider: null, authorization_finished_provider: null }), auth.Oauth({name: "user", realm: "OAuth", oauth_provider: app.provider, oauth_protocol: (useHTTPS) ? 'https' : 'http', authenticate_provider: oauth.authenticate, authorize_provider: oauth.authorize, authorization_finished_provider: oauth.authorizationFinished }) ])); app.use(express["static"](__dirname + "/../public")); app.use(app.router); }); app.error(function(err, req, res, next) { log.error(err); if (err instanceof HTTPError) { if (req.xhr || req.originalUrl.substr(0, 5) === '/api/') { res.json({error: err.message}, err.code); } else if (req.accepts("html")) { res.status(err.code); res.render("error", {page: {title: "Error"}, error: err}); } else { res.writeHead(err.code, {"Content-Type": "text/plain"}); res.end(err.message); } } else { next(err); } }); // Routes api.addRoutes(app); webfinger.addRoutes(app); clientreg.addRoutes(app); shared.addRoutes(app); if (_.has(config, "uploaddir")) { // Simple boolean flag config.canUpload = true; uploads.addRoutes(app); Image.uploadDir = config.uploaddir; } if (config.requireEmail) { confirm.addRoutes(app); } // Use "noweb" to disable Web site (API engine only) if (!_(config).has("noweb") || !config.noweb) { web.addRoutes(app); } else { // A route to show the API doc at root app.get("/", function(req, res, next) { var Showdown = require("showdown"), converter = new Showdown.converter(); Step( function() { fs.readFile(path.join(__dirname, "..", "API.md"), this); }, function (err, data) { var html, markdown; if (err) { next(err); } else { markdown = data.toString(); html = converter.makeHtml(markdown); res.render("doc", {page: {title: "API"}, html: html}); } } ); }); } DatabankObject.bank = db; URLMaker.hostname = hostname; URLMaker.port = (config.urlPort) ? config.urlPort : port; URLMaker.path = config.urlPath; Distributor.log = log.child({component: "distributor"}); Distributor.plugins = _.filter(plugins, function(plugin) { return _.isFunction(plugin.distributeActivity) || _.isFunction(plugin.distributeToPerson); }); if (_(config).has('serverUser')) { app.on('listening', function() { process.setuid(config.serverUser); }); } if (config.sockjs) { pumpsocket.connect(app, log); } if (config.firehose) { log.info({firehose: config.firehose}, "Setting up firehose"); Firehose.setup(config.firehose, log); } if (config.spamhost) { if (!config.spamclientid || !config.spamclientsecret) { throw new Error("Need client ID and secret for spam host"); } log.info({spamhost: config.spamhost}, "Configuring spam host"); ActivitySpam.init({ host: config.spamhost, clientID: config.spamclientid, clientSecret: config.spamclientsecret, logger: log }); } dialbackClient = new DialbackClient({ hostname: hostname, bank: db, app: app, url: "/api/dialback" }); Credentials.dialbackClient = dialbackClient; // Each worker takes a turn cleaning up, so *this* worker does // its cleanup once every config.workers cleanup periods var workers = config.workers || 1; var cleanupTime = 1200 * workers * 1000; // We set a timer so we start with an offset, instead of having // all workers start at almost the same time setTimeout(function() { log.info("Cleaning up old OAuth nonces"); Nonce.cleanup(); setInterval(function() { log.info("Cleaning up old OAuth nonces"); Nonce.cleanup(); }, cleanupTime); }, Math.floor(Math.random() * cleanupTime)); app.run = function(callback) { var self = this, removeListeners = function() { self.removeListener("listening", listenSuccessHandler); self.removeListener("err", listenErrorHandler); }, listenErrorHandler = function(err) { removeListeners(); log.error(err); callback(err); }, listenSuccessHandler = function() { var removeBounceListeners = function() { bounce.removeListener("listening", bounceSuccess); bounce.removeListener("err", bounceError); }, bounceError = function(err) { removeBounceListeners(); log.error(err); callback(err); }, bounceSuccess = function() { log.info("Finished setting up bounce server."); removeBounceListeners(); callback(null); }; log.info("Finished setting up main server."); removeListeners(); if (useBounce) { bounce.on("error", bounceError); bounce.on("listening", bounceSuccess); bounce.listen(80, address); } else { callback(null); } }; this.on("error", listenErrorHandler); this.on("listening", listenSuccessHandler); log.info("Listening on "+port+" for host " + address); this.listen(port, address); }; // So they can add their own routes or other stuff to the app _.each(plugins, function(plugin, name) { if (_.isFunction(plugin.initializeApp)) { log.info({plugin: name}, "Initializing app."); plugin.initializeApp(app); } }); callback(null, app); });
function serveExpress (port, path, cb) { // Create an `EventEmitter` for test-related events. var tests = new events.EventEmitter; var app = express.createServer(); app.set("views", __dirname + "/views"); app.set("view engine", "jade"); // Use our version of Jade. app.register(".jade", require("jade")); app.get("/", function (req, res) { tests.emit("visitor", req.ua); var json = jsonize(req, ["transport", "timeout"]); res.header("Expires", "0"); res.header("Pragma", "no-cache"); res.header("Cache-Control", "no-cache"); res.render("index", { locals : { bootstrap : "YETI.start(" + json + ")", yeti_version : pkg.readPackageSync().version } }); }); var testIds = {}; var testResults = {}; var testQueue = {}; // Add a new test. Called by the CLI in `app.js`. app.put("/tests/add", function (req, res) { if (!req.body.tests.length) return res.send(500); var urls = []; var id = makeId(); req.body.tests.forEach(function (url) { urls.push("/project/" + id + url); }); ui.debug("/tests/add: registered batch", id); if (tests.listeners("add").length) { tests.emit("add", id, urls); } else { testQueue[id] = urls; } res.send(id); }); // Comet middleware. // Sends a response when a test comes in. function wait (req, responseCallback) { function ADDCB (id, urls) { ui.debug("/tests/wait: send", urls); responseCallback({ tests : urls }); testIds[id] = 1; } function SHUTDOWNCB (cb) { ui.debug("/tests/wait: shutdown!", port); req.on("end", cb); // Prevent browsers from reconnecting. responseCallback({shutdown:true}); req.emit("end"); } tests.on("add", ADDCB); tests.on("shutdown", SHUTDOWNCB); // create a run-once function var CLEANUPCB = (function () { var once = false; return function () { if (!once) return; once = true; // No longer able to write data here. tests.removeListener("add", ADDCB); tests.removeListener("shutdown", SHUTDOWNCB); } })(); // Thanks to IE, we must listen to both. // IE sends a RST, other browsers FIN ACK. // Just respond to whatever happens sooner. req.connection.on("end", CLEANUPCB); req.connection.on("close", CLEANUPCB); // TODO: Delete stale tests from testQueue? if (testQueue) { for ( var id in testQueue ) tests.emit("add", id, testQueue[id]); testQueue = {}; } } // EventSource-powered Comet, called by the browser. app.get("/tests/wait", function (req, res) { res.writeHead(200, { "Content-Type" : "text/event-stream" }); wait(req, function (data) { res.write("data: " + JSON.stringify(data) + "\n\n"); }); }); // XMLHttpRequest-powered Comet, called by the browser. app.post("/tests/wait", function (req, res) { wait(req, function (data) { res.send(data); }); }); // Respond when test results for the given batch ID arrive. // Called by the CLI in `app.js`. app.get("/status/:id", function (req, res) { var id = req.params.id; if (id in testIds) { if (id in testResults) { var results = testResults[id].shift(); if (results) { return res.send(results); } else { // nothing in the queue delete testResults[id]; // fallthrough to the test listener } } tests.on(id, function (results) { res.send(results); }); } else { res.send("Nothing is listening to this batch. At least one browser should be pointed at the Yeti server.", 404); } }); // Recieves test results from the browser. app.post("/results", function (req, res) { var result = JSON.parse(req.body.results); result.ua = req.body.useragent; var id = req.body.id; ui.debug("/results:", id, " has results from: " + result.ua); if (id in testIds) { if (tests.listeners(id).length) { tests.emit(id, result); } else { if ( ! (id in testResults) ) { testResults[id] = []; } testResults[id].push(result); } } else { ui.results(result); } // Advance to the next test immediately. // We do this here because determining if an iframe has loaded // is much harder on the client side. Takes advantage of the // fact that we're on the same domain as the parent page. res.send("<script>parent.parent.YETI.next()</script>"); }); // #### File Server var projectSend = function (res, file, appendString, nocache, prependString) { sendfiles.call( res, [file], appendString, null, // callback { prependString : prependString, cache : !nocache } ); }; app.get('/project/*', function (req, res) { var nocache = false; var splat = req.params.pop().split("/"); if (splat[0] in testIds) { splat.shift(); nocache = true; // using a unique url } if (splat[0] === "") splat.shift(); // stupid leading slashes splat = splat.join("/"); var file = "/" + decodeURIComponent(splat); // The requested file must begin with our cwd. if (file.indexOf(path) !== 0) { // The file is outside of our cwd. // Reject the request. ui.log(ui.color.red("[!]") + " Rejected " + file + ", run in the directory to serve" + " or specify --path."); return res.send(403); } if (/^.*\.html?$/.test(req.url)) { // Inject a test reporter into the test page. projectSend( res, file, "<script src=\"/dyn/" + cachebuster + "/inject.js\"></script><script>" + "$yetify({url:\"/results\"});</script>", nocache ); } else { // Everything else goes untouched. projectSend(res, file, "", nocache); } }); var incSend = function (res, name, nocache) { sendfiles.call( res, [__dirname + "/../inc/" + name], "", // appendString null, // callback { cache : !nocache } ); }; app.get("/inc/*", function (req, res) { incSend(res, req.params); }); app.get("/dyn/:cachebuster/*", function (req, res) { incSend(res, req.params, true); }); app.get("/favicon.ico", function (req, res) { incSend(res, "favicon.ico", true); }); // Start the server. // Workaround Express and/or Connect bugs // that strip out the `host` and `callback` args. // n.b.: Express's `run()` sets up view reloading // and sets the `env` to `process.env.ENV`, etc. // We are bypassing all of that by using http directly. http.Server.prototype.listen.call(app, port, null, cb); // Publish the `tests` emitter. emitterRegistry[port] = tests; return app; }
var dbName = process.env[ 'GRUMBLE_DB' ] != null ? process.env[ 'GRUMBLE_DB' ] : 'grumble'; var mongoose = require( 'mongoose' ); mongoose.connect( dbHost, dbName, dbPort ); var mongo = require( 'mongodb' ); var sessionDb = new mongo.Db( dbName, new mongo.Server( dbHost, dbPort, { auto_reconnect: true } ), {} ); var mongoStore = require( 'connect-mongodb' ); var sessionSecret = process.env[ 'GRUMBLE_SECRET' ] != null ? sha1( process.env[ 'GRUMBLE_SECRET' ] ) : sha1( __dirname + __filename + process.env[ 'USER' ] ); var app = express.createServer( express.static( __dirname + '/static' ), express.bodyParser(), express.cookieParser(), express.session({ cookie: { maxAge: 60000 * 60 * 24 * 30 }, // 30 days secret: sessionSecret, store: new mongoStore( { db: sessionDb } ) }) ); var apiModules = [ require( './api/Sessions.js' ), require( './api/Users.js' ), require( './api/Rooms.js' ), require( './api/Messages.js' ) ]; for ( var moduleIndex = 0; moduleIndex < apiModules.length; ++moduleIndex ) { apiModules[ moduleIndex ].bind( app );
function TerminusServer(settings) { var self = {}; var app = express.createServer(); var io = sio.listen(app); var factories = {} io.set('log level', 1); app.set("view options", {layout: false}); app.register(".tpl", mustache_templater); self.register_configuration = function (type, cfg) { cfg.type = type; var factory = TTYFactory(cfg, { data: function (data) { if (this.socket) { this.socket.emit('data', data.toString()); } else { this.backlog += data; } }, exit: function () { if (this.socket) { this.socket.emit('exit'); } this.parent.terminate(this.id); } }); factories[type] = factory; app.get('/' + type, function (req, res) { var id = factory.create(); res.redirect('/' + type + '/' + id); }); app.get('/' + type + '/:id', function (req, res) { var id = req.params.id; console.log('Requesting: ' + type + "/" + id); if (!factory[id]) { factory.make(id); } else { factory.notimeout(id); } var client_settings = cfg.settings; if (typeof(client_settings) != "string") { throw "a list of settings is unsupported" } else { client_settings = '/resources/settings/' + client_settings; } res.render(path.join(settings.path, 'page', cfg.template), {termtype: type, id: id, magic: 12345678, style: cfg.style, settings: client_settings, server: settings.host, port: settings.port}) }); } process.env.HOSTNAME = os.hostname() self.register_filesystem = function (name, mountpoint) { name = expand_env(name); app.get('/f/' + name + "/*", function (req, res) { var file = req.params[0]; res.sendfile(file, {root: mountpoint}); // var fullpath = path.join(mountpoint, file); // res.sendfile(fullpath, {root: ""}); // res.sendfile(fullpath); }); console.log('mounted ' + mountpoint + ' on /' + name); } if (settings.fileserve) { for (var name in settings.fileserve) { self.register_filesystem(name, settings.fileserve[name]); } } app.get('/resources/*', function (req, res) { var file = req.params[0] res.sendfile(file, {root: settings.path}); // res.sendfile(path.join(settings.path, file)); }); for (var type in settings.configurations) { self.register_configuration(type, settings.configurations[type]); } io.sockets.on('connection', function (socket) { var command = null; var id = null; socket.on('connect_to', function (data) { console.log('connect to: ' + data.command + '/' + data.id); command = data.command; id = data.id; factories[command].set_socket(id, socket); }); socket.on('setsize', function (data) { if (command != null) { console.log('from ' + command + "#" + id + ' -> setsize: ' + data.h + "x" + data.w); factories[command][id].set_window_size(data.h, data.w); } }); socket.on('data', function (data) { if (command != null) { factories[command][id].send(data); } }); socket.on('disconnect', function () { if (command != null) { factories[command].schedule_terminate(id); } }); }); app.listen(settings.port, settings.host); console.log('Terminus serving on http://' + settings.host + ":" + settings.port) return self; }
// Post a SYSTEM message saying the chat restarted chatLog.push({ userid: -1000, name: 'SYSTEM', color: '#dc50ff', time: (new Date().getTime()), text: 'The chat system was restarted successfully.', gameid: -1000 }); var sslKey = fs.readFileSync('[].key'); var sslCert = fs.readFileSync('[].crt'); var sslCa = fs.readFileSync('[].crt'); var http_app = express.createServer( ); http_app.listen( 80, config.localbackendip ); var http_io = socketio.listen( http_app ); register( http_app, http_io ); var https_app = express.createServer({ key: sslKey, cert: sslCert, ca: sslCa }); https_app.listen( 443, config.localbackendip ); var https_io = socketio.listen( https_app ); register( https_app, https_io );
* The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ var fs = require('fs'), privateKey = fs.readFileSync('pem/key.pem').toString(), certificate = fs.readFileSync('pem/certificate.pem').toString(), express = require('express'), app = process.env.PRODUCTION ? express.createServer() : express.createServer({key: privateKey, cert: certificate}), path = require('path'), WS = require('ws').Server, mongoose = require('mongoose'), chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'; var DataStore = (function(){ var init, store, connection, TestSuiteModel; init = function(mongoose, isProduction, connectionString) { console.log('Connecting to Mongo [isProduction: ' + isProduction + ']'); if (isProduction) { connection = mongoose.connect(connectionString); } else { connection = mongoose.connect('mongodb://localhost/wsperf');
var _http = require('http'); var _url = require('url'); var _qs = require('querystring'); var _fs = require('fs'); var _express = require('express'); var app = _express.createServer(); app.get('/', function (req, res) { res.send('discovery root'); }); function requestPrivateAddressDelay (delay, next) { requestPrivateAddress(function(error, address) { if (error) { setTimeout(function () { requestPrivateAddress(next); }, delay); return; } return next(null, address); }); } function requestPrivateAddress (next) { var address = null; var _os = require('os'); var ifces = _os.networkInterfaces(); var ifce_key = app.set('discovery interface');
( function () { var http = require( 'http' ), express = require( 'express' ), sqlite = require( 'sqlite3' ), dbStack = [], dbFlag = false, argv = require( 'optimist' ).argv, db = new sqlite.Database( argv._[0] || '/mnt/rtserver/pages.db' ), // The maximum number of tries per article maxTries = 6, // The maximum number of fetch retries per article maxFetchRetries = 6, // "Random" estimate of how many pending pages we have in the db pendingPagesEstimate = 500; // ----------------- Prepared queries -------------- var dbGetTitle = db.prepare( 'SELECT pages.id, pages.title ' + 'FROM pages ' + 'LEFT JOIN claims ON pages.id = claims.page_id AND claims.commit_hash = ? ' + 'LEFT JOIN stats ON stats.id = pages.latest_result ' + 'WHERE num_fetch_errors < ? AND ' + '( claims.id IS NULL OR ' + '( claims.has_errorless_result = 0 AND claims.num_tries <= ? AND claims.timestamp < ? ) ) ' + 'ORDER BY stats.score DESC, ' + 'claims.timestamp ASC LIMIT 1 OFFSET ? ' ); var dbGetTitleRandom = db.prepare( 'SELECT pages.id, pages.title ' + 'FROM pages ' + 'LEFT JOIN claims ON pages.id = claims.page_id AND claims.commit_hash = ? ' + 'LEFT JOIN stats ON stats.id = pages.latest_result ' + 'WHERE num_fetch_errors < ? AND ' + '( claims.id IS NULL OR ' + '( claims.has_errorless_result = 0 AND claims.num_tries <= ? AND claims.timestamp < ? ) ) ' + 'ORDER BY stats.score DESC, ' + 'claims.timestamp ASC, RANDOM() LIMIT 1' ); var dbIncrementFetchErrorCount = db.prepare( 'UPDATE pages SET num_fetch_errors = num_fetch_errors + 1 WHERE title = ?'); var dbClearFetchErrorCount = db.prepare( 'UPDATE pages SET num_fetch_errors = 0 WHERE title = ?'); var dbInsertCommit = db.prepare( 'INSERT OR IGNORE INTO commits ( hash, timestamp ) ' + 'VALUES ( ?, ? )' ); var dbFindClaimByPageId = db.prepare( 'SELECT claims.id, claims.num_tries FROM claims ' + 'WHERE claims.page_id = ? AND claims.commit_hash = ?'); var dbFindClaimByTitle = db.prepare( 'SELECT claims.id, claims.num_tries, claims.page_id FROM claims ' + 'JOIN pages ON pages.id = claims.page_id AND pages.title = ? ' + 'WHERE claims.commit_hash = ? AND claims.has_errorless_result = 0'); var dbInsertClaim = db.prepare( 'INSERT INTO claims ( page_id, commit_hash, timestamp ) ' + 'VALUES ( ?, ?, ? )'); var dbUpdateClaim = db.prepare( 'UPDATE claims SET timestamp = ?, num_tries = num_tries + 1 WHERE id = ?'); var dbUpdateClaimResult = db.prepare( 'UPDATE claims SET has_errorless_result = 1 WHERE id = ?'); var dbFindStatRow = db.prepare( 'SELECT id FROM stats WHERE page_id = ? AND commit_hash = ?'); var dbInsertResult = db.prepare( 'INSERT INTO results ( claim_id, result ) ' + 'VALUES ( ?, ? )'); var dbUpdateResult = db.prepare( 'UPDATE results SET result = ? WHERE claim_id = ?'); var dbInsertClaimStats = db.prepare( 'INSERT INTO stats ' + '( skips, fails, errors, score, page_id, commit_hash ) ' + 'VALUES ( ?, ?, ?, ?, ?, ? ) ' ); var dbUpdateClaimStats = db.prepare( 'UPDATE stats ' + 'SET skips = ?, fails = ?, errors = ?, score = ? ' + 'WHERE page_id = ? AND commit_hash = ?' ); var dbUpdateLatestResult = db.prepare( 'UPDATE pages ' + 'SET latest_result = ( SELECT id from stats ' + 'WHERE stats.commit_hash = ? AND page_id = pages.id ) ' + 'WHERE id = ?' ); var dbLatestCommitHash = db.prepare( 'SELECT hash FROM commits ORDER BY timestamp DESC LIMIT 1'); var dbSecondLastCommitHash = db.prepare( 'SELECT hash FROM commits ORDER BY timestamp DESC LIMIT 1 OFFSET 1'); // IMPORTANT: node-sqlite3 library has a bug where it seems to cache // invalid results when a prepared statement has no variables. // Without this dummy variable as a workaround for the caching bug, // stats query always fails after the first invocation. So, if you // do upgrade the library, please test before removing this workaround. var dbStatsQuery = db.prepare( 'SELECT ? AS cache_bug_workaround, ' + '(select hash from commits order by timestamp desc limit 1) as maxhash, ' + '(select count(*) from stats where stats.commit_hash = ' + '(select hash from commits order by timestamp desc limit 1)) as maxresults, ' + '(select avg(stats.errors) from stats join pages on ' + 'pages.latest_result = stats.id) as avgerrors, ' + '(select avg(stats.fails) from stats join pages on ' + 'pages.latest_result = stats.id) as avgfails, ' + '(select avg(stats.skips) from stats join pages on ' + 'pages.latest_result = stats.id) as avgskips, ' + '(select avg(stats.score) from stats join pages on ' + 'pages.latest_result = stats.id) as avgscore, ' + 'count(*) AS total, ' + 'count(CASE WHEN stats.errors=0 THEN 1 ELSE NULL END) AS no_errors, ' + 'count(CASE WHEN stats.errors=0 AND stats.fails=0 '+ 'then 1 else null end) AS no_fails, ' + 'count(CASE WHEN stats.errors=0 AND stats.fails=0 AND stats.skips=0 '+ 'then 1 else null end) AS no_skips, ' + // get regression count between last two commits '(SELECT count(*) ' + 'FROM pages p ' + 'JOIN stats AS s1 ON s1.page_id = p.id ' + 'JOIN stats AS s2 ON s2.page_id = p.id ' + 'WHERE s1.commit_hash = (SELECT hash ' + 'FROM commits ORDER BY timestamp DESC LIMIT 1 ) ' + 'AND s2.commit_hash = (SELECT hash ' + 'FROM commits ORDER BY timestamp DESC LIMIT 1 OFFSET 1) ' + 'AND s1.score > s2.score ) as numregressions, ' + // get fix count between last two commits '(SELECT count(*) ' + 'FROM pages ' + 'JOIN stats AS s1 ON s1.page_id = pages.id ' + 'JOIN stats AS s2 ON s2.page_id = pages.id ' + 'WHERE s1.commit_hash = (SELECT hash FROM commits ORDER BY timestamp DESC LIMIT 1 ) ' + 'AND s2.commit_hash = (SELECT hash FROM commits ORDER BY timestamp DESC LIMIT 1 OFFSET 1 ) ' + 'AND s1.score < s2.score ) as numfixes ' + 'FROM pages JOIN stats on pages.latest_result = stats.id'); var dbFailsQuery = db.prepare( 'SELECT pages.title, commits.hash, stats.errors, stats.fails, stats.skips ' + 'FROM stats ' + 'JOIN (' + ' SELECT MAX(id) AS most_recent FROM stats GROUP BY page_id' + ') AS s1 ON s1.most_recent = stats.id ' + 'JOIN pages ON stats.page_id = pages.id ' + 'JOIN commits ON stats.commit_hash = commits.hash ' + 'ORDER BY stats.score DESC ' + 'LIMIT 40 OFFSET ?' ); var dbGetOneResult = db.prepare( 'SELECT result FROM results ' + 'JOIN claims ON results.claim_id = claims.id ' + 'JOIN commits ON claims.commit_hash = commits.hash ' + 'JOIN pages ON pages.id = claims.page_id ' + 'WHERE pages.title = ? ' + 'ORDER BY commits.timestamp DESC LIMIT 1' ); var dbGetResultWithCommit = db.prepare( 'SELECT result FROM results ' + 'JOIN claims ON results.claim_id = claims.id ' + 'AND claims.commit_hash = ? ' + 'JOIN pages ON pages.id = claims.page_id ' + 'WHERE pages.title = ?' ); var dbFailedFetches = db.prepare( 'SELECT title FROM pages WHERE num_fetch_errors >= ?'); var dbRegressedPages = db.prepare( 'SELECT pages.title, ' + 's1.commit_hash AS new_commit, s1.errors AS new_errors, s1.fails AS new_fails, s1.skips AS new_skips, ' + 's2.commit_hash AS old_commit, s2.errors AS old_errors, s2.fails AS old_fails, s2.skips AS old_skips ' + 'FROM pages ' + 'JOIN stats AS s1 ON s1.id = pages.latest_result ' + 'JOIN stats AS s2 ON s2.page_id = pages.id ' + 'WHERE s2.id != s1.id AND s1.score > s2.score ' + 'GROUP BY pages.id ' + // picks a "random" past hash from which we regressed 'ORDER BY s1.score - s2.score DESC ' + 'LIMIT 40 OFFSET ?'); var dbFixedPages = db.prepare( 'SELECT pages.title, ' + 's1.commit_hash AS new_commit, s1.errors AS new_errors, s1.fails AS new_fails, s1.skips AS new_skips, ' + 's2.commit_hash AS old_commit, s2.errors AS old_errors, s2.fails AS old_fails, s2.skips AS old_skips ' + 'FROM pages ' + 'JOIN stats AS s1 ON s1.id = pages.latest_result ' + 'JOIN stats AS s2 ON s2.page_id = pages.id ' + 'WHERE s2.id != s1.id AND s1.score < s2.score ' + 'GROUP BY pages.id ' + // picks a "random" past hash from which we regressed 'ORDER BY s1.score - s2.score ASC ' + 'LIMIT 40 OFFSET ?'); var dbFailsDistribution = db.prepare( 'SELECT ? AS caching_bug_workaround, fails, count(*) AS num_pages ' + 'FROM stats ' + 'JOIN pages ON pages.latest_result = stats.id ' + 'GROUP by fails'); var dbSkipsDistribution = db.prepare( 'SELECT ? AS caching_bug_workaround, skips, count(*) AS num_pages ' + 'FROM stats ' + 'JOIN pages ON pages.latest_result = stats.id ' + 'GROUP by skips'); var dbCommits = db.prepare( 'SELECT ? AS caching_bug_workaround, hash, timestamp, ' + //// get the number of fixes column // '(SELECT count(*) ' + // 'FROM pages ' + // 'JOIN stats AS s1 ON s1.page_id = pages.id ' + // 'JOIN stats AS s2 ON s2.page_id = pages.id ' + // 'WHERE s1.commit_hash = (SELECT hash FROM commits c2 where c2.timestamp < c1.timestamp ORDER BY timestamp DESC LIMIT 1 ) ' + // 'AND s2.commit_hash = c1.hash AND s1.score < s2.score) as numfixes, ' + //// get the number of regressions column // '(SELECT count(*) ' + // 'FROM pages ' + // 'JOIN stats AS s1 ON s1.page_id = pages.id ' + // 'JOIN stats AS s2 ON s2.page_id = pages.id ' + // 'WHERE s1.commit_hash = (SELECT hash FROM commits c2 where c2.timestamp < c1.timestamp ORDER BY timestamp DESC LIMIT 1 ) ' + // 'AND s2.commit_hash = c1.hash AND s1.score > s2.score) as numregressions, ' + //// get the number of tests for this commit column '(select count(*) from stats where stats.commit_hash = c1.hash) as numtests ' + 'FROM commits c1 ' + 'ORDER BY timestamp DESC'); var dbFixesBetweenRevs = db.prepare( 'SELECT pages.title, ' + 's1.commit_hash AS new_commit, s1.errors AS new_errors, s1.fails AS new_fails, s1.skips AS new_skips, ' + 's2.commit_hash AS old_commit, s2.errors AS old_errors, s2.fails AS old_fails, s2.skips AS old_skips ' + 'FROM pages ' + 'JOIN stats AS s1 ON s1.page_id = pages.id ' + 'JOIN stats AS s2 ON s2.page_id = pages.id ' + 'WHERE s1.commit_hash = ? AND s2.commit_hash = ? AND s1.score < s2.score ' + 'ORDER BY s1.score - s2.score ASC ' + 'LIMIT 40 OFFSET ?'); var dbNumFixesBetweenRevs = db.prepare( 'SELECT count(*) as numFixes ' + 'FROM pages ' + 'JOIN stats AS s1 ON s1.page_id = pages.id ' + 'JOIN stats AS s2 ON s2.page_id = pages.id ' + 'WHERE s1.commit_hash = ? AND s2.commit_hash = ? AND s1.score < s2.score '); var dbRegressionsBetweenRevs = db.prepare( 'SELECT pages.title, ' + 's1.commit_hash AS new_commit, s1.errors AS new_errors, s1.fails AS new_fails, s1.skips AS new_skips, ' + 's2.commit_hash AS old_commit, s2.errors AS old_errors, s2.fails AS old_fails, s2.skips AS old_skips ' + 'FROM pages ' + 'JOIN stats AS s1 ON s1.page_id = pages.id ' + 'JOIN stats AS s2 ON s2.page_id = pages.id ' + 'WHERE s1.commit_hash = ? AND s2.commit_hash = ? AND s1.score > s2.score ' + 'ORDER BY s1.score - s2.score DESC ' + 'LIMIT 40 OFFSET ?'); var dbNumRegressionsBetweenRevs = db.prepare( 'SELECT count(*) as numRegressions ' + 'FROM pages ' + 'JOIN stats AS s1 ON s1.page_id = pages.id ' + 'JOIN stats AS s2 ON s2.page_id = pages.id ' + 'WHERE s1.commit_hash = ? AND s2.commit_hash = ? AND s1.score > s2.score '); var dbNumRegressionsBetweenLastTwoRevs = db.prepare( 'SELECT count(*) as numRegressions ' + 'FROM pages ' + 'JOIN stats AS s1 ON s1.page_id = pages.id ' + 'JOIN stats AS s2 ON s2.page_id = pages.id ' + 'WHERE s1.commit_hash = (SELECT hash ' + 'FROM commits ORDER BY timestamp DESC LIMIT 1 ) ' + 'AND s2.commit_hash = (SELECT hash ' + 'FROM commits ORDER BY timestamp DESC LIMIT 1 OFFSET 1) ' + 'AND s1.score > s2.score '); function dbUpdateErrCB(title, hash, type, msg, err) { if (err) { console.error("Error inserting/updating " + type + " for page: " + title + " and hash: " + hash); if (msg) { console.error(msg); } console.error("ERR: " + err); } } function titleCallback( req, res, retry, commitHash, cutOffTimestamp, err, row ) { if ( err && !retry ) { res.send( 'Error! ' + err.toString(), 500 ); } else if ( err === null && row ) { db.serialize( function () { // SSS FIXME: what about error checks? dbInsertCommit.run( [ commitHash, decodeURIComponent( req.query.ctime ) ] ); dbFindClaimByPageId.get( [ row.id, commitHash ], function ( err, claim ) { if (claim) { // Ignoring possible duplicate processing // Increment the # of tries, update timestamp dbUpdateClaim.run([Date.now(), claim.id], dbUpdateErrCB.bind(null, row.title, commitHash, "claim", null)); if (claim.num_tries >= maxTries) { // Too many failures. Insert an error stats entry and retry fetch console.log( ' CRASHER? ' + row.title); var stats = [0, 0, 1, statsScore(0,0,1), claim.page_id, commitHash]; dbInsertClaimStats.run( stats, function ( err ) { if (err) { // Try updating the stats instead of inserting if we got an error // Likely a sql constraint error dbUpdateClaimStats.run(stats, function (err) { dbUpdateErrCB( row.title, commitHash, 'stats', null, err ); }); } } ); fetchPage(commitHash, cutOffTimestamp, req, res); } else { console.log( ' -> ' + row.title); res.send( row.title ); } } else { // Claim doesn't exist dbInsertClaim.run( [ row.id, commitHash, Date.now() ], function(err) { if (!err) { console.log( ' -> ' + row.title); res.send( row.title ); } else { console.error(err); console.error("Multiple clients trying to access the same title: " + row.title); // In the rare scenario that some other client snatched the // title before us, get a new title (use the randomized ordering query) dbGetTitleRandom.get( [ commitHash, maxFetchRetries, maxTries, cutOffTimestamp ], titleCallback.bind( null, req, res, false, commitHash, cutOffTimestamp ) ); } }); } }); }); } else if ( retry ) { // Try again with the slow DB search method dbGetTitleRandom.get( [ commitHash, maxFetchRetries, maxTries, cutOffTimestamp ], titleCallback.bind( null, req, res, false, commitHash, cutOffTimestamp ) ); } else { res.send( 'no available titles that fit those constraints', 404 ); } } function fetchPage( commitHash, cutOffTimestamp, req, res ) { // This query picks a random page among the first 'pendingPagesEstimate' pages var rowOffset = Math.floor(Math.random() * pendingPagesEstimate); dbGetTitle.get([ commitHash, maxFetchRetries, maxTries, cutOffTimestamp, rowOffset ], titleCallback.bind( null, req, res, true, commitHash, cutOffTimestamp ) ); } var getTitle = function ( req, res ) { res.setHeader( 'Content-Type', 'text/plain; charset=UTF-8' ); // Select pages that were not claimed in the 10 minutes. // If we didn't get a result from a client 10 minutes after // it got a rt claim on a page, something is wrong with the client // or with parsing the page. // // Hopefully, no page takes longer than 10 minutes to parse. :) fetchPage(req.query.commit, Date.now() - 600, req, res); }, statsScore = function(skipCount, failCount, errorCount) { // treat <errors,fails,skips> as digits in a base 1000 system // and use the number as a score which can help sort in topfails. return errorCount*1000000+failCount*1000+skipCount; } receiveResults = function ( req, res ) { var title = decodeURIComponent( req.params[0] ), result = req.body.results, skipCount = result.match( /\<skipped/g ), failCount = result.match( /\<failure/g ), errorCount = result.match( /\<error/g ); skipCount = skipCount ? skipCount.length : 0; failCount = failCount ? failCount.length : 0; errorCount = errorCount ? errorCount.length : 0; res.setHeader( 'Content-Type', 'text/plain; charset=UTF-8' ); var commitHash = req.body.commit; //console.warn("got: " + JSON.stringify([title, commitHash, result, skipCount, failCount, errorCount])); if ( errorCount > 0 && result.match( 'DoesNotExist' ) ) { console.log( 'XX', title ); dbIncrementFetchErrorCount.run([title], dbUpdateErrCB.bind(null, title, commitHash, "page fetch error count", "null")); // NOTE: the last db update may not have completed yet // For now, always sending HTTP 200 back to client. res.send( '', 200 ); } else { dbFindClaimByTitle.get( [ title, commitHash ], function ( err, claim ) { if (!err && claim) { db.serialize( function () { dbClearFetchErrorCount.run([title], dbUpdateErrCB.bind(null, title, commitHash, "page fetch error count", "null")); // Insert/update result and stats depending on whether this was // the first try or a subsequent retry -- prevents duplicates dbInsertResult.run([claim.id, result], dbUpdateErrCB.bind(null, title, commitHash, "result", "null")); var stats = [skipCount, failCount, errorCount, statsScore(skipCount,failCount,errorCount)]; dbInsertClaimStats.run(stats.concat([claim.page_id, commitHash]), function ( err ) { if ( err ) { dbUpdateErrCB( title, commitHash, 'stats', null, err ); } else { dbUpdateLatestResult.run( commitHash, claim.page_id, dbUpdateErrCB.bind(null, title, commitHash, 'latest result', null ) ); } } ); // Mark the claim as having a result. Used to be // error-free result, but now we are using it to track if // we have a result already. dbUpdateClaimResult.run([claim.id], dbUpdateErrCB.bind(null, title, commitHash, "claim result", "null")); console.log( '<- ' + title + ': ', skipCount, failCount, errorCount, commitHash.substr(0,7) ); // NOTE: the last db update may not have completed yet // For now, always sending HTTP 200 back to client. res.send( '', 200 ); }); } else { var msg = "Did not find claim for title: " + title; msg = err ? msg + "\n" + err.toString() : msg; res.send(msg, 500); } } ); } }, indexLinkList = function () { return '<p>More details:</p>\n<ul>' + '<li><a href="/topfails">Results by title</a></li>\n' + '<li><a href="/regressions">Top regressions</a></li>\n' + '<li><a href="/topfixes">Top fixes</a></li>\n' + '<li><a href="/stats/failedFetches">Non-existing test pages</a></li>\n' + '<li><a href="/stats/failsDistr">Histogram of failures</a></li>\n' + '<li><a href="/stats/skipsDistr">Histogram of skips</a></li>\n' + '<li><a href="/commits">List of all tested commits</a></li>\n' + '</ul>'; }, statsWebInterface = function ( req, res ) { function displayRow(res, title, val) { // round numeric data, but ignore others if(!isNaN(Math.round(val*100)/100)) { val = Math.round(val*100)/100; } res.write( '<tr style="font-weight:bold"><td style="padding-left:20px;">' + title + '</td><td style="padding-left:20px; text-align:right">' + val + '</td></tr>' ); } // Fetch stats for commit dbStatsQuery.get([-1], function ( err, row ) { if ( err || !row ) { var msg = "Stats query returned nothing!"; msg = err ? msg + "\n" + err.toString() : msg; console.error("Error: " + msg); res.send( msg, 500 ); } else { res.setHeader( 'Content-Type', 'text/html; charset=UTF-8' ); res.status( 200 ); res.write( '<html><body>' ); var tests = row.total, errorLess = row.no_errors, skipLess = row.no_skips, numRegressions = row.numregressions, numFixes = row.numfixes, noErrors = Math.round( 100 * 100 * errorLess / tests ) / 100, perfects = Math.round( 100* 100 * skipLess / tests ) / 100, syntacticDiffs = Math.round( 100 * 100 * ( row.no_fails / tests ) ) / 100; res.write( '<p>We have run roundtrip-tests on <b>' + tests + '</b> articles, of which <ul><li><b>' + noErrors + '%</b> parsed without crashes </li><li><b>' + syntacticDiffs + '%</b> round-tripped without semantic differences, and </li><li><b>' + perfects + '%</b> round-tripped with no character differences at all.</li>' + '</ul></p>' ); var width = 800; res.write( '<table><tr height=60px>'); res.write( '<td width=' + ( width * perfects / 100 || 0 ) + 'px style="background:green" title="Perfect / no diffs"></td>' ); res.write( '<td width=' + ( width * ( syntacticDiffs - perfects ) / 100 || 0 ) + 'px style="background:yellow" title="Syntactic diffs"></td>' ); res.write( '<td width=' + ( width * ( 100 - syntacticDiffs ) / 100 || 0 ) + 'px style="background:red" title="Semantic diffs"></td>' ); res.write( '</tr></table>' ); res.write( '<p>Latest revision:' ); res.write( '<table><tbody>'); displayRow(res, "Git SHA1", row.maxhash); displayRow(res, "Test Results", row.maxresults); displayRow(res, "Regressions", numRegressions); displayRow(res, "Fixes", numFixes); res.write( '</tbody></table></p>' ); res.write( '<p>Averages (over the latest results):' ); res.write( '<table><tbody>'); displayRow(res, "Errors", row.avgerrors); displayRow(res, "Fails", row.avgfails); displayRow(res, "Skips", row.avgskips); displayRow(res, "Score", row.avgscore); res.write( '</tbody></table></p>' ); res.write( indexLinkList() ); res.end( '</body></html>' ); } }); }, failsWebInterface = function ( req, res ) { console.log( 'GET /topfails/' + req.params[0] ); var page = ( req.params[0] || 0 ) - 0, offset = page * 40; dbFailsQuery.all( [ offset ], function ( err, rows ) { var i, row, output, matches, total = {}; if ( err ) { res.send( err.toString(), 500 ); } else if ( rows.length <= 0 ) { res.send( 'No entries found', 404 ); } else { res.setHeader( 'Content-Type', 'text/html; charset=UTF-8' ); res.status( 200 ); res.write( '<html><body>' ); res.write( '<p>' ); if ( page > 0 ) { res.write( '<a href="/topfails/' + ( page - 1 ) + '">Previous</a> | ' ); } else { res.write( 'Previous | ' ); } res.write( '<a href="/topfails/' + ( page + 1 ) + '">Next</a>' ); res.write( '</p>' ); res.write( '<table><tr><th>Title</th><th>Commit</th><th>Syntactic diffs</th><th>Semantic diffs</th><th>Errors</th></tr>' ); for ( i = 0; i < rows.length; i++ ) { res.write( '<tr><td style="padding-left: 0.4em; border-left: 5px solid ' ); row = rows[i]; if ( row['stats.skips'] === 0 && row['stats.fails'] === 0 && row['stats.errors'] === 0 ) { res.write( 'green' ); } else if ( row['stats.errors'] > 0 ) { res.write( 'red' ); } else if ( row['stats.fails'] === 0 ) { res.write( 'orange' ); } else { res.write( 'red' ); } res.write( '"><a target="_blank" href="http://parsoid.wmflabs.org/_rt/en/' + row.title + '">' + row.title + '</a> | ' + '<a target="_blank" href="http://*****:*****@lh</a> | ' + '<a target="_blank" href="/latestresult/' + row.title + '">latest result</a>' + '</td>' ); res.write( '<td>' + makeCommitLink( row.hash, row.title ) + '</td>' ); res.write( '<td>' + row.skips + '</td><td>' + row.fails + '</td><td>' + ( row.errors === null ? 0 : row.errors ) + '</td></tr>' ); } res.end( '</table></body></html>' ); } } ); }, resultsWebInterface = function ( req, res ) { db.all( 'SELECT result FROM results', function ( err, rows ) { var i; if ( err ) { console.error( err ); res.send( err.toString(), 500 ); } else { if ( rows.length === 0 ) { res.send( '', 404 ); } else { res.setHeader( 'Content-Type', 'text/xml; charset=UTF-8' ); res.status( 200 ); res.write( '<?xml-stylesheet href="/static/result.css"?>\n' ); res.write( '<testsuite>' ); for ( i = 0; i < rows.length; i++ ) { res.write( rows[i].result ); } res.end( '</testsuite>' ); } } } ); }; function resultWebCallback( req, res, err, row ) { if ( err ) { console.error( err ); res.send( err.toString(), 500 ); } else if ( row ) { res.setHeader( 'Content-Type', 'text/xml; charset=UTF-8' ); res.status( 200 ); res.write( '<?xml-stylesheet href="/static/result.css"?>\n' ); res.end( row.result ); } else { res.send( 'no results for that page at the requested revision', 404 ); } } function resultWebInterface( req, res ) { var commit = req.params[1] ? req.params[0] : null; var title = commit === null ? req.params[0] : req.params[1]; if ( commit !== null ) { dbGetResultWithCommit.get( commit, title, resultWebCallback.bind( null, req, res ) ); } else { dbGetOneResult.get( title, resultWebCallback.bind( null, req, res ) ); } } function GET_failedFetches( req, res ) { dbFailedFetches.all( [maxFetchRetries], function ( err, rows ) { if ( err ) { console.error( err ); res.send( err.toString(), 500 ); } else { var n = rows.length; res.setHeader( 'Content-Type', 'text/html; charset=UTF-8' ); res.status( 200 ); res.write( '<html><body>' ); if (n === 0) { res.write('No titles returning 404! All\'s well with the world!'); } else { res.write('<h1> The following ' + n + ' titles return 404</h1>'); res.write('<ul>'); for (var i = 0; i < n; i++) { res.write('<li> ' + rows[i].title + ' </li>'); } res.write( '</ul>'); } res.end('</body></html>' ); } } ); } function GET_failsDistr( req, res ) { dbFailsDistribution.all([-1], function ( err, rows ) { if ( err ) { console.error( err ); res.send( err.toString(), 500 ); } else { var n = rows.length; res.setHeader( 'Content-Type', 'text/html; charset=UTF-8' ); res.status( 200 ); res.write( '<html><body>' ); res.write('<h1> Distribution of semantic errors </h1>'); res.write('<table><tbody>'); res.write('<tr><th># errors</th><th># pages</th></tr>'); for (var i = 0; i < n; i++) { var r = rows[i]; res.write('<tr><td>' + r.fails + '</td><td>' + r.num_pages + '</td></tr>'); } res.end('</table></body></html>' ); } } ); } function GET_skipsDistr( req, res ) { dbSkipsDistribution.all([-1], function ( err, rows ) { if ( err ) { console.error( err ); res.send( err.toString(), 500 ); } else { var n = rows.length; res.setHeader( 'Content-Type', 'text/html; charset=UTF-8' ); res.status( 200 ); res.write( '<html><body>' ); res.write('<h1> Distribution of syntactic errors </h1>'); res.write('<table><tbody>'); res.write('<tr><th># errors</th><th># pages</th></tr>'); for (var i = 0; i < n; i++) { var r = rows[i]; res.write('<tr><td>' + r.skips + '</td><td>' + r.num_pages + '</td></tr>'); } res.end('</table></body></html>' ); } } ); } function makeCommitLink( commit, title ) { return '<a href="/result/' + commit + '/' + title + '">' + commit.substr( 0, 7 ) + '</a>'; } function displayPageList(res, urlPrefix, page, header, err, rows) { console.log( 'GET ' + urlPrefix + "/" + page ); if ( err ) { res.send( err.toString(), 500 ); } else if ( !rows || rows.length <= 0 ) { res.send( 'No entries found', 404 ); } else { res.setHeader( 'Content-Type', 'text/html; charset=UTF-8' ); res.status( 200 ); res.write('<html>'); res.write('<head><style type="text/css">'); res.write('th { padding: 0 10px }'); res.write('td { text-align: center; }'); res.write('td.title { text-align: left; }'); res.write('</style></head>'); res.write('<body>'); if (header) { res.write("<b>" + header + "</b>"); } res.write('<p>'); if ( page > 0 ) { res.write( '<a href="' + urlPrefix + "/" + ( page - 1 ) + '">Previous</a> | ' ); } else { res.write( 'Previous | ' ); } if (rows.length === 40) { res.write('<a href="' + urlPrefix + "/" + ( page + 1 ) + '">Next</a>'); } res.write('</p>'); res.write('<table>'); res.write('<tr><th>Title</th><th>New Commit</th><th>Errors|Fails|Skips</th><th>Old Commit</th><th>Errors|Fails|Skips</th></tr>' ); for (var i = 0; i < rows.length; i++ ) { var r = rows[i]; res.write('<tr>'); res.write('<td class="title"><a href="http://parsoid.wmflabs.org/_rt/en/' + r.title.replace(/"/g, '"') + '">' + r.title + '</a></td>'); res.write('<td>' + makeCommitLink( r.new_commit, r.title ) + '</td>'); res.write('<td>' + r.new_errors + "|" + r.new_fails + "|" + r.new_skips + '</td>'); res.write('<td>' + makeCommitLink( r.old_commit, r.title ) + '</td>'); res.write('<td>' + r.old_errors + "|" + r.old_fails + "|" + r.old_skips + '</td>'); res.write('</tr>'); } res.end( '</table></body></html>' ); } } function GET_regressions ( req, res ) { var page, offset, urlPrefix; if (req.params.length > 1) { var r1 = req.params[0]; var r2 = req.params[1]; urlPrefix = "/regressions/between/" + r1 + "/" + r2; page = (req.params[2] || 0) - 0; offset = page * 40; dbNumRegressionsBetweenRevs.get([r2,r1], function(err, row) { if (err || !row) { res.send( err.toString(), 500 ); } else { var topfixesLink = "/topfixes/between/" + r1 + "/" + r2, header = "Total regressions between selected revisions: " + row.numRegressions + ' | <a href="' + topfixesLink + '">topfixes</a>'; dbRegressionsBetweenRevs.all([r2, r1, offset ], displayPageList.bind(null, res, urlPrefix, page, header)); } }); } else { urlPrefix = "/regressions"; page = ( req.params[0] || 0 ) - 0; offset = page * 40; dbRegressedPages.all([ offset ], displayPageList.bind(null, res, urlPrefix, page, null)); } } function GET_topfixes ( req, res ) { var page, offset, urlPrefix; if (req.params.length > 1) { var r1 = req.params[0]; var r2 = req.params[1]; urlPrefix = "/topfixes/between/" + r1 + "/" + r2; page = (req.params[2] || 0) - 0; offset = page * 40; dbNumFixesBetweenRevs.get([r2,r1], function(err, row) { if (err || !row) { res.send( err.toString(), 500 ); } else { var regressionLink = "/regressions/between/" + r1 + "/" + r2, header = "Total fixes between selected revisions: " + row.numFixes + ' | <a href="' + regressionLink + '">regressions</a>'; dbFixesBetweenRevs.all([r2, r1, offset ], displayPageList.bind(null, res, urlPrefix, page, header)); } }); } else { urlPrefix = "/topfixes"; page = ( req.params[0] || 0 ) - 0; offset = page * 40; dbFixedPages.all([ offset ], displayPageList.bind(null, res, urlPrefix, page, null)); } } function GET_commits( req, res ) { dbCommits.all([-1], function ( err, rows ) { if ( err ) { console.error( err ); res.send( err.toString(), 500 ); } else { var n = rows.length; res.setHeader( 'Content-Type', 'text/html; charset=UTF-8' ); res.status( 200 ); res.write( '<html><body>' ); res.write('<h1> List of all commits </h1>'); res.write('<table><tbody>'); res.write('<tr><th>Commit hash</th><th>Timestamp</th>' + //'<th>Regressions</th><th>Fixes</th>' + '<th>Tests</th>' + '<th>-</th><th>+</th></tr>'); for (var i = 0; i < n; i++) { var r = rows[i]; res.write('<tr><td>' + r.hash + '</td><td>' + r.timestamp + '</td>'); //res.write('<td>' + r.numregressions + '</td>'); //res.write('<td>' + r.numfixes + '</td>'); res.write('<td>' + r.numtests + '</td>'); if ( i + 1 < n ) { res.write('<td><a href="/regressions/between/' + rows[i+1].hash + '/' + r.hash + '"><b>-</b></a></td>' ); res.write('<td><a href="/topfixes/between/' + rows[i+1].hash + '/' + r.hash + '"><b>+</b></a></td>' ); } else { res.write('<td></td><td></td>'); } res.write('</tr>'); } res.end('</table></body></html>' ); } } ); } // Make an app var app = express.createServer(); // Make the coordinator app var coordApp = express.createServer(); // Add in the bodyParser middleware (because it's pretty standard) app.use( express.bodyParser() ); coordApp.use( express.bodyParser() ); // Main interface app.get( /^\/results$/, resultsWebInterface ); // Results for a title (on latest commit) app.get( /^\/latestresult\/(.*)$/, resultWebInterface ); // Results for a title on any commit app.get( /^\/result\/([a-f0-9]*)\/(.*)$/, resultWebInterface ); // List of failures sorted by severity app.get( /^\/topfails\/(\d+)$/, failsWebInterface ); // 0th page app.get( /^\/topfails$/, failsWebInterface ); // Overview of stats app.get( /^\/$/, statsWebInterface ); app.get( /^\/stats$/, statsWebInterface ); // Failed fetches app.get( /^\/stats\/failedFetches$/, GET_failedFetches ); // Regressions -- 0th and later pages app.get( /^\/regressions$/, GET_regressions ); app.get( /^\/regressions\/(\d+)$/, GET_regressions ); app.get( /^\/regressions\/between\/([^\/]+)\/([^\/]+)(?:\/(\d+))?$/, GET_regressions ); // Topfixes -- 0th and later pages app.get( /^\/topfixes$/, GET_topfixes ); app.get( /^\/topfixes\/(\d+)$/, GET_topfixes ); app.get( /^\/topfixes\/between\/([^\/]+)\/([^\/]+)(?:\/(\d+))?$/, GET_topfixes ); // Distribution of fails app.get( /^\/stats\/failsDistr$/, GET_failsDistr ); // Distribution of fails app.get( /^\/stats\/skipsDistr$/, GET_skipsDistr ); // List of all commits app.use( '/commits', GET_commits ); app.use( '/static', express.static( __dirname + '/static' ) ); // Clients will GET this path if they want to run a test coordApp.get( /^\/title$/, getTitle ); // Receive results from clients coordApp.post( /^\/result\/([^\/]+)/, receiveResults ); // Start the app app.listen( 8001 ); coordApp.listen( 8002 ); }() );
var express = require('express'), sio = require('socket.io'); var app = express.createServer( express.bodyParser(), express.static('public') ); // app.use(express.bodyParser()); // app.use(express.static('public')); app.listen(3000); var io = sio.listen(app); io.sockets.on('connection', function(socket){ // console.log('Someone connected'); socket.on('join', function(name) { socket.nickname = name; socket.broadcast.emit('announcement', name + ' joined the chat'); // 广播消息给其他用户 }); socket.on('text', function(msg,fn){ socket.broadcast.emit('text', socket.nickname, msg); // 确认消息已经接收 fn(Date.now()); }); });
// merge contacts from journals var fs = require('fs'), sys = require('sys'), http = require('http'), url = require('url'), lfs = require('../../Common/node/lfs.js'), crypto = require('crypto'); var lockerInfo; var express = require('express'),connect = require('connect'); var app = express.createServer(connect.bodyDecoder(), connect.cookieDecoder(), connect.session({secret : "locker"})); // Process the startup JSON object process.stdin.resume(); process.stdin.on("data", function(data) { lockerInfo = JSON.parse(data); if (!lockerInfo || !lockerInfo["workingDirectory"]) { process.stderr.write("Was not passed valid startup information."+data+"\n"); process.exit(1); } process.chdir(lockerInfo.workingDirectory); app.listen(lockerInfo.port, "localhost", function() { sys.debug(data); process.stdout.write(data); gatherContacts(); }); });
var express = require('express'); var app = express.createServer(express.logger()); var fs = require("fs"); var app = express.createServer(express.logger()); app.configure(function(){ app.use('/static', express.static(__dirname + '/static')); }); app.get('/', function(req, res) { var buf = new Buffer(fs.readFileSync('index.html'), 'utf-8'); res.send(buf.toString()); }); var port = process.env.PORT || 8080; app.listen(port, function() { console.log("Listening on " + port); });
mailer = require('mailer'), markdown = require('markdown').markdown, models = require('./models'), sys = require('sys'), path = require('path'), fs = require('fs'), db, Friends, User, Video, LoginToken, Settings = { development: {}, test: {}, production: {} }, emails; var app = module.exports = express.createServer(form({ keepExtensions: true })); function renderJadeFile(template, options) { var fn = jade.compile(template, options); return fn(options.locals); } // Configuration var pub = __dirname + '/public'; app.configure(function(){ app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.use(express.favicon()); app.use(express.bodyParser()); //app.use(connectTimeout({ time: 10000 }));
var express = require('express'), app = express.createServer(), io = require('socket.io').listen(app), fs = require('fs'); app.get('/', function(req, res){ io.sockets.emit('reload'); res.send('ok'); }); app.get('/delayed', function(req, res){ setTimeout(function(){ io.sockets.emit('reload'); res.send('ok'); }, 1000); }); app.configure(function(){ app.use(express.methodOverride()); app.use(express.bodyParser()); app.use(express.static(__dirname + '/public')); app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); app.use(app.router); }); app.listen(17001);
(function() { // init vars var config , version = '0.1.0a' // get modules , fs = require('fs') , git = require('gitty') // get os module , os = require('os') , qs = require('querystring') // get middleware , express = require('express') , app = express.createServer() , http = require('http') , jade = require('jade') // create socket connection , io = require('socket.io').listen(app) , port = 1337 , nslookup = require('dns').lookup , netIp , launched_apps = {}; // console output colors var red = '\u001b[31m' , blue = '\u001b[34m' , reset = '\u001b[0m'; var ipFlag = false; console.log('Starting NodeTV...'); console.log('Resolving network IP...'); resolveIp(os.hostname()); function resolveIp(hostname) { // determine network ip from hostname nslookup(hostname, function(err, addr, fam) { // if failed if (err) { // if there is a domain in the hostname if (os.hostname().split('.').length === 3) { // let the user know console.log(red + '!!! ' + reset + 'NodeTV has detected a potential issue while resolving your IP, applying workaround...'); ipFlag = true; // try again without it var hostNoDomain = os.hostname().split('.')[0] + '.' + os.hostname().split('.')[2]; resolveIp(hostNoDomain); } else { // otherwise tell the user something's up console.log(red + 'There was a problem resolving the network IP from the server\'s hostname.' + reset); // and quit process.exit(); } } else { if (ipFlag) { console.log(red + '!!! ' + reset + 'NodeTV applied a workaround for an issue and may exhibit unexpected behavior.'); } // all is good give NodeTV the resolved IP netIp = addr; // once IP is resolved, start the server // this nslookup fixes an issue for devices that are unable // to resolve a hostname over LAN, like Android init(); } }); } function init() { // load modules require('./remote.js')(io); // config server app.configure(function() { // set view directory and engine app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); // methodOverride checks req.body.method for the HTTP method override // bodyParser parses the request body and populates req.body app.use(express.methodOverride()); app.use(express.bodyParser()); // use cookie parser app.use(express.cookieParser()); // set public directory for static files app.use(express.static(__dirname + '/public')); // use router for non-static files app.use(app.router); }); // dev env app.configure('development', function(){ app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); // prod env app.configure('production', function(){ app.use(express.errorHandler()); }); /* * http routes */ // render app app.get('/', function(req, res) { res.render('index', { layout : 'layout', netIp : 'http://' + netIp, version : version }); }); // give client the app list app.get('/applist', function(req, res) { // generate a temporary unique id for each app var appId = function() { var chars = 'abcdefghijklmnopqrstuvwxyz1234567890' , id = ''; for (var i = 0; i < 10; i++) { id += chars.charAt((Math.random() * chars.length - 1).toFixed()); } return id; }; // get app list, create array, and send to client fs.readdir(__dirname + '/apps', function(err, files) { if (err || !files.length) { // if an error is thrown log it and tell the client console.log(err || red + '!!! ' + reset + 'No apps installed. Failed.'); res.writeHead(500); res.write('Error reading app directory or no apps are installed.'); res.end(); } else { // otherwise lets serve up some apps var applist = []; // construct app object from manifest file files.forEach(function(val, key) { var appname = val // get manifest path , manifest = __dirname + '/apps/' + appname + '/manifest.json' , appconfig = JSON.parse(fs.readFileSync(manifest)); // resolve paths to public route appconfig.icon = '/apps/' + appname + appconfig.icon; // do the same for each script appconfig.scripts.forEach(function(val, key) { appconfig.scripts[key] = '/apps/' + appname + val; }); // give id appconfig.id = appname + ':' + appId(); // add to list applist.push(appconfig); }); res.writeHead(200); res.write(JSON.stringify(applist)); res.end(); } }); }); // resolve static content for apps app.get('/apps/:appname/:directory/:file', function(req, res) { // get params var params = req.params , appname = params.appname , dir = params.directory , file = params.file , path = __dirname + '/apps/' + appname + '/' + dir + '/' + file; // determine if file is valid fs.exists(path, function(valid) { if (valid) { // read the file var asset = fs.readFileSync(path); // and serve it up res.writeHead(200); res.end(asset); } else { // fail res.writeHead(404); res.write('File not found.'); res.end(); } }); }); // app launcher/ui server app.post('/launch/:appname', function(req, res) { var appname = req.params.appname , app_dir = __dirname + '/apps/' + appname , appconfig , manifest = app_dir + '/manifest.json'; // sanity check if (fs.existsSync(manifest)) { appconfig = JSON.parse(fs.readFileSync(manifest)); // determine if the view should be rendered or sent var splitup = appconfig.home.split('.') , last = splitup.length - 1; // render jade template if (splitup[last] == 'jade') { res.render(app_dir + appconfig.home, { layout: false }); // render static html } else if (splitup[last] == 'html') { res.writeHead(200); fs.readFile(app_dir + appconfig.home, function(err, data) { res.write(data); res.end(); }); } // require server side code if (appconfig.init && !(launched_apps[appname])) { require(app_dir + appconfig.init)(app); launched_apps[appname] = true } } else { res.writeHead(404); res.end(); } }); // get mounted drives app.get('/getMountedDisks', function(req, res) { // determine os type var platform = os.platform() , disks = [] , paths = { 'darwin' : '/Volumes', 'linux' : '/mnt' }; // find and parse mounted disks fs.readdir(paths[platform], function(err, data) { if (err) { res.writeHead(500); res.end(); } else { data.forEach(function(val, key) { var disk = { name : val, path : paths[platform] + '/' + val }; disks.push(disk); }); res.write(JSON.stringify(disks)); res.end(); } }); }); // finds subdirectories of the passed path and returns them in an array app.get('/listDirectories', function(req, res) { // get the path var var path = qs.parse(req.url.split('?')[1]).path , dirs = []; // if the path is good then get it's dirs if (fs.existsSync(path)) { fs.readdir(path, function(err, files) { files.forEach(function(val,key) { if (fs.lstatSync(path + '/' + val).isDirectory() && val.charAt(0) !== '.') { dirs.push(val); } }); res.write(JSON.stringify(dirs)); res.end(); }); // otherwise fail } else { res.writeHead(500); res.write('Invalid path.'); res.end(); } }); // index library app.post('/indexLibrary', function(req, res) { var path = qs.parse(req.url.split('?')[1]).path; // scan path for movies, music, and pictures require('./indexlib.js')(path, io, function(data) { // respond with library res.write(JSON.stringify(data)); res.end(); }, function(err) { res.writeHead(500); res.end(); }); }); // send the media request by the path app.get('/play', function(req, res) { var path = qs.parse(req.url.split('?')[1]).path; // retrieve media and respond with it }); /* * start server */ app.listen(port, function() { console.log('NodeTV running at ' + netIp + ':' + port); }); } })();