PageRenderTime 60ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/handlers/error.js

https://github.com/KobeCena/jsbin
JavaScript | 132 lines | 100 code | 21 blank | 11 comment | 25 complexity | e1e47eb3cc80ecd2cc71204437879b89 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause
  1. var utils = require('../utils'),
  2. errors = require('../errors'),
  3. BinHandler = require('./bin'),
  4. Observable = utils.Observable,
  5. crypto = require('crypto');
  6. // Handles application errors.
  7. module.exports = Observable.extend({
  8. constructor: function ErrorHandler(sandbox) {
  9. Observable.apply(this, arguments);
  10. this.sandbox = sandbox;
  11. this.helpers = sandbox.helpers;
  12. this.mailer = sandbox.mailer;
  13. utils.bindAll(this, 'notFound', 'httpError', 'uncaughtError');
  14. },
  15. // Handles all types of HTTPError and ensures that the correct type of
  16. // response is returned depending on the type of content requested. So if
  17. // you're expecting JSON you should get JSON.
  18. httpError: function (err, req, res, next) {
  19. err = this.coerceError(err);
  20. if (err instanceof errors.NotFound && req.accepts('html')) {
  21. if (err instanceof errors.BinNotFound) {
  22. return (new BinHandler(this.sandbox)).notFound(req, res);
  23. } else {
  24. return this.renderErrorPage(err, req, res);
  25. }
  26. } else if (err instanceof errors.HTTPError) {
  27. return this.renderError(err, req, res);
  28. }
  29. next(err);
  30. },
  31. // Fall through handler for when no routes match.
  32. notFound: function (req, res, next) {
  33. var error = new errors.NotFound('Page Does Not Exist');
  34. if (req.accepts('html')) {
  35. this.renderErrorPage(error, req, res);
  36. } else {
  37. this.renderError(error, req, res);
  38. }
  39. },
  40. // Displays a friendly 500 page in production if requesting html otherwise
  41. // returns an appropriate format.
  42. uncaughtError: function (err, req, res, next) {
  43. this.sendErrorReport(err, req);
  44. if (req.accepts('html')) {
  45. this.renderErrorPage(err, req, res);
  46. } else {
  47. var error = new errors.HTTPError(500, 'Internal Server Error');
  48. this.renderError(error, req, res);
  49. }
  50. },
  51. renderError: function (err, req, res) {
  52. res.status(err.status);
  53. if (req.accepts(['html'])) {
  54. res.contentType('html');
  55. res.send(err.toHTMLString());
  56. } else if (req.accepts(['json'])) {
  57. res.json(err);
  58. } else {
  59. res.contentType('txt');
  60. res.send(err.toString());
  61. }
  62. },
  63. renderErrorPage: function (err, req, res) {
  64. var status = err.status || 500;
  65. res.status(status).render('error', {
  66. is_500: status !== 404, // Saves us having many error pages at the mo.
  67. is_404: status === 404,
  68. root: this.helpers.url('', true),
  69. dave: this.helpers.urlForStatic('/images/logo.png')
  70. });
  71. },
  72. sendErrorReport: function (err, req) {
  73. var to = this.helpers.set('notify errors'),
  74. session = utils.extend({}, req.session),
  75. context, headers;
  76. if (this.helpers.production && to && to.length) {
  77. // Don't send the users email address via email.
  78. if (session && session.user) {
  79. delete session.user.email;
  80. }
  81. headers = utils.extend({}, req.headers);
  82. delete headers.cookie;
  83. context = {
  84. name: err.name,
  85. message: err.message,
  86. hash: crypto.createHash('md5').update(err.stack).digest('hex').slice(0, 6),
  87. stack: err.stack,
  88. body: JSON.stringify(req.body, null, 2),
  89. session: JSON.stringify(session, null, 2) || null,
  90. url: this.helpers.url(req.url, true),
  91. path: req.url,
  92. headers: JSON.stringify(headers, null, 2) || null,
  93. method: req.method
  94. };
  95. if (context.body === '{}') {
  96. context.body = null;
  97. }
  98. this.mailer.errorReport(to, context);
  99. }
  100. },
  101. // Checks to see if the error has a status property and if so converts
  102. // it into an instance of HTTPError. Just returns this original error
  103. // if no status is found.
  104. coerceError: function (err) {
  105. var status = typeof err === 'number' ? err : err.status;
  106. if (!(err instanceof errors.HTTPError) && status) {
  107. return errors.create(status, err.message);
  108. }
  109. return err;
  110. }
  111. });