Skip to main content

Mapping to NATS

Every message an MQTT or AMQP client sends is an ordinary NATS message on a subject. MQTT, AMQP and NATS clients that use the same subject see each other's messages. This page shows how topics and addresses become subjects and how message metadata becomes NATS headers. It also shows how a NATS client exchanges messages with MQTT and AMQP clients.

The examples below use these names for one subject:

ClientName
MQTTtopic orders/eu
AMQPaddress orders.eu
NATSsubject orders.eu

MQTT topics​

The gateway converts each topic level to a subject token. It uses the same conversion as the MQTT server in nats-server.

MQTTNATSRule
plant/line1/tempplant.line1.temp/ becomes .
spBv1.0/G1spBv1//0.G1. becomes //
plant/+/tempplant.*.temp+ becomes *
plant/#plant.> and plant# becomes >, plus the parent level
#>
/plant/.plantAn empty first level becomes /
plant/plant./An empty last level becomes /
plant//tempplant./.tempAn empty middle level becomes /
$share/g1/plant/+plant.*, queue group g1A shared subscription is a NATS queue subscription

A subject converts back to a topic by the reverse rules. * and > in a subject that a NATS client published stay as they are in the topic.

Rules:

  • The gateway refuses a topic or filter that contains whitespace or DEL.
  • The gateway refuses a filter with a level of only * or >, because NATS reads that level as a wildcard.
  • A filter that starts with + or # does not match topics that start with $.
  • The gateway does not deliver a message to MQTT clients if its subject holds + or #. No MQTT topic can hold these characters.
  • Your NATS permissions decide whether a client can reach a $ subject, such as $JS.> or $SYS.>. The gateway does not treat them differently.

AMQP addresses​

An AMQP address is the NATS subject, with no conversion.

AMQPNATS
Target orders.euPublishes to orders.eu
Target orders/euPublishes to the one-token subject orders/eu, which no MQTT topic reaches
Source orders.* or orders.>Reads with the wildcard
Null target (anonymous relay)Publishes to the to of each message
Dynamic source or targetA new inbox subject, for replies
Source orders.eu::billingReads from the stream consumer billing, which an operator made

Rules:

  • A target cannot contain wildcards, empty tokens or whitespace.
  • An unsettled receiver on a wildcard source needs one binding that covers the whole source. The gateway refuses a source that spans streams, or that mixes stored and unstored subjects, unless the receiver asks for presettled delivery.
  • An operator queue (<address>::<queue>) must be a pull consumer with explicit acks and no max_bytes, on the stream that stores the address. Its filter subjects must match the address. Otherwise the gateway refuses the receiver: amqp:not-found when the queue does not exist, and amqp:not-implemented or amqp:precondition-failed when it does not fit.
  • The gateway refuses sends to, and receivers on, its admin subjects under $MQGW.admin.>.

Routes​

A route puts message properties in the subject. With mqtt.routes or amqp.routes, a send to the route's subject goes to a subject that the route's template builds. MQTT v5 User Properties and AMQP application properties fill the template. The gateway does not route MQTT 3.1.1 publishes.

TemplateSend toPropertyNATS subject
orders.{region}ordersregion=euorders.eu
orders.{region}ordersregion=eu westorders.eu%20west
orders.{region}ordersNoneThe gateway refuses the message

Rules:

  • The gateway percent-encodes ., %, /, +, #, whitespace and control characters in a value. An empty value becomes %, and a value of * or > becomes %2A or %3E.
  • MQTT subscribers see the encoded value in the topic, such as orders/eu%20west.
  • If a property that the template names is missing, the gateway refuses a QoS 1 or 2 or unsettled message. It drops a QoS 0 or presettled message. Errors lists the codes.
  • A send to a subject that the template makes, such as orders.eu, must agree with its properties. The gateway handles a message to orders.eu with region=us the same as a message without the property.

Message bodies​

The MQTT payload is the NATS payload, byte for byte.

An AMQP body of one data section becomes the NATS payload. The gateway publishes any other body, such as an amqp-value string, in its AMQP encoding, with the header Mqgw-Amqp-Body: sections. MQTT and NATS clients then read AMQP bytes:

AMQP bodyNATS payload
data hellohello
amqp-value "hello"00 53 77 a1 05 68 65 6c 6c 6f

Send AMQP bodies as one data section when MQTT or NATS clients read them. Many AMQP clients, Qpid JMS among them, send a string as an amqp-value by default.

A message from MQTT or NATS reaches an AMQP receiver as one data section.

Headers​

The gateway puts message metadata in NATS headers named Mqgw-*. A field that both protocols have uses one shared header, so a NATS service reads one set of headers from either protocol. A field that only one protocol has uses a header with that protocol's name in it.

