UNPKG

@steelbreeze/broker

Version:

Lightweight publish and subscribe using Server-Sent Events for node and express

62 lines (61 loc) 2.68 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var express_1 = require("express"); // find or create a topic given its name function getTopic(topics, topic) { return topics[topic] || (topics[topic] = { lastEventId: -1, data: undefined, subscribers: [] }); } // write a single message to a client function sendEvent(client, eventId, data) { setImmediate(function (client, eventId, data) { client.write("id:" + eventId + "\ndata:" + data + "\n\n"); }, client, eventId, data); } /** * Creates an instance of a message broker server. * Many message broker servers may be created, each bound to a different base url. * @param cacheLastMessage When true, subscribers will receive the last message upon subscrition. * @returns Returns an express Router for use within an express application. */ function server(cacheLastMessage) { if (cacheLastMessage === void 0) { cacheLastMessage = false; } var router = express_1.Router(); var topics = {}; // GET method is used to subscribe by EventSource clients router.get('*', function (req, res) { var topic = getTopic(topics, req.url); // remove the subscription when the connection closes req.on('close', function () { topic.subscribers.splice(topic.subscribers.indexOf(res), 1); }); // create the subscription topic.subscribers.push(res); // set the response headers to specify this is an event stream res.set({ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); // update the client with the last message if required if (cacheLastMessage && topic.data) { sendEvent(res, topic.lastEventId, topic.data); } }); router.post('*', function (req, res) { var topic = getTopic(topics, req.url); var body = []; // read the post body req.on('data', function (chunk) { body.push(chunk); }); req.on('end', function () { // update the topic with the new event details topic.data = Buffer.concat(body).toString(); topic.lastEventId = (topic.lastEventId === Number.MAX_VALUE ? -1 : topic.lastEventId) + 1; // queue dispatch of event to all current subscribers topic.subscribers.forEach(function (subscriber) { sendEvent(subscriber, topic.lastEventId, topic.data); // NOTE: as we have just set topic.data we know it's not undefined }); }); // send response to publisher res.sendStatus(200); }); return router; } exports.server = server;