UNPKG

sqsd-handler

Version:

Express middleware for handling SQS messages in AWS ElasticBeanstalk worker-tier apps.

157 lines (142 loc) 6.11 kB
(function (sqsdHandler) { "use strict"; var _ = require("underscore"); var express = require("express"); var Promise = require("bluebird"); function create(defaultHandlerFunc) { if (defaultHandlerFunc && (typeof defaultHandlerFunc !== "function")) { throw new Error("The argument to handle() must be a function"); } function messageProcessor (req, res, next) { /*jshint validthis: true */ var config = this; var message = req.msg; var handlerFunc = config.defaultHandler; if (message.taskName && config.tasks[message.taskName]) { var taskHandlerFunc = config.tasks[message.taskName]; handlerFunc = taskHandlerFunc; } if (message.sns && config.snsHandler) { handlerFunc = config.snsHandler; } if (handlerFunc == config.defaultHandler && config.filterHandlers.length > 0) { config.filterHandlers.forEach(function (handler) { if (_.isMatch(message.payload, handler.filter)) { handlerFunc = handler.handlerFunc; } }); } var handlePromise = Promise .try(function () { message.response = message.response || {}; message.response.status = message.response.status || 200; message.response.text = message.response.text || ""; return handlerFunc(message) || message; }) .catch(function (exception) { message.response.status = 500; if (config.errorHandler) { var errorHandlerPromise = Promise.try(function () { return config.errorHandler(message, exception) || message; }); return errorHandlerPromise; } }) .finally(function () { var responseStatus = message.response.status || 200; var responseText = message.response.text.toString(); res.status(responseStatus).send(responseText); if (config.logHandler) { return config.logHandler(message); } }); } function RouteConfig (defaultHandler) { this.tasks = {}; this.filterHandlers = []; this.snsHandler = null; this.errorHandler = null; this.logHandler = null; this.defaultHandler = defaultHandler || function () {}; } var routeConfig = new RouteConfig(defaultHandlerFunc); var routeConfigMessageProcessor = messageProcessor.bind(routeConfig); var router = express.Router(); var messageRouter = router.post("/", sqsdMessageParser, snsMessageParser, routeConfigMessageProcessor); messageRouter.task = function (taskName, taskHandlerFunc) { var config = this; config.tasks[taskName] = taskHandlerFunc; }.bind(routeConfig); messageRouter.filter = function (filterObj, handlerFunc) { var config = this; config.filterHandlers.push({"filter": filterObj, "handlerFunc": handlerFunc}); }.bind(routeConfig); messageRouter.sns = function (handlerFunc) { var config = this; config.snsHandler = handlerFunc; }.bind(routeConfig); messageRouter.error = function (errorHandlerFunc) { var config = this; config.errorHandler = errorHandlerFunc; }.bind(routeConfig); messageRouter.log = function (logHandlerFunc) { var config = this; config.logHandler = logHandlerFunc; }.bind(routeConfig); return messageRouter; } function sqsdMessageParser(req, res, next){ var userAgent = req.headers["user-agent"]; req.setEncoding("utf8"); req.msg = { "body": "", "msgid": req.get("x-aws-sqsd-msgid"), "receiveCount": req.get("x-aws-sqsd-receive-count"), "firstReceivedAt": req.get("x-aws-sqsd-first-received-at"), "sentAt": req.get("x-aws-sqsd-sent-at"), "scheduledAt": req.get("x-aws-sqsd-scheduled-at"), "path": req.get("x-aws-sqsd-path"), "senderId": req.get("x-aws-sqsd-sender-id"), "queue": req.get("x-aws-sqsd-queue"), "taskName": req.get("x-aws-sqsd-taskname"), "userAgent": userAgent, "response": {} }; _.each(req.headers, function (value, key) { if (key.indexOf("x-aws-sqsd-attr-") != -1) { req.msg.attributes = req.msg.attributes || {}; var attribName = key.substr("x-aws-sqsd-attr-".length); req.msg.attributes[attribName] = value; } }); req.on("data", function (chunk) { req.msg.body += chunk; }); req.on("end", function () { if (req.is("application/json") && req.msg.body) { try { req.msg.payload = JSON.parse(req.msg.body); next(); } catch (jsonParseError) { next(jsonParseError); } } else { next(); } }); } function snsMessageParser(req, res, next) { var msg = req.msg; if (msg && msg.payload && msg.payload.Type && msg.payload.Type === "Notification" && msg.payload.Message) { var messageText = msg.payload.Message; if (messageText) { var sns = JSON.parse(messageText); msg.sns = sns; } } next(); } sqsdHandler.sqsdMessageParser = sqsdMessageParser; sqsdHandler.snsMessageParser = snsMessageParser; sqsdHandler.create = create; })(module.exports);