diff --git a/aedes.js b/aedes.js index 36fd056a..376e7b0d 100644 --- a/aedes.js +++ b/aedes.js @@ -25,6 +25,7 @@ const defaultOptions = { authorizePublish: defaultAuthorizePublish, authorizeSubscribe: defaultAuthorizeSubscribe, authorizeForward: defaultAuthorizeForward, + preUnsubscribe: defaultPreUnsubscribe, published: defaultPublished, trustProxy: false, trustedProxies: [], @@ -69,6 +70,7 @@ function Aedes (opts) { this.authorizePublish = opts.authorizePublish this.authorizeSubscribe = opts.authorizeSubscribe this.authorizeForward = opts.authorizeForward + this.preUnsubscribe = opts.preUnsubscribe this.published = opts.published this.decodeProtocol = opts.decodeProtocol @@ -337,6 +339,8 @@ function defaultAuthorizeForward (client, packet) { return packet } +function defaultPreUnsubscribe (client, packet) { } + function defaultPublished (packet, client, callback) { callback(null) } diff --git a/docs/Aedes.md b/docs/Aedes.md index afeaa0e8..957fbde5 100644 --- a/docs/Aedes.md +++ b/docs/Aedes.md @@ -29,6 +29,7 @@ - [Handler: authorizePublish (client, packet, callback)](#handler-authorizepublish-client-packet-callback) - [Handler: authorizeSubscribe (client, subscription, callback)](#handler-authorizesubscribe-client-subscription-callback) - [Handler: authorizeForward (client, packet)](#handler-authorizeforward-client-packet) + - [Handler: preUnsubscribe (client, packet)](#handler-preunsubscribe-client-packet) - [Handler: published (packet, client, callback)](#handler-published-packet-client-callback) ## new Aedes([options]) / new Aedes.Server([options]) @@ -386,6 +387,28 @@ aedes.authorizeForward = function (client, packet) { } ``` +## Handler: preUnsubscribe (client, packet) + +- client: [``](./Client.md) +- packet: `` & [`UNSUBSCRIBE`][UNSUBSCRIBE] + +Invoked when a client unsubscribes from topics. Just like `authorizeSubscribe`, this function allows modifying the topics before executing the unsubscribe. This may be needed in cases where topics were modified in authorizeSubscribe. For example: + +```js +aedes.authorizeSubscribe = (client, subscription, callback) => { + // overwrite subscription: force client to its namespace + subscription.topic = `/${client.id}/${subscription.topic}`; + callback(null, subscription); +} + +aedes.preUnsubscribe = (client, packet) => { + // overwrite unsubscriptions: force client to its namespace + for (let i in packet.unsubscriptions) { + packet.unsubscriptions[i] = `/${client.id}/${packet.unsubscriptions[i]}`; + } +} +``` + ## Handler: published (packet, client, callback) - packet: `` & [`PUBLISH`][PUBLISH] @@ -397,6 +420,7 @@ same as [`Event: publish`](#event-publish), but provides a backpressure function [CONNECT]: https://github.com/mqttjs/mqtt-packet#connect [CONNACK]: https://github.com/mqttjs/mqtt-packet#connack [SUBSCRIBE]: https://github.com/mqttjs/mqtt-packet#subscribe +[UNSUBSCRIBE]: https://github.com/mqttjs/mqtt-packet#unsubscribe [PINGREQ]: https://github.com/mqttjs/mqtt-packet#pingreq [PUBLISH]: https://github.com/mqttjs/mqtt-packet#publish [PUBREL]: https://github.com/mqttjs/mqtt-packet#pubrel diff --git a/lib/handlers/unsubscribe.js b/lib/handlers/unsubscribe.js index de8b4cb7..784713d6 100644 --- a/lib/handlers/unsubscribe.js +++ b/lib/handlers/unsubscribe.js @@ -16,6 +16,10 @@ function UnsubscribeState (client, packet, finish) { function handleUnsubscribe (client, packet, done) { const broker = client.broker + if (broker.preUnsubscribe) { + broker.preUnsubscribe(client, packet) + } + const unsubscriptions = packet.unsubscriptions let err