// requires var http = require('http'); var path = require('path'); var url = require('url'); var fs = require('fs'); var child_process = require('child_process'); // constants var PORT = +process.env.PORT || 9292; var HOST = process.env.HOST || '0.0.0.0'; // main http.createServer(serveRequest).listen(PORT, HOST); console.log('listening on ' + HOST + ':' + PORT); run_make_test(); 'src test Makefile package.json'.split(' ').forEach(function (filename) { recursivelyWatch(filename, run_make_test); }); // functions function serveRequest(req, res) { var reqTime = new Date(); enqueueOrDo(function () { var filepath = path.normalize(url.parse(req.url).pathname).slice(1); fs.readFile(filepath, function (err, data) { if (err) { if (err.code === 'ENOENT' || err.code === 'EISDIR') { res.statusCode = 404; res.end('404 Not Found: /' + filepath + '\n'); } else { console.log(err); res.statusCode = 500; res.end('500 Internal Server Error: ' + err.code + '\n'); } } else { var ext = filepath.match(/\.[^.]+$/); if (ext) res.setHeader('Content-Type', 'text/' + ext[0].slice(1)); res.end(data); } console.log( '[%s] %s %s /%s - %s%sms', reqTime.toISOString(), res.statusCode, req.method, filepath, data ? (data.length >> 10) + 'kb, ' : '', Date.now() - reqTime ); }); }); } function recursivelyWatch(watchee, cb) { fs.readdir(watchee, function (err, files) { if (err) { // not a directory, just watch it fs.watch(watchee, cb); } else { // a directory, recurse, also watch for files being added or deleted files.forEach(recurse); fs.watch(watchee, function () { fs.readdir(watchee, function (err, filesNew) { if (err) return; // watchee may have been deleted // filesNew - files = new files or dirs to watch filesNew .filter(function (file) { return files.indexOf(file) < 0; }) .forEach(recurse); files = filesNew; }); cb(); }); } function recurse(file) { recursivelyWatch(path.join(watchee, file), cb); } }); } var q; function enqueueOrDo(cb) { q ? q.push(cb) : cb(); } function run_make_test() { if (q) return; q = []; console.log('[%s]\nmake test', new Date().toISOString()); var make_test = child_process.exec('make test', { env: process.env }); make_test.stdout.pipe(process.stdout, { end: false }); make_test.stderr.pipe(process.stderr, { end: false }); make_test.on('exit', function (code) { if (code) { console.error('Exit Code ' + code); } else { var serverAddress = HOST === '0.0.0.0' ? 'localhost:' + PORT : HOST + ':' + PORT; console.log('\nMathQuill is now running on ' + serverAddress); console.log('Open http://' + serverAddress + '/test/demo.html\n'); } for (var i = 0; i < q.length; i += 1) q[i](); q = undefined; }); }