Get support for Ilshidur/node-mercure

If you're new to LTH, please see our FAQ for more information on what it is we do.

Support Options

Unfortunately, there are currently no active helpers for this repository on the platform. Until they become available, we reccomend the following actions:

View Open Issues

Take a look to see if anyone else has experienced the same issue as you and if they managed to solve it.

Open an Issue

Make sure to read any relevant guidelines for opening issues on this repo before posting a new issue.

Sponsor directly

Check out the page and see if there are any options to sponsor this project or it's developers directly.

Ilshidur/node-mercure

mercure

Mercure Hub & Publisher implemented in Node.js.

stability-beta Build Status

npm version Known Vulnerabilities dependency status devdependency status downloads Code Climate

NPM

Note: this npm package has been transfered for a new project by the initial owner, which serves a totally different purpose. This new version is an implementation of the Mercure protocol. The previous mercure package had 1 release (0.0.1) and served as a file downloader. You can still access it: https://www.npmjs.com/package/mercure/v/0.0.1. Please make sure to lock this version in your package.json file, as the new versions will begin at 0.0.2 and will keep following the semver versioning.

TODOs

  • CORS
  • Hearthbeat mechanism (https://github.com/dunglas/mercure/pull/53)
  • Docker image (iso with official image)
  • Prometheus metrics exporter:
    • Subscribers count
    • Events count / size (in Bytes), per publisher
    • Publishers IPs
    • Instances count
  • hub.on('connect') listeners
  • Events database
  • Export authorization.js mechanism
  • Discovery helpers
  • Handle Forwarded and X-Forwarded-For headers (related issue)
  • Provide a Socket.io adapter (see this thread)
  • Allow the dev to pass an URL in the Publisher contructor
  • Publisher: allow the user to specify a JWT key and the claims instead of a JWT
  • Publisher: getters like get host(), port, protocol...
  • Increase code quality score
  • JSDoc
  • Logging
  • Unit tests
  • Find a way to clear Redis if the process gets interrupted
  • Benchmarks

State

This is a beta version. This has not fully been tested in production yet.

This implementation does not reflect the latest specification since they got changed. I don't recommend to use this module.

Requirements

  • node.js >= 11.7.0
  • Redis (optional)

Features

  • 100% implementation of the protocol
  • Events asymmetric encryption
  • Easy integration to any existing app using http.Server or express
  • Redis-based clustering support
  • Inventory of all open connections stored in Redis, per node process
  • Kill switch

Future improvements

  • Implement as a lambda function ?

Installation

npm install mercure --save

Usage

This library provides 3 components: a Hub, a Server and a Publisher:

Classes preview

Simple hub

-> Documentation

The Hub class is the core component that uses a simple http.Server instance. An existing instance can be provided to the Hub, thus the Hub will use it instead of creating a new one.

Use case: implanting the hub on an existing http.Server app, without the need to handle external publishers (only the app does the publishing).

It handles:

  • the SSE connections
  • the events database
  • the authorization mechanism
  • events related to the Hub activity
const http = require('http');
const { Hub } = require('mercure');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('200');
});

const hub = new Hub(server, {
  jwtKey: '!UnsecureChangeMe!',
  path: '/.well-known/mercure',
});

hub.listen(3000);

Hub server

-> Documentation

The Server is built upon the Hub component. It creates a new Express instance and allows external publishers to POST an event to the hub.

Use case: implanting he hub on an new application that is meant to accept external publishers, with no other HTTP server ... or one listening on a different port.

It handles everything the Hub does, plus:

  • a freshly created Express instance, built upon the Hub's http.Server (middlewares can be applied to enhance security)
  • external publishers (POST requests)
const { Server } = require('mercure');

const server = new Server({
  jwtKey: '!UnsecureChangeMe!',
  path: '/.well-known/mercure',
});

server.listen(3000);

Because the Server leverages Express, it is possible to add middlewares in front of the internal Hub middleware:

const compression = require('compression');

class SecuredHubServer extends Server {
  configure() {
    this.app.use(compression());
  }
}

const server = new SecuredHubServer(...);

Publisher

-> Documentation

It can be created in different ways:

  • using an existing Hub instance (when the app is meant to be THE ONLY publisher)
  • using an existing Server instance (when the app is meant to be a publisher)
  • using configuration: host, port... (when the publisher and the hub are distant)

It handles:

  • Message publication to the Hub
  • Message encryption (optional)
const { Publisher } = require('mercure');

const publisher = new Publisher({
  protocol: 'https', // or 'http', but please don't.
  host: 'example.com',
  port: 3000,
  path: '/.well-known/mercure',
  jwt: 'PUBLISHER_JWT',
});

// Payload to send to the subscribers.
const data = {
  '@id': 'http://localhost:3000/books/666.jsonld',
  hello: 'world',
};

await publisher.publish(
  ['https://example.com:3000/books/666.jsonld'], // Topics.
  JSON.stringify(data),
);

API

API docs can be found in the docs/API.md file.

Encrypting the datas

In certain cases, the Mercure hub can be hosted by a third-party host. You don't really want them to "sniff" all your cleartext messages. To make the Publisher => Hub => Subscriber flow fully encrypted, it is required that the Publisher sends encrypted data.

To achieve this, the Publisher#useEncryption() method will activate messages encryption. Thus, the Hub will not be able to access your private datas:

const crypto = require('crypto');
const util = require('util');

const publisher = new Publisher({
  // ...
});

const data = { message: 'TOP SECRET DATAS' };
const { privateKey } = await util.promisify(crypto.generateKeyPair)('rsa', {
  modulusLength: 4096,
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem',
  },
});

// Start encrypting the events.
await publisher.useEncryption({
  rsaPrivateKey: privateKey,
});

// Will send encrypted datas.
await publisher.publish(
  [...], // Topics.
  JSON.stringify(data),
);

Decrypting:

const jose = require('node-jose');

const encryptedData = 'ENCRYPTED DATA';
const decrypted = await jose.JWE.createDecrypt(publisher.keystore).decrypt(encryptedData);

console.log(decrypted.plaintext.toString());

Kill switch

In case the hub must urgently close all connections (e.g.: in case of compromission of the JWT key), a kill switch is available:

await hub.killSwitch();

The new JWT Key will be output to stdout.

License

GNU GENERAL PUBLIC LICENSE v3.

Our Mission

We want to make open source more sustainable. The entire platform was born from this and everything we do is in aid of this.

Interesting Articles

Thank you for checking out LiveTechHelper |
2025 © lth-dev incorporated

p-e622a1a2