HeaderSet byMeaning
Mqgw-QoSMQTT, AMQP0, 1 or 2. AMQP sets 0 for presettled and 1 for unsettled. No header means 0
Mqgw-Content-TypeMQTT v5, AMQPContent Type, or content-type
Mqgw-Correlation-IdMQTT v5, AMQPCorrelation Data, or correlation-id
Mqgw-Reply-ToMQTT v5, AMQPThe reply subject: a Response Topic as a subject, or reply-to
Mqgw-ExpiresMQTT v5, AMQPWhen the message expires, in Unix milliseconds
Mqgw-Prop-<key>MQTT v5, AMQPOne User Property or application property. A repeated key has one value for each
Mqgw-Mqtt-RetainMQTTtrue when the publish set RETAIN
Mqgw-Mqtt-Client-IdMQTTThe client ID of the publisher
Mqgw-Mqtt-Payload-FormatMQTT v5Payload Format Indicator, 0 or 1
Mqgw-Mqtt-Props-OrderMQTT v5The order of User Properties with different keys
Mqgw-Amqp-Message-IdAMQPmessage-id
Mqgw-Amqp-SubjectAMQPThe subject property (JMSType), not the NATS subject
Mqgw-Amqp-Container-IdAMQPThe container-id of the sender
Mqgw-Amqp-Head, Mqgw-Amqp-Body, Mqgw-Amqp-FooterAMQPThe sender's own sections, which AMQP receivers get unchanged

Rules:

  • A key or value that a header cannot hold is percent-encoded, and so is %. The User Property with space is the header Mqgw-Prop-with%20space.
  • An AMQP application property becomes text. A number is decimal, a boolean is true or false, a timestamp is Unix milliseconds, a uuid is its canonical form and binary is base64. The gateway drops null, decimal, lists and maps.
  • A core NATS message with a reply subject also has it as its NATS reply subject. A stored message keeps it only in Mqgw-Reply-To.
  • An MQTT 3.1.1 client sends and receives no properties.
  • On a message that an AMQP client sent, AMQP receivers get the sender's own sections. A NATS service that forwards it and changes Mqgw-Prop-*, Mqgw-Content-Type or Mqgw-Correlation-Id changes what MQTT and NATS receivers see, not what AMQP receivers see.

What a crossing loses​

  • An AMQP receiver gets only the first value of a repeated User Property key.
  • An MQTT client gets AMQP application properties as text.
  • A Content Type that is not ASCII does not reach AMQP.
  • A value that MQTT cannot carry does not reach MQTT clients. Examples are text that is not valid UTF-8 and values longer than 65,535 bytes.
  • MQTT and AMQP clients do not get NATS headers outside the table above, such as a service's own Trace-Id.
  • Each protocol's own headers reach only that protocol and NATS clients.

NATS clients​

Read messages from MQTT and AMQP clients​

Subscribe to the subject. Every message is on core NATS, stored or not, with the headers above. To read the stored messages, consume from the stream that the binding names.

Publish to MQTT and AMQP clients​

A plain NATS publish reaches MQTT clients at QoS 0, not retained, with no properties. It reaches AMQP receivers as one data section, with to set to the subject.

Set headers to give MQTT v5 and AMQP clients the matching fields:

nats pub orders.eu '{"id": 42}' \
-H 'Mqgw-Content-Type:application/json' \
-H 'Mqgw-Prop-region:eu'

On a subject that a binding stores:

  • An AMQP queue on the address delivers every message that the stream holds.
  • An MQTT QoS 1 or 2 subscription gets the message from the stream only when Mqgw-QoS is 1 or 2. Without it, the subscriber gets the message at QoS 0, and only when connected.

Request and reply​

A NATS request reaches MQTT v5 clients with its reply subject as the Response Topic, and AMQP clients with it as reply-to. Usually no binding stores a reply subject, so these clients reply at QoS 0 or presettled.

A NATS service that answers MQTT or AMQP requests sends the reply to Mqgw-Reply-To when the request has it, else to the message's reply subject. The reply needs Mqgw-Correlation-Id from the request when the requester matches replies by correlation ID.

Shared subscriptions​

An MQTT client subscribed to $share/g1/orders/+ is a member of the NATS queue group g1 on orders.*. A NATS queue subscriber in g1 on that subject joins the group, and gets a share of the QoS 0 messages.

Trust​

These headers are only as trustworthy as the publisher. A NATS client can set or omit any of them. For example, a forged Mqgw-Mqtt-Client-Id changes which MQTT No Local subscribers get the message.