├── .gitignore ├── README.md ├── config.json ├── package.json ├── index.js └── rabbit.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rabbit-Mailconsumer 2 | 3 | RabbitMQ consumer, posts received data to an URL 4 | 5 | ## Usage 6 | 7 | 1. Update config.json 8 | 2. Run *node index.js* -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "rabbit": { 3 | "url": "amqp://user:pass@host", 4 | "exchange": "mail.parsed" 5 | }, 6 | "targetUrl": "http://blog.node.ee/postreceive.php?api_token=12345" 7 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "rabbit-mail-consumer", 4 | "version": "0.1.0", 5 | "description": "RabbitMQ consumer to post received data", 6 | "main": "index.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": "", 11 | "author": "", 12 | "license": "BSD", 13 | "dependencies":{ 14 | "amqp": "git://github.com/postwait/node-amqp.git" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var amqp = require("amqp"), 2 | config = require("./config.json"), 3 | rabbit = require("./rabbit"), 4 | rabbitQueue = rabbit.createQueue("", "queue"), 5 | http = require("http"), 6 | urllib = require("url"); 7 | 8 | rabbitQueue.on("message", function(message, callback){ 9 | var url = urllib.parse(config.targetUrl, true, true); 10 | 11 | message = new Buffer(JSON.stringify(message), "utf-8"); 12 | 13 | url.method = "POST"; 14 | 15 | url.headers = { 16 | "Content-Type": "application/json", 17 | "Content-Length": message.length 18 | }; 19 | 20 | var req = http.request(url, function(res) { 21 | console.log('STATUS: ' + res.statusCode); 22 | console.log('HEADERS: ' + JSON.stringify(res.headers)); 23 | res.setEncoding('utf8'); 24 | res.on('data', function (chunk) { 25 | console.log('BODY: ' + chunk); 26 | }); 27 | res.on("end", function(){ 28 | console.log("Request done"); 29 | rabbitQueue.shift(); 30 | }); 31 | }); 32 | 33 | req.on('error', function(e) { 34 | console.log('problem with request: ' + e.message); 35 | }); 36 | 37 | // write data to request body 38 | req.end(message); 39 | 40 | }); 41 | 42 | process.on("SIGTERM", function(){ 43 | console.log("Exited on SIGTERM"); 44 | process.exit(0); 45 | }); 46 | 47 | process.on("SIGINT", function(){ 48 | console.log("Exited on SIGINT"); 49 | process.exit(0); 50 | }); 51 | 52 | process.on("uncaughtException", function(err) { 53 | console.log(err.stack); 54 | process.exit(1); 55 | }); 56 | 57 | var url = urllib.parse(config.targetUrl); -------------------------------------------------------------------------------- /rabbit.js: -------------------------------------------------------------------------------- 1 | var config = require("./config.json"), 2 | amqp = require('amqp'), 3 | rabbit = amqp.createConnection({url: config.rabbit.url}), 4 | rabbitQueues = [], 5 | rabbitConnected = false, 6 | Stream = require('stream').Stream, 7 | utillib = require('util'); 8 | 9 | module.exports.createQueue = function(interfaceName, interfaceType){ 10 | return new RabbitQueue(interfaceName, interfaceType); 11 | } 12 | 13 | function RabbitQueue(interfaceName, interfaceType){ 14 | Stream.call(this); 15 | this.queue = [], 16 | this.interfaceName = interfaceName || ""; 17 | this.interfaceType = (interfaceType || "exchange").toString().trim().toLowerCase(); 18 | this.processing = false; 19 | this.interface = false; 20 | this.ctag = false; 21 | rabbitQueues.push(this); 22 | if(rabbitConnected){ 23 | this.openInterface(); 24 | } 25 | } 26 | utillib.inherits(RabbitQueue, Stream); 27 | 28 | RabbitQueue.prototype.openInterface = function(){ 29 | if(this.interfaceType == "exchange"){ 30 | rabbit.exchange(this.interfaceName, {passive: true}, (function (exchange) { 31 | console.log('Exchange ' + exchange.name + ' is open'); 32 | this.interface = exchange; 33 | this.process(); 34 | }).bind(this)); 35 | }else{ 36 | var queueOptions = {}; 37 | if(this.interfaceName){ 38 | queueOptions = {passive: true}; 39 | }else{ 40 | queueOptions = {exclusive: true, durable: false, autoDelete: true}; 41 | } 42 | rabbit.queue(this.interfaceName, queueOptions, (function(queue){ 43 | queue.bind(config.rabbit.exchange, "#"); 44 | console.log('Queue ' + queue.name + ' is open for subscription'); 45 | this.interface = queue; 46 | this.interface.subscribe({ack: true}, this.subscription.bind(this)).addCallback((function(ok){ 47 | this.ctag = ok.consumerTag; 48 | }).bind(this)); 49 | }).bind(this)); 50 | } 51 | } 52 | 53 | RabbitQueue.prototype.subscription = function(message, headers, deliveryInfo){ 54 | console.log("Received message from " + this.interfaceName, JSON.stringify({message: message, envelope: deliveryInfo})); 55 | this.emit("message", message, headers, deliveryInfo); 56 | } 57 | 58 | RabbitQueue.prototype.shift = function(){ 59 | if(this.interface && this.interface.shift){ 60 | this.interface.shift(); 61 | } 62 | } 63 | 64 | RabbitQueue.prototype.process = function(forced){ 65 | if(this.processing && !forced){ 66 | return; 67 | } 68 | 69 | if(!this.interface || !this.queue.length){ 70 | this.processing = false; 71 | return; 72 | } 73 | this.processing = true; 74 | 75 | var message = this.queue.shift(); 76 | if(!message){ 77 | return process.nextTick(this.process.bind(this, true)); 78 | } 79 | 80 | this.interface.publish(message[0] || "mail", JSON.stringify(message[1]), {contentType: 'application/json', deliveryMode: 2}); 81 | 82 | process.nextTick(this.process.bind(this, true)); 83 | } 84 | 85 | RabbitQueue.prototype.publish = function(key, data){ 86 | if(!data && typeof key == "object"){ 87 | data = key; 88 | key = undefined; 89 | } 90 | console.log("Publish new message", JSON.stringify(data)) 91 | this.queue.push([key, data]); 92 | this.process(); 93 | } 94 | 95 | rabbit.on("ready", function(){ 96 | rabbitConnected = true; 97 | rabbitReconnectCounter = 0; 98 | 99 | console.log("Connected to rabbit"); 100 | 101 | rabbitQueues.forEach(function(queue){ 102 | if(rabbitConnected){ 103 | queue.openInterface(); 104 | } 105 | }); 106 | }); 107 | 108 | rabbit.on("close", function () { 109 | rabbitConnected = false; 110 | rabbitQueues.forEach(function(queue){ 111 | if(queue.ctag){ 112 | queue.interface.unsubscribe(queue.ctag); 113 | } 114 | queue.interface = false; 115 | }); 116 | 117 | console.log("Connection to rabbit closed"); 118 | 119 | setTimeout(function(){ 120 | console.log("Reconnecting to rabbit"); 121 | rabbit = amqp.createConnection({url: config.rabbit.url}); 122 | }, (++rabbitReconnectCounter)*1000); 123 | }); 124 | 125 | rabbit.on("error", function(err){ 126 | console.log(err.message || err, err.stack || ""); 127 | }); --------------------------------------------------------------------------------