use response.js for all responses

results in:
1) less duplicated code
2) default response headers being used at all times
3) *all* requests being logged properly

- adds documentation for result.code
- allows using result.code to override HTTP 500
- uses response.js for too-busy, server error, method not allowed
This commit is contained in:
jomo 2016-11-07 03:59:07 +01:00
parent 6f1c414a4a
commit f1f3ba6709
3 changed files with 31 additions and 28 deletions

View File

@ -25,6 +25,7 @@ var silent_errors = ["ETIMEDOUT", "ESOCKETTIMEDOUT", "ECONNRESET", "EHOSTUNREACH
// * type: a valid Content-Type for the body, defaults to "text/plain" // * type: a valid Content-Type for the body, defaults to "text/plain"
// * hash: image hash, required when body is an image // * hash: image hash, required when body is an image
// * err: a possible Error // * err: a possible Error
// * code: override HTTP response code when status is < 0
module.exports = function(request, response, result) { module.exports = function(request, response, result) {
// These headers are the same for every response // These headers are the same for every response
var headers = { var headers = {
@ -32,7 +33,7 @@ module.exports = function(request, response, result) {
"Cache-Control": "max-age=" + config.caching.browser, "Cache-Control": "max-age=" + config.caching.browser,
"Response-Time": Date.now() - request.start, "Response-Time": Date.now() - request.start,
"X-Request-ID": request.id, "X-Request-ID": request.id,
"Access-Control-Allow-Origin": "*" "Access-Control-Allow-Origin": "*",
}; };
response.on("close", function() { response.on("close", function() {
@ -87,7 +88,7 @@ module.exports = function(request, response, result) {
} else if (result.status === -1) { } else if (result.status === -1) {
// 500 responses shouldn't be cached // 500 responses shouldn't be cached
headers["Cache-Control"] = "private, max-age=0, no-cache"; headers["Cache-Control"] = "private, max-age=0, no-cache";
response.writeHead(500, headers); response.writeHead(result.code || 500, headers);
} else { } else {
if (result.body) { if (result.body) {
headers.Etag = etag; headers.Etag = etag;

View File

@ -23,13 +23,13 @@ function handle_default(img_status, userId, size, def, req, err, callback) {
callback({ callback({
status: img_status, status: img_status,
redirect: newUrl, redirect: newUrl,
err: err err: err,
}); });
} else { } else {
callback({ callback({
status: img_status, status: img_status,
redirect: def, redirect: def,
err: err err: err,
}); });
} }
} else { } else {
@ -44,7 +44,7 @@ function handle_default(img_status, userId, size, def, req, err, callback) {
body: image, body: image,
type: "image/png", type: "image/png",
hash: def, hash: def,
err: resize_err || err err: resize_err || err,
}); });
}); });
} }
@ -62,7 +62,7 @@ module.exports = function(req, callback) {
callback({ callback({
status: -2, status: -2,
body: "Invalid Path", body: "Invalid Path",
code: 404 code: 404,
}); });
return; return;
} }
@ -73,13 +73,13 @@ module.exports = function(req, callback) {
// https://tools.ietf.org/html/rfc4918#page-78 // https://tools.ietf.org/html/rfc4918#page-78
callback({ callback({
status: -2, status: -2,
body: "Invalid Size" body: "Invalid Size",
}); });
return; return;
} else if (!helpers.id_valid(userId)) { } else if (!helpers.id_valid(userId)) {
callback({ callback({
status: -2, status: -2,
body: "Invalid UserID" body: "Invalid UserID",
}); });
return; return;
} }
@ -101,7 +101,7 @@ module.exports = function(req, callback) {
body: image, body: image,
type: "image/png", type: "image/png",
err: err, err: err,
hash: hash hash: hash,
}); });
} else { } else {
handle_default(status, userId, size, def, req, err, callback); handle_default(status, userId, size, def, req, err, callback);

View File

@ -16,7 +16,7 @@ var routes = {
avatars: require("./routes/avatars"), avatars: require("./routes/avatars"),
skins: require("./routes/skins"), skins: require("./routes/skins"),
renders: require("./routes/renders"), renders: require("./routes/renders"),
capes: require("./routes/capes") capes: require("./routes/capes"),
}; };
// serves assets from lib/public // serves assets from lib/public
@ -28,7 +28,7 @@ function asset_request(req, callback) {
callback({ callback({
body: data, body: data,
type: mime.lookup(filename), type: mime.lookup(filename),
err: err err: err,
}); });
}); });
} else { } else {
@ -70,60 +70,62 @@ function requestHandler(req, res) {
toobusy.maxLag(200); toobusy.maxLag(200);
if (toobusy() && !process.env.TRAVIS) { if (toobusy() && !process.env.TRAVIS) {
res.writeHead(503, { response(req, res, {
"Content-Type": "text/plain" status: -1,
body: "Server is over capacity :/",
err: "Too busy",
code: 503,
}); });
res.end("Server is over capacity :/");
logging.error("Too busy:", req.id, 503, Date.now() - req.start + "ms", "(error)");
return; return;
} }
if (req.method === "GET" || req.method === "HEAD") { if (req.method === "GET" || req.method === "HEAD") {
try { try {
switch (local_path) { switch (local_path) {
case "": case "":
routes.index(req, function(result) { routes.index(req, function(result) {
response(req, res, result); response(req, res, result);
}); });
break; break;
case "avatars": case "avatars":
routes.avatars(req, function(result) { routes.avatars(req, function(result) {
response(req, res, result); response(req, res, result);
}); });
break; break;
case "skins": case "skins":
routes.skins(req, function(result) { routes.skins(req, function(result) {
response(req, res, result); response(req, res, result);
}); });
break; break;
case "renders": case "renders":
routes.renders(req, function(result) { routes.renders(req, function(result) {
response(req, res, result); response(req, res, result);
}); });
break; break;
case "capes": case "capes":
routes.capes(req, function(result) { routes.capes(req, function(result) {
response(req, res, result); response(req, res, result);
}); });
break; break;
default: default:
asset_request(req, function(result) { asset_request(req, function(result) {
response(req, res, result); response(req, res, result);
}); });
} }
} catch(e) { } catch(e) {
var error = JSON.stringify(req.headers) + "\n" + e.stack; var error = JSON.stringify(req.headers) + "\n" + e.stack;
logging.error(req.id + "Error:", error); response(req, res, {
res.writeHead(500, { status: -1,
"Content-Type": "text/plain" body: config.server.debug_enabled ? error : "Internal Server Error",
err: error,
}); });
res.end(config.server.debug_enabled ? error : "Internal Server Error");
} }
} else { } else {
res.writeHead(405, { response(req, res, {
"Content-Type": "text/plain" status: -2,
body: "Method Not Allowed",
code: 405,
}); });
res.end("Method Not Allowed");
} }
} }