diff --git a/package.json b/package.json index 172b6e48c9..a529116deb 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "pretty-data": "git://github.com/vkiryukhin/pretty-data#master", "js2xmlparser": "~0.1.2", "mongoose": "~3.8.1", - "domain-middleware": "~0.1.0", "swagger-node-express": "git://github.com/lefnire/swagger-node-express#habitrpg", "passport": "~0.1.18", "passport-facebook": "~1.0.2", @@ -48,7 +47,8 @@ "connect-ratelimit": "0.0.6", "winston": "~0.7.2", "winston-mail": "~0.2.7", - "winston-newrelic": "~0.1.4" + "winston-newrelic": "~0.1.4", + "domain-middleware": "~0.1.0" }, "private": true, "subdomain": "habitrpg", diff --git a/public/js/app.js b/public/js/app.js index c642aea407..fdffa58ad6 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -200,24 +200,40 @@ window.habitrpg = angular.module('habitrpg', } // Handle errors - var interceptor = ['$rootScope', '$q', function ($rootScope, $q) { + $httpProvider.responseInterceptors.push(['$rootScope', '$q', function ($rootScope, $q) { function success(response) { return response; } function error(response) { - //var status = response.status; - response.data = (response.data.err) ? response.data.err : response.data; - if (response.status == 0) response.data = window.env.t('serverUnreach'); - if (response.status == 500) response.data += window.env.t('seeConsole'); + debugger; + // Offline + if (response.status == 0 || + // don't know why we're getting 404 here, should be 0 + (response.status == 404 && _.isEmpty(response.data))) { + $rootScope.$broadcast('responseText', window.env.t('serverUnreach')); - var error = response.status == 0 ? response.data : (window.env.t('error') + ' ' + response.status + ': ' + response.data); - $rootScope.$broadcast('responseError', error); - console.log(arguments); - return $q.reject(response); + // Needs refresh + } else if (response.needRefresh) { + $rootScope.$broadcast('responseError', "The site has been updated and the page needs to refresh. The last action has not been recorded, please refresh and try again."); + + // 400 range? + } else if (response < 500) { + $rootScope.$broadcast('responseText', response.data.err || response.data); + + // Error + } else { + var error = 'Please reload, ' + + '"'+window.env.t('error')+' '+(response.data.err || response.data || 'something went wrong')+'"' + + window.env.t('seeConsole'); + $rootScope.$broadcast('responseError', error); + console.error(response); + } + + //return $q.reject(response); // this completely halts the chain, meaning we can't queue offline actions + return response; } return function (promise) { return promise.then(success, error); } - }]; - $httpProvider.responseInterceptors.push(interceptor); + }]); }]) diff --git a/public/js/controllers/notificationCtrl.js b/public/js/controllers/notificationCtrl.js index fa2c69bf0e..a04474e879 100644 --- a/public/js/controllers/notificationCtrl.js +++ b/public/js/controllers/notificationCtrl.js @@ -137,5 +137,8 @@ habitrpg.controller('NotificationCtrl', $rootScope.$on('responseError', function(ev, error){ Notification.error(error); }); + $rootScope.$on('responseText', function(ev, error){ + Notification.text(error); + }); } ]); diff --git a/public/js/services/notificationServices.js b/public/js/services/notificationServices.js index 323f542d92..02f92bbc83 100644 --- a/public/js/services/notificationServices.js +++ b/public/js/services/notificationServices.js @@ -10,7 +10,7 @@ angular.module("notificationServices", []) top_offset: 20, align: 'right', //('left', 'right', or 'center') width: 250, //(integer, or 'auto') - delay: 7000, + delay: (type=='error') ? 0 : 7000, allow_dismiss: true, stackup_spacing: 10 // spacing between consecutive stacecked growls. }); diff --git a/src/middleware.js b/src/middleware.js index edda3917a5..311995fe3f 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -7,6 +7,7 @@ var limiter = require('connect-ratelimit'); var logging = require('./logging'); module.exports.apiThrottle = function(app) { + if (nconf.get('NODE_ENV') !== 'production') return; app.use(limiter({ end:false, catagories:{ @@ -23,6 +24,23 @@ module.exports.apiThrottle = function(app) { }); } +module.exports.errorHandler = function(err, req, res, next) { + //res.locals.domain.emit('error', err); + // when we hit an error, send it to admin as an email. If no ADMIN_EMAIL is present, just send it to yourself (SMTP_USER) + var stack = (err.stack ? err.stack : err.message ? err.message : err) + + "\n ----------------------------\n" + + "\n\noriginalUrl: " + req.originalUrl + + "\n\nauth: " + req.headers['x-api-user'] + ' | ' + req.headers['x-api-key'] + + "\n\nheaders: " + JSON.stringify(req.headers) + + "\n\nbody: " + JSON.stringify(req.body) + + (res.locals.ops ? "\n\ncompleted ops: " + JSON.stringify(res.locals.ops) : ""); + logging.error(stack); + var message = err.message ? err.message : err; + message = (message.length < 200) ? message : message.substring(0,100) + message.substring(message.length-100,message.length); + res.json(500,{err:message}); //res.end(err.message); +} + + module.exports.forceSSL = function(req, res, next){ var baseUrl = nconf.get("BASE_URL"); // Note x-forwarded-proto is used by Heroku & nginx, you'll have to do something different if you're not using those @@ -194,7 +212,7 @@ module.exports.locals = function(req, res, next) { if(err) return res.json(500, {err: err}); var isStaticPage = req.url.split('/')[1] === 'static'; // If url contains '/static/' - console.log(isStaticPage) + //console.log(isStaticPage) // Load moment.js language file only when not on static pages language.momentLang = ((!isStaticPage && momentLangs[language.code])|| undefined); diff --git a/src/server.js b/src/server.js index 04981a8147..3f2cb65f3e 100644 --- a/src/server.js +++ b/src/server.js @@ -1,5 +1,4 @@ // Only do the minimal amount of work before forking just in case of a dyno restart -var cluster = require("cluster"); var _ = require('lodash'); var nconf = require('nconf'); var utils = require('./utils'); @@ -8,23 +7,10 @@ var logging = require('./logging'); var isProd = nconf.get('NODE_ENV') === 'production'; var isDev = nconf.get('NODE_ENV') === 'development'; -if (cluster.isMaster && (isDev || isProd)) { - // Fork workers. - _.times(require('os').cpus().length, function(){ - cluster.fork(); - }); - - cluster.on('disconnect', function(worker, code, signal) { - var w = cluster.fork(); // replace the dead worker - logging.info('[%s] [master:%s] worker:%s disconnect! new worker:%s fork', new Date(), process.pid, worker.process.pid, w.process.pid); - }); - -} else { require('coffee-script'); // remove this once we've fully converted over var express = require("express"); var http = require("http"); var path = require("path"); - var domainMiddleware = require('domain-middleware'); var swagger = require("swagger-node-express"); var middleware = require('./middleware'); @@ -91,13 +77,7 @@ if (cluster.isMaster && (isDev || isProd)) { // ------------ Server Configuration ------------ - domainMiddleware({ - server: server, - killTimeout: 3000 - }), - app.set("port", nconf.get('PORT')); - middleware.apiThrottle(app); if (!isProd) app.use(express.logger("dev")); app.use(express.compress()); @@ -125,11 +105,6 @@ if (cluster.isMaster && (isDev || isProd)) { app.use(express['static'](path.join(__dirname, "/../build"), { maxAge: maxAge })); app.use(express['static'](path.join(__dirname, "/../public"))); - // development only - //if ("development" === app.get("env")) { - // app.use(express.errorHandler()); - //} - // Custom Directives app.use(require('./routes/pages').middleware); app.use(require('./routes/auth').middleware); @@ -137,16 +112,12 @@ if (cluster.isMaster && (isDev || isProd)) { app.use('/api/v2', v2); app.use('/api/v1', require('./routes/apiv1').middleware); app.use('/export', require('./routes/dataexport').middleware); - - app.use(utils.crashWorker(server,mongoose)); - app.use(utils.errorHandler); - require('./routes/apiv2.coffee')(swagger, v2); + app.use(middleware.errorHandler); server.on('request', app); server.listen(app.get("port"), function() { return logging.info("Express server listening on port " + app.get("port")); }); - module.exports = server; -} + module.exports = server; \ No newline at end of file diff --git a/src/utils.js b/src/utils.js index a4a44d52c2..fd29e8f4e8 100644 --- a/src/utils.js +++ b/src/utils.js @@ -2,7 +2,6 @@ var nodemailer = require('nodemailer'); var nconf = require('nconf'); var crypto = require('crypto'); var path = require("path"); -var cluster = require("cluster"); module.exports.sendEmail = function(mailData) { var smtpTransport = nodemailer.createTransport("SMTP",{ @@ -46,39 +45,4 @@ module.exports.setupConfig = function(){ Error.stackTraceLimit = Infinity; if (nconf.get('NODE_ENV') === 'production') require('newrelic'); -}; - -module.exports.crashWorker = function(server,mongoose) { - return function(err, req, res, next) { - if (!cluster.isMaster) { - // make sure we close down within 30 seconds - var killtimer = setTimeout(function() { - process.exit(1); - }, 30000); - // But don't keep the process open just for that! - killtimer.unref(); - // stop taking new requests. - server.close(); - mongoose.connection.close(); - cluster.worker.disconnect(); - } - next(err); - }; -} - - -module.exports.errorHandler = function(err, req, res, next) { - // when we hit an error, send it to admin as an email. If no ADMIN_EMAIL is present, just send it to yourself (SMTP_USER) - var stack = (err.stack ? err.stack : err.message ? err.message : err) + - "\n ----------------------------\n" + - "\n\noriginalUrl: " + req.originalUrl + - "\n\nauth: " + req.headers['x-api-user'] + ' | ' + req.headers['x-api-key'] + - "\n\nheaders: " + JSON.stringify(req.headers) + - "\n\nbody: " + JSON.stringify(req.body) + - (res.locals.ops ? "\n\ncompleted ops: " + JSON.stringify(res.locals.ops) : ""); - var logging = require('./logging'); - logging.error(stack); - var message = err.message ? err.message : err; - message = (message.length < 200) ? message : message.substring(0,100) + message.substring(message.length-100,message.length); - res.json(500,{err:message}); //res.end(err.message); -} +}; \ No newline at end of file diff --git a/views/options/social/tavern.jade b/views/options/social/tavern.jade index 2f83b3bd33..102914091a 100644 --- a/views/options/social/tavern.jade +++ b/views/options/social/tavern.jade @@ -28,7 +28,7 @@ table.table.table-striped tr td - a(target='_blank', href='http://habitrpg.wikia.com/wiki/Board:Looking_for_a_Group_(LFG)')=env.t('lfgPosts') + a(target='_blank', href='http://habitrpg.wikia.com/wiki/Board:The_Archery_-_LFG')=env.t('lfgPosts') tr td a(target='_blank', href='https://vimeo.com/57654086')=env.t('tutorial')