c9-core/plugins/c9.error/error_handler.js

165 wiersze
4.8 KiB
JavaScript
Czysty Zwykły widok Historia

2015-02-10 19:41:24 +00:00
"use strict";
var errors = require("http-error");
2015-02-10 19:41:24 +00:00
plugin.consumes = [
"connect",
2015-09-22 14:46:28 +00:00
"connect.static",
2015-02-10 19:41:24 +00:00
"connect.render",
"connect.render.ejs"
];
plugin.provides = [
"connect.error"
];
module.exports = plugin;
2015-09-22 14:46:28 +00:00
var errorPages = {
404: 1,
401: 1,
500: 1,
503: 1
};
2015-02-10 19:41:24 +00:00
var statusCodes = {
400: "Bad Request",
401: "Unauthorized",
402: "Payment Required",
403: "Forbidden",
404: "Not Found",
405: "Method Not Allowed",
406: "Not Acceptable",
407: "Proxy Authentication Required",
408: "Request Timeout",
409: "Conflict",
410: "Gone",
411: "Length Required",
412: "Precondition Failed",
413: "Request Entity Too Large",
414: "Request-URI Too Long",
415: "Unsupported Media Type",
416: "Requested Range Not Satisfiable",
417: "Expectation Failed",
418: "I'm a Teapot", // (RFC 2324) http://tools.ietf.org/html/rfc2324
420: "Enhance Your Calm", // Returned by the Twitter Search and Trends API when the client is being rate limited
422: "Unprocessable Entity", // (WebDAV) (RFC 4918)
423: "Locked", // (WebDAV) (RFC 4918)
424: "Failed Dependency", // (WebDAV) (RFC 4918)
425: "Unordered Collection", // (RFC 3648)
426: "Upgrade Required", // (RFC 2817)
428: "Precondition Required",
429: "Too Many Requests", // Used for rate limiting
431: "Request Header Fields Too Large",
444: "No Response", // An nginx HTTP server extension. The server returns no information to the client and closes the connection (useful as a deterrent for malware).
449: "Retry With", // A Microsoft extension. The request should be retried after performing the appropriate action.
450: "Blocked By Windows Parental Controls",
499: "Client Closed Request",
500: "Internal Server Error",
501: "Not Implemented",
502: "Bad Gateway",
503: "Service Unavailable",
504: "Gateway Timeout",
505: "HTTP Version Not Supported",
506: "Variant Also Negotiates",
507: "Insufficient Storage",
508: "Loop Detected",
509: "Bandwidth Limit Exceeded",
510: "Not Extended",
511: "Network Authentication Required"
};
2015-09-18 12:14:46 +00:00
var NICE_USER_ERROR_MSG = "Something went wrong. Please retry in a few minutes and contact support if it continues to occur";
2015-09-22 14:46:28 +00:00
2015-02-10 19:41:24 +00:00
function plugin(options, imports, register) {
var connect = imports.connect;
var showStackTrace = false;
var frontdoor = require("frontdoor");
var statics = imports["connect.static"];
2015-09-22 14:46:28 +00:00
function isDev(mode) {
return /^(onlinedev|devel)$/.test(mode);
}
2015-02-10 19:41:24 +00:00
// serve index.html
statics.addStatics([{
path: __dirname + "/www",
mount: "/error_handler"
}]);
// make sure res.json is available
connect.useStart(frontdoor.middleware.jsonWriter());
2015-09-22 14:46:28 +00:00
function sanitizeErrorCode(code) {
code = parseInt(code, 10);
if (isNaN(code)) return 500;
if (code < 400) return 500;
2015-09-22 14:46:28 +00:00
return code;
}
2015-02-10 19:41:24 +00:00
connect.useError(function(err, req, res, next) {
if (typeof err == "string")
err = new errors.InternalServerError(err);
2015-02-10 19:41:24 +00:00
2015-09-22 14:46:28 +00:00
var statusCode = sanitizeErrorCode(err.code || err.status || res.statusCode);
var stack;
2015-02-10 19:41:24 +00:00
2015-09-22 14:46:28 +00:00
if (isDev(options.mode))
stack = err.stack || err.message || err.toString();
2015-02-10 19:41:24 +00:00
var accept = req.headers.accept || '';
2015-09-22 14:46:28 +00:00
if (/json/.test(accept)) {
2015-02-10 19:41:24 +00:00
var error = {
code: statusCode,
2015-02-10 19:41:24 +00:00
hostname: options.hostname,
2015-09-22 14:46:28 +00:00
scope: options.scope,
stack: stack
2015-02-10 19:41:24 +00:00
};
var allowedErrorKeys = [
2015-10-05 14:43:31 +00:00
"message", "projectState", "premium", "retryIn", "progress",
2015-12-21 14:28:47 +00:00
"oldHost", "blocked", "className", "errors"
];
allowedErrorKeys.forEach(function(key) {
if (err.hasOwnProperty(key))
error[key] = err[key];
});
2015-02-10 19:41:24 +00:00
try {
JSON.stringify(error);
2015-09-22 14:46:28 +00:00
}
catch (e) {
console.error("Cannot send error as JSON: ", error);
2015-09-18 12:14:46 +00:00
error.message = NICE_USER_ERROR_MSG;
2015-09-18 11:02:50 +00:00
error.scope = null;
}
2015-09-22 14:46:28 +00:00
return res.json({
error: error
}, null, statusCode);
2015-02-10 19:41:24 +00:00
}
2015-09-22 14:46:28 +00:00
var path = errorPages[statusCode] ? __dirname + "/views/error-" + statusCode + ".html.ejs" : __dirname + "/views/error.html.ejs";
res.setHeader('Content-Type', 'text/html; charset=utf-8');
2015-09-22 14:46:28 +00:00
res.render(path, {
title: statusCodes[statusCode] || NICE_USER_ERROR_MSG,
scope: options.scope || "",
showStackTrace: showStackTrace,
stack: stack,
2015-09-22 14:46:28 +00:00
statusCode: statusCode,
error: err.toString()
}, next);
2015-02-10 19:41:24 +00:00
});
register(null, {
"connect.error": {}
});
}