STOMP Plugin
Overview
RabbitMQ supports STOMP via a plugin that ships in the core distribution. The plugin supports STOMP versions 1.0 through 1.2 with some extensions and restrictions.
STOMP clients can interoperate with other protocols. All the functionality in the management UI and several other plugins can be used with STOMP, although there may be some limitations or the need to tweak the defaults.
Enabling the Plugin
The STOMP plugin is included in the RabbitMQ distribution. Before clients can successfully connect, it must be enabled using rabbitmq-plugins:
rabbitmq-plugins enable rabbitmq_stomp
Plugin Configuration
TCP Listeners
When no configuration is specified the STOMP Adapter will listen on
all interfaces on port 61613 and have a default user login/passcode
of guest
/guest
.
To change the listener port, edit your
Configuration file,
to contain a tcp_listeners
variable for the rabbitmq_stomp
application.
For example, a minimalistic configuration file which changes the listener port to 12345 would look like:
stomp.listeners.tcp.1 = 12345
while one which changes the listener to listen only on localhost (for both IPv4 and IPv6) would look like:
stomp.listeners.tcp.1 = 127.0.0.1:61613
stomp.listeners.tcp.2 = ::1:61613
TCP Listener Options
The plugin supports TCP listener option configuration.
The settings use a common prefix, stomp.tcp_listen_options
, and control
things such as TCP buffer sizes, inbound TCP connection queue length, whether TCP keepalives
are enabled and so on. See the Networking guide for details.
stomp.listeners.tcp.1 = 127.0.0.1:61613
stomp.listeners.tcp.2 = ::1:61613
stomp.tcp_listen_options.backlog = 4096
stomp.tcp_listen_options.recbuf = 131072
stomp.tcp_listen_options.sndbuf = 131072
stomp.tcp_listen_options.keepalive = true
stomp.tcp_listen_options.nodelay = true
stomp.tcp_listen_options.exit_on_close = true
stomp.tcp_listen_options.send_timeout = 120
TLS Support
To use TLS for STOMP connections, TLS must be configured in the broker. To enable
TLS-enabled STOMP connections, add a TLS listener for STOMP using the stomp.listeners.ssl.*
configuration keys.
The plugin will use core RabbitMQ server certificates and key (just like AMQP 0-9-1 and AMQP 1.0 listeners do):
ssl_options.cacertfile = /path/to/tls/ca_certificate.pem
ssl_options.certfile = /path/to/tls/server_certificate.pem
ssl_options.keyfile = /path/to/tls/server_key.pem
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true
stomp.listeners.tcp.1 = 61613
# default TLS-enabled port for STOMP connections
stomp.listeners.ssl.1 = 61614
This configuration creates a standard TCP listener on port 61613 and a TLS listener on port 61614.
When a TLS listener is set up, you may want to deactivate all non-TLS ones. This can be configured like so:
stomp.listeners.tcp = none
stomp.listeners.ssl.1 = 61614
Default User
The RabbitMQ STOMP adapter allows CONNECT
frames to omit the login
and passcode
headers if a default is configured.
To configure a default login and passcode, add a default_user
section to the rabbitmq_stomp
application configuration. For example:
stomp.default_user = guest
stomp.default_pass = guest
The configuration example above makes guest
/guest
the default
login/passcode pair.
Authentication with TLS/x509 client certificates
The plugin can authenticate TLS-enabled connections by extracting a name from the client's TLS (x509) certificate, without using a password.
For safety the server must be configured with the TLS options
fail_if_no_peer_cert
set to true
and verify
set to verify_peer
, to
force all TLS clients to have a verifiable client certificate.
To switch this feature on, set ssl_cert_login
to true
for the
rabbitmq_stomp
application. For example:
stomp.ssl_cert_login = true
By default this will set the username to an RFC4514-ish string form of the certificate's subject's Distinguished Name, similar to that produced by OpenSSL's "-nameopt RFC2253" option.
To use the Common Name instead, add:
ssl_cert_login_from = common_name
to your configuration.
Note that:
- The authenticated user must exist in the configured authentication / authorisation backend(s).
- Clients must not supply
login
andpasscode
headers.
Implicit Connect
If you configure a default user or use SSL client certificate
authentication, you can also choose to allow clients to omit the
CONNECT
frame entirely. In this mode, if the first frame sent on a
session is not a CONNECT
, the client is automatically connected as
the default user or the user supplied in the SSL certificate.
To enable implicit connect, set implicit_connect
to true
for the
rabbit_stomp
application. For example:
stomp.default_user = guest
stomp.default_pass = guest
stomp.implicit_connect = true
Implicit connect is not enabled by default.
Note: A client causing an implicit connect will not receive a
CONNECTED
frame from the server.
Proxy Protocol
The STOMP plugin supports the proxy protocol. This feature is turned off by default. To turn it on for STOMP clients:
stomp.proxy_protocol = true
See the Networking Guide for more information about the proxy protocol.
Frame Size Limit
By default frame size limit is 4Mb. When a frame exceeds the limit it's an error and connection closed.
stomp.max_frame_size = 4 * 1024 * 1024
Destinations
The STOMP specification does not prescribe what kinds of destinations
a broker must support, instead the value of the destination
header
in SEND
and MESSAGE
frames is broker-specific. The RabbitMQ STOMP
adapter supports a number of different destination types:
/exchange
--SEND
to arbitrary routing keys andSUBSCRIBE
to arbitrary binding patterns;/queue
--SEND
andSUBSCRIBE
to queues managed by the STOMP gateway;/amq/queue
--SEND
andSUBSCRIBE
to queues created outside the STOMP gateway;/topic
--SEND
andSUBSCRIBE
to transient and durable topics;/temp-queue/
-- create temporary queues (inreply-to
headers only).
AMQP 0-9-1 Semantics
The destination
header on a MESSAGE
frame is set as though the
message originated from a SEND
frame:
- messages published to the default exchange are given the destination
/queue/
queuename; - messages published to
amq.topic
are given the destination/topic/
routing_key; - all other messages are given the destination
/exchange/
exchange_name[/
routing_key].
If /
, %
or non-ascii bytes are in the queuename, exchange_name
or routing_key, they are each replaced with the sequence %
dd,
where dd is the hexadecimal code for the byte.
Because of these rules the destination on a MESSAGE
frame may not
exactly match that on a SEND
that published it.
Different destinations have different queue parameter defaults. They can be controlled explicitly via headers, as explained further in this guide.
Exchange Destinations
Any exchange/queue or exchange/routing-key combination can be accessed
using destinations prefixed with /exchange
.
For SUBSCRIBE
frames, a destination of the form
/exchange/<name>[/<pattern>]
can be used. This destination:
- creates an exclusive, auto-delete queue on
<name>
exchange; - if
<pattern>
is supplied, binds the queue to<name>
exchange using<pattern>
; and - registers a subscription against the queue, for the current STOMP session.
For SEND
frames, a destination of the form
/exchange/<name>[/<routing-key>]
can be used. This destination:
- sends to exchange
<name>
with the routing key<routing-key>
.
Note: Exchange destinations are not suitable for
consuming messages from an existing queue. A new queue is created for
each subscriber and is bound to the specified exchange using the
supplied routing key. To work with existing queues, use
/amq/queue
destinations.
Queue Destinations
For simple queues, destinations of the form /queue/<name>
can be
used.
Queue destinations deliver each message to at most one subscriber. Messages sent when no subscriber exists will be queued until a subscriber connects to the queue.
AMQP 0-9-1 Semantics
For SUBSCRIBE
frames, these destinations create a shared queue <name>
. A
subscription against the queue <name>
is created for the current STOMP
session.
For SEND
frames, a shared queue <name>
is created on the first SEND
to
this destination in this session, but not subsequently. The message is sent to
the default exchange with the routing key <name>
.
If no queue parameters are specified, queue will be assumed to be durable, non-exclusive, non-autodeleted.
AMQ Queue Destinations
To address existing queues created outside the STOMP adapter,
destinations of the form /amq/queue/<name>
can be used.
AMQP 0-9-1 Semantics
For both SEND
and SUBSCRIBE
frames no queue is created.
For SUBSCRIBE
frames, it is an error if the queue does not exist.
For SEND
frames, the message is sent directly to the existing queue named
<name>
via the default exchange.
For SUBSCRIBE
frames, a subscription against the existing queue <name>
is
created for the current STOMP session.
If no queue parameters are specified, queue will be assumed to be durable, non-exclusive, non-autodeleted.
Topic Destinations
Perhaps the most common destination type used by STOMP clients is /topic/<name>
.
They perform topic matching on publishing messages against subscriber patterns
and can route a message to multiple subscribers (each gets its own copy).
Topic destinations support all the routing patterns of AMQP 0-9-1
topic exchanges.
Messages sent to a topic destination that has no active subscribers are simply discarded.
AMQP 0-9-1 Semantics
For SEND
frames, the message is sent to the amq.topic
exchange
with the routing key <name>
.
For SUBSCRIBE
frames, an autodeleted, non-durable queue is created and bound to the
amq.topic
exchange with routing key <name>
. A subscription is
created against the queue.
A different default exchange than amq.topic
can be specified
using the stomp.default_topic_exchange
configuration setting:
stomp.default_topic_exchange = some.exchange
Durable Topic Subscriptions
The STOMP adapter supports durable topic subscriptions. Durable subscriptions allow clients to disconnect from and reconnect to the STOMP broker as needed, without missing messages that are sent to the topic.
Topics are neither durable nor transient, instead subscriptions are durable or transient. Durable and transient can be mixed against a given topic.
Creating a Durable Subscription
To create a durable subscription, set the durable
header to
true
in the SUBSCRIBE
frame. persistent
is also supported as an alias for
durable
for backwards compatibility with earlier plugin versions.
When creating a durable subscription to a topic destination,
set auto-delete
to false
to make sure the queue that backs your
subscription is not deleted when last subscriber disconnects.
When creating a durable subscription,
the id
header must be specified. For example:
SUBSCRIBE
destination:/topic/my-durable
id:1234
durable:true
auto-delete:false
AMQP 0-9-1 Semantics
For SEND
frames, the message is sent to the amq.topic
exchange
with the routing key <name>
.
For SUBSCRIBE
frames, a shared queue is created for each distinct
subscription ID x destination pair, and bound to the amq.topic
exchange with routing key <name>
. A subscription is created against
the queue.
Note: a different default exchange than amq.topic
can be specified
using the stomp.default_topic_exchange
configuration setting.
Deleting a Durable Subscription
To permanently delete a durable subscription, send an UNSUBSCRIBE
frame for
the subscription ID with the same durable
and auto-delete
header values as when
subscribing.
For example:
UNSUBSCRIBE id:1234 durable:true auto-delete:false
Temp Queue Destinations
Temp queue destinations allow you to define temporary destinations
in the reply-to
header of a SEND
frame.
Temp queues are managed by the broker and their identities are private to each session -- there is no need to choose distinct names for temporary queues in distinct sessions.
To use a temp queue, put the reply-to
header on a SEND
frame and
use a header value starting with /temp-queue/
. For example:
SEND destination:/queue/reply-test reply-to:/temp-queue/foo
Hello World!
This frame creates a temporary queue (with a generated name) that is private
to the session and automatically subscribes to that queue.
A different session that uses reply-to:/temp-queue/foo
will have a new,
distinct queue created.
The internal subscription id is a concatenation of the string
/temp-queue/
and the temporary queue (so /temp-queue/foo
in this example). The subscription id can be used to identify reply
messages. Reply messages cannot be identified from the destination
header, which will be different from the value in the reply-to
header. The internal subscription uses auto-ack mode and it cannot be
cancelled.
The /temp-queue/
destination is not the name of the destination
that the receiving client uses when sending the reply. Instead, the
receiving client can obtain the (real) reply destination queue name
from the reply-to
header of the MESSAGE
frame. This reply
destination name can then be used as the value of the destination
header in the SEND
frame sent in reply to the received
MESSAGE
.
Reply destination queue names are opaque and cannot be inferred from
the /temp-queue/
name.
SEND
and SUBSCRIBE
frames must not contain /temp-queue
destinations in the destination
header. Messages cannot be sent to
/temp-queue
destinations, and subscriptions to reply queues are
created automatically.
AMQP 0-9-1 Semantics
Each /temp-queue/
corresponds to a distinct anonymous, exclusive,
auto delete queue. As such, there is no need for explicit clean up of
reply queues.
User generated queue names for Topic and Exchange destinations
When subscribing to an exchange
or topic
destination, RabbitMQ would generate
a queue name by default. It is possible to provide
a custom name using the x-queue-name
header:
SUBSCRIBE destination:/topic/alarms x-queue-name:my-alarms-queue
Controlling RabbitMQ Queue Parameters with STOMP
Queue properties can be controlled via STOMP headers:
durable
(aliased aspersistent
)auto-delete
exclusive
plus optional arguments ("x-arguments") for controlling dead lettering, queue and message TTL, queue limits, etc:
x-dead-letter-exchange
x-dead-letter-routing-key
x-expires
x-message-ttl
x-max-length
x-max-length-bytes
x-max-age
(available only for streams)x-stream-max-segment-size-bytes
(available only for streams)x-overflow
x-max-priority
x-queue-type
(to be able to declare quorum queues and streams)
The meaning of every header is the same as when a queue is declared over AMQP 0-9-1. Please consult the rest of the documentation for details.
Using Policies with STOMP
RabbitMQ policies allow for flexible, centralised attribute configuration of queues and exchanges. Policies can be used with queues used by the STOMP plugin.
Policies make it possible to use more RabbitMQ features with STOMP:
All server-named queues created by the STOMP plugin are prefixed with stomp-
which makes it easy to match the queues in a policy. For example, to limit
STOMP queue length to 1000 messages, create the following policy:
rabbitmqctl set_policy stomp-queues "^stomp-" '{"max-length":1000}' --apply-to queues
with rabbitmqctl.bat
on Windows:
rabbitmqctl.bat set_policy stomp-queues "^stomp-" "{""max-length"":1000}" --apply-to queues
Note that only one policy is applied to a queue at a time, so to specify multiple arguments (e.g. queue length limit and dead lettering) one needs to put them into a single policy.
Protocol Extensions and Restrictions
The RabbitMQ STOMP adapter relaxes the protocol on CONNECT
and supports a number of non-standard headers on certain
frames. These extra headers provide access to features that are not
described in the STOMP specs. In addition, we prohibit some headers which
are reserved for server use. The details are given below.
Connection and Virtual Hosts
The CONNECT
(or STOMP
) frame in
STOMP 1.1 has a
mandatory host
header (to select the virtual host to use for the
connection). The RabbitMQ adapter allows this to be optional.
When omitted, the default virtual host (/
) is presumed.
To configure a different default virtual host, add a default_vhost
section to the rabbitmq_stomp
application configuration, e.g.
stomp.default_vhost = /
If a host
header is specified it must be one of the
virtual hosts known to the RabbitMQ server, otherwise the connection is
rejected. The host
header is respected even if the STOMP 1.0 version is
negotiated at the time of the connect.
Message Persistence
On the SEND
frame, the STOMP adapter supports the inclusion of a persistent
header.
Setting the persistent
header to true
has the effect of making the message persistent.
Receipts for SEND
frames with persistent:true
are not sent until a
confirm is received from the broker. The exact semantics for confirms
on persistent messages can be found here.
MESSAGE
frames for persistent messages will contain a persistent:true
header.
ACK and NACK
RabbitMQ STOMP plugin supports auto
, client
, and client-individual
subscription headers that affect how ACK
on NACK
operations work.
The auto
mode uses automatic acknowledgements. The client
mode is manual
(client-driven) acknowledgements of multiple messages at once. The client-individual
is for message-by-message manual acknowledgement.
NACK
frames can optionally carry the requeue
header which controls whether
the message will be requeued or discarded/dead lettered. Default value is true
.
Prefetch
The prefetch count for all subscriptions is set to unlimited by
default. This can be controlled by setting the prefetch-count
header
on SUBSCRIBE
frames to the desired integer count.
Stream Support
The SUBSCRIBE
frame supports a x-stream-offset
header to specify the offset
to start consuming from in a stream. A typical subscription frame
for a stream will look like the following:
SUBSCRIBE destination:/amq/queue/my-stream ack:client prefetch-count:10 x-stream-offset:next
Note the ack
and prefetch-count
headers are also necessary. The x-stream-offset
header
has the same semantics as in AMQP 0.9.1, the possible values are:
first
to start consuming from the first available message in the streamlast
to start consuming from the last written chunk of messagesnext
to start consuming from the end of the stream (note the consumer will not receive messages until someone is publishing to the stream)offset=<offset-value>
to start from a specific offset, e.g.offset=40000
timestamp=<unix-time>
to start from a given time, e.g.timestamp=1619432061
for2021-04-26T10:14:21+00:00
The default value is next
.
When delivering messages from a stream, the message offset (that is the position of the
message in the stream) is included in the x-stream-offset
header of the MESSAGE
frame.
Stream filtering is also supported. The stream protocol is the preferred way to interact with streams, but most features are also available with other protocols. Stream filtering is no exception, it works the same way with STOMP as with AMQP:
- Declaration: a stream can be created on subscription.
Set the
x-queue-type
header tostream
and use thex-stream-filter-size-bytes
header to set the filter size (optional). - Publishing: use the
x-stream-filter-value
header to set the filter value for outbound messages. - Consuming: use the
x-stream-filter
header to set the expected filter value(s) (use a comma to separate values) and optionally thex-stream-match-unfiltered
header (true
orfalse
) to receive messages without any filter value as well (default isfalse
). Applications must also implement client-side filtering, as it is still possible to receive messages that do not meet the filter value(s) criteria.
Header prohibited on SEND
It is not permitted to set a message-id
header on a SEND
frame.
The header and its value is set by the server on a MESSAGE
frame sent
to a client.
Queue Properties
SEND
frames also allow headers corresponding to the AMQP properties
available when publishing messages. These headers are also set on
MESSAGE
frames sent to clients.
All non-deprecated AMQP 0-9-1 properties (content-type
,
content-encoding
, headers
, delivery-mode
, priority
,
correlation-id
, reply-to
, expiration
, message-id
, timestamp
,
type
, user-id
and app-id
) are supported. The following special
rules apply:
amqp-message-id
in STOMP is converted tomessage-id
in AMQP, and vice-versa.- The
reply-to
header causes temporary queues to be created (see Temp Queue Destinations above). - Some x-prefixed STOMP headers are translated into optional queue arguments (see below).
Optional Queue Properties
With RabbitMQ, SEND
and SUBSCRIBE
frames can include a set of headers to configure the queue behaviour,
for example, use TTL or similar extensions.
The list of supported headers is
- x-message-ttl
- x-expires
- x-max-length
- x-max-length-bytes
- x-dead-letter-exchange
- x-dead-letter-routing-key
- x-max-priority
For example, if you want to use priority queues with STOMP, you can SUBSCRIBE (or SEND) with the following header:
SUBSCRIBE destination:/queue/my-priority-queue x-max-priority:5
Queue Immutability
Once a queue is declared, its properties cannot be changed. Optional arguments can be modified with policies. Otherwise the queue has to be deleted and re-declared. This is true for STOMP clients as well as AMQP 0-9-1.