How can I get RabbitMQ exchange name inside a handler

164 views
Skip to first unread message

Erez Bar-Tal

unread,
Oct 1, 2015, 2:04:07 AM10/1/15
to Particular Software
Hi,
We are using NSB + Rabbit. We have many clients (embedded devices) that are not using NSB and sending messages to different exchanges. For security reasons each embedded device has its own exchange. All exchanges are binded to the same queue. This queue is NSB endpoint where .NET code consumes in several handlers.

We are distinguishing the clients by the exchange name.
I need to know the exchange name inside the handler. For security reasons I don't want the client to supply this information. How can I retrieve it? I guess I need to extend NSB because exchange is not common to all brokers.

With Rabbit code it is very easy to do:
var consumer = new EventingBasicConsumer(ch);
                        consumer.Received += (model, ea) =>
                        {
                            var body = ea.Body;
                            string exchangeName = ea.Exchange;
                            var message = Encoding.UTF8.GetString(body);
                            Console.WriteLine(" [x] Received {0}", message);
                        };


Thanks in advance
Erez

Erez Bar-Tal

unread,
Oct 1, 2015, 10:26:22 AM10/1/15
to Particular Software
Hi,
Another option is to force the client to send the correct user_id as described in this link: https://www.rabbitmq.com/validated-user-id.html
The problem is that NSB only transfer the Rabbit headers and not the properties of Rabbit BasicDeliverEventArgs class.
Is there any way to get the properties, especially the user_id and/or Exchange at NSB handler?

simon.cropp

unread,
Oct 1, 2015, 11:53:19 PM10/1/15
to Particular Software
Officially: No it is not supported. you could raise a feature request here https://github.com/Particular/NServiceBus.RabbitMQ/issues or your can run a forked version of the nsb.rabbit transport with your own customisations

Unofficially you can leverage the CustomMessageIdStrategy feature to monkey patch the current exchange back into the headers.

Add this class

public static class ExchangeCapture
{
    public static string InjectExchange(BasicDeliverEventArgs deliverEventArgs)
    {
        var properties = deliverEventArgs.BasicProperties;
        properties.Headers["CurrentExchange"] = deliverEventArgs.Exchange;

        if (!properties.IsMessageIdPresent() || string.IsNullOrWhiteSpace(properties.MessageId))
        {
            throw new InvalidOperationException("A non empty message_id property is required when running NServiceBus on top of RabbitMq. If this is a interop message please make sure to set the message_id property before publishing the message");
        }

        return properties.MessageId;
    }
}

Then in your bus config add

        busConfiguration.UseTransport<RabbitMQTransport>()
            .CustomMessageIdStrategy(ExchangeCapture.InjectExchange)

Then in your handler you can do 

public class MyHandler : IHandleMessages<MyMessage>
{
    IBus bus;
    static ILog logger = LogManager.GetLogger(typeof(MyHandler));

    public MyHandler(IBus bus)
    {
        this.bus = bus;
    }

    public void Handle(MyMessage message)
    {
        logger.Info("Hello from MyHandler");
        logger.Info("Current exchange:" + bus.CurrentMessageContext.Headers["CurrentExchange"]);
    }
}

simon.cropp

unread,
Oct 1, 2015, 11:54:25 PM10/1/15
to Particular Software

Erez Bar-Tal

unread,
Oct 6, 2015, 9:35:18 AM10/6/15
to Particular Software
Thanks,
It is working.
I also opened an issue to support it. #103
Reply all
Reply to author
Forward
0 new messages