STOMP is a simple interoperable protocol designed for asynchronous messagepassing between clients via mediating servers. It defines a text basedwire-format for messages passed between these clients and servers.
STOMP has been in active use for several years and is supported by manymessage brokers and client libraries. This specification defines the STOMP 1.2protocol and is an update toSTOMP 1.1.
Please send feedback to the stomp-spec@googlegroups.com mailing list.
STOMP arose from a need to connect to enterprise message brokers fromscripting languages such as Ruby, Python and Perl. In such anenvironment it is typically logically simple operations that arecarried out such as 'reliably send a single message and disconnect'or 'consume all messages on a given destination'.
It is an alternative to other open messaging protocols such as AMQPand implementation specific wire protocols used in JMS brokers suchas OpenWire. It distinguishes itself by covering a small subset ofcommonly used messaging operations rather than providing acomprehensive messaging API.
More recently STOMP has matured into a protocol which can be used pastthese simple use cases in terms of the wire-level features it nowoffers, but still maintains its core design principles of simplicityand interoperability.
STOMP is a frame based protocol, with frames modelled on HTTP. A frameconsists of a command, a set of optional headers and an optional body. STOMPis text based but also allows for the transmission of binary messages. Thedefault encoding for STOMP is UTF-8, but it supports the specification ofalternative encodings for message bodies.
A STOMP server is modelled as a set of destinations to which messages can besent. The STOMP protocol treats destinations as opaque string and their syntaxis server implementation specific. Additionally STOMP does not define what thedelivery semantics of destinations should be. The delivery, or “messageexchange”, semantics of destinations can vary from server to server and evenfrom destination to destination. This allows servers to be creative with thesemantics that they can support with STOMP.
A STOMP client is a user-agent which can act in two (possibly simultaneous)modes:
as a producer, sending messages to a destination on the server via aSENDframe
as a consumer, sending aSUBSCRIBE frame for a given destination andreceiving messages from the server asMESSAGE frames.
STOMP 1.2 is mostly backwards compatible with STOMP 1.1. There are only twoincompatible changes:
it is now possible to end frame lines with carriage return plus line feedinstead of only line feed
message acknowledgment has been simplified and now uses a dedicated header
Apart from these, STOMP 1.2 introduces no new features but focuses on clarifyingsome areas of the specification such as:
repeated frame header entries
use of thecontent-length andcontent-type headers
required support of theSTOMP frame by servers
connection lingering
scope and uniqueness of subscription and transaction identifiers
meaning of theRECEIPT frame with regard to previous frames
The main philosophies driving the design of STOMP are simplicity andinteroperability.
STOMP is designed to be a lightweight protocol that is easy to implement bothon the client and server side in a wide range of languages. This implies, inparticular, that there are not many constraints on the architecture of serversand many features such as destination naming and reliability semantics areimplementation specific.
In this specification we will note features of servers which are notexplicitly defined by STOMP 1.2. You should consult your STOMP server'sdocumentation for the implementation specific details of these features.
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”,“SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to beinterpreted as described inRFC 2119.
Implementations may impose implementation-specific limits on unconstrainedinputs, e.g. to prevent denial of service attacks, to guard against runningout of memory, or to work around platform-specific limitations.
The conformance classes defined by this specification are STOMP clients andSTOMP servers.
STOMP is a frame based protocol which assumes a reliable 2-way streamingnetwork protocol (such as TCP) underneath. The client and server willcommunicate using STOMP frames sent over the stream. A frame's structurelooks like:
COMMANDheader1:value1header2:value2Body^@The frame starts with a command string terminated by an end-of-line (EOL),which consists of an OPTIONAL carriage return (octet 13) followed by aREQUIRED line feed (octet 10). Following the command are zero or more headerentries in<key>:<value> format. Each header entry is terminated by an EOL.A blank line (i.e. an extra EOL) indicates the end of the headers and thebeginning of the body. The body is then followed by the NULL octet. Theexamples in this document will use^@, control-@ in ASCII, to representthe NULL octet. The NULL octet can be optionally followed by multiple EOLs.For more details, on how to parse STOMP frames, see theAugmented BNF section of this document.
All commands and header names referenced in this document are case sensitive.
The commands and headers are encoded in UTF-8. All frames except theCONNECTandCONNECTED frames will also escape any carriage return, line feed or colonfound in the resulting UTF-8 encoded headers.
Escaping is needed to allow header keys and values to contain those frameheader delimiting octets as values. TheCONNECT andCONNECTED frames do notescape the carriage return, line feed or colon octets in order to remain backwardcompatible with STOMP 1.0.
C style string literal escapes are used to encode any carriage return, line feedor colon that are found within the UTF-8 encoded headers. When decoding frame headers,the following transformations MUST be applied:
\r (octet 92 and 114) translates to carriage return (octet 13)\n (octet 92 and 110) translates to line feed (octet 10)\c (octet 92 and 99) translates to: (octet 58)\\ (octet 92 and 92) translates to\ (octet 92)Undefined escape sequences such as\t (octet 92 and 116) MUST be treated asa fatal protocol error. Conversely when encoding frame headers, the reversetransformation MUST be applied.
The STOMP 1.0 specification included many example frames with padding in theheaders and many servers and clients were implemented to trim or pad headervalues. This causes problems if applications want to send headers that SHOULDnot get trimmed. In STOMP 1.2, clients and servers MUST never trim or padheaders with spaces.
Only theSEND,MESSAGE, andERROR frames MAY have a body. All otherframes MUST NOT have a body.
Some headers MAY be used, and have special meaning, with most frames.
All frames MAY include acontent-length header. This header is an octetcount for the length of the message body. If acontent-length header isincluded, this number of octets MUST be read, regardless of whether or notthere are NULL octets in the body. The frame still needs to be terminatedwith a NULL octet.
If a frame body is present, theSEND,MESSAGE andERROR frames SHOULDinclude acontent-length header to ease frame parsing. If the frame bodycontains NULL octets, the frame MUST include acontent-length header.
If a frame body is present, theSEND,MESSAGE andERROR frames SHOULDinclude acontent-type header to help the receiver of the frame interpretits body. If thecontent-type header is set, its value MUST be a MIME typewhich describes the format of the body. Otherwise, the receiver SHOULDconsider the body to be a binary blob.
The implied text encoding for MIME types starting withtext/ is UTF-8. Ifyou are using a text based MIME type with a different encoding then youSHOULD append;charset=<encoding> to the MIME type. For example,text/html;charset=utf-16 SHOULD be used if you're sending an HTML body inUTF-16 encoding. The;charset=<encoding> SHOULD also get appended to anynontext/ MIME types which can be interpreted as text. A good example ofthis would be a UTF-8 encoded XML. Itscontent-type SHOULD get set toapplication/xml;charset=utf-8
All STOMP clients and servers MUST support UTF-8 encoding and decoding. Therefore,for maximum interoperability in a heterogeneous computing environment, it isRECOMMENDED that text based content be encoded with UTF-8.
Any client frame other thanCONNECT MAY specify areceipt header with anarbitrary value. This will cause the server to acknowledge the processing ofthe client frame with aRECEIPT frame (see theRECEIPT framefor more details).
SENDdestination:/queue/areceipt:message-12345hello queue a^@Since messaging systems can be organized in store and forward topologies,similar to SMTP, a message may traverse several messaging servers beforereaching a consumer. A STOMP server MAY 'update' header values by eitherprepending headers to the message or modifying a header in-place in themessage.
If a client or a server receives repeated frame header entries, only thefirst header entry SHOULD be used as the value of header entry. Subsequentvalues are only used to maintain a history of state changes of the headerand MAY be ignored.
For example, if the client receives:
MESSAGEfoo:Worldfoo:Hello^@The value of thefoo header is justWorld.
To prevent malicious clients from exploiting memory allocation in aserver, servers MAY place maximum limits on:
If these limits are exceeded the server SHOULD send the client anERRORframe and then close the connection.
STOMP servers must be able to support clients which rapidly connect anddisconnect.
This implies a server will likely only allow closed connections to lingerfor short time before the connection is reset.
As a consequence, a client may not receive the last frame sent by the server(for instance anERROR frame or theRECEIPT frame in reply to aDISCONNECT frame) before the socket is reset.
A STOMP client initiates the stream or TCP connection to the server by sendingtheCONNECT frame:
CONNECTaccept-version:1.2host:stomp.github.org^@If the server accepts the connection attempt it will respond with aCONNECTED frame:
CONNECTEDversion:1.2^@The server can reject any connection attempt. The server SHOULD respond backwith anERROR frame explaining why the connection was rejected and then closethe connection.
STOMP servers MUST handle aSTOMP frame in the same manner as aCONNECTframe. STOMP 1.2 clients SHOULD continue to use theCONNECT command toremain backward compatible with STOMP 1.0 servers.
Clients that use theSTOMP frame instead of theCONNECT frame will onlybe able to connect to STOMP 1.2 servers (as well as some STOMP 1.1 servers)but the advantage is that a protocol sniffer/discriminator will be able todifferentiate the STOMP connection from an HTTP connection.
STOMP 1.2 clients MUST set the following headers:
accept-version : The versions of the STOMP protocol the client supports.SeeProtocol Negotiation for more details.
host : The name of a virtual host that the client wishes to connect to.It is recommended clients set this to the host name that the socketwas established against, or to any name of their choosing. If thisheader does not match a known virtual host, servers supporting virtualhosting MAY select a default virtual host or reject the connection.
STOMP 1.2 clients MAY set the following headers:
login : The user identifier used to authenticate against a secured STOMP server.
passcode : The password used to authenticate against a secured STOMPserver.
heart-beat : TheHeart-beating settings.
STOMP 1.2 servers MUST set the following headers:
version : The version of the STOMP protocol the session will be using.SeeProtocol Negotiation for more details.STOMP 1.2 servers MAY set the following headers:
heart-beat : TheHeart-beating settings.
session : A session identifier that uniquely identifies the session.
server : A field that contains information about the STOMP server.The field MUST contain a server-name field and MAY be followed by optional comment fields delimited by a space octet.
The server-name field consists of a name token followed by an optional versionnumber token.
server = name ["/" version] *(comment)
Example:
server:Apache/1.3.9
From STOMP 1.1 and onwards, theCONNECT frame MUST include theaccept-version header. It SHOULD be set to a comma separated list ofincrementing STOMP protocol versions that the client supports. If theaccept-version header is missing, it means that the client only supportsversion 1.0 of the protocol.
The protocol that will be used for the rest of the session will be thehighest protocol version that both the client and server have in common.
For example, if the client sends:
CONNECTaccept-version:1.0,1.1,2.0host:stomp.github.org^@The server will respond back with the highest version of the protocol thatit has in common with the client:
CONNECTEDversion:1.1^@If the client and server do not share any common protocol versions, then theserver MUST respond with anERROR frame similar to the following and thenclose the connection:
ERRORversion:1.2,2.1content-type:text/plainSupported protocol versions are 1.2 2.1^@Heart-beating can optionally be used to test the healthiness of theunderlying TCP connection and to make sure that the remote end is alive andkicking.
In order to enable heart-beating, each party has to declare what it can doand what it would like the other party to do. This happens at the verybeginning of the STOMP session, by adding aheart-beat header to theCONNECT andCONNECTED frames.
When used, theheart-beat header MUST contain two positive integersseparated by a comma.
The first number represents what the sender of the frame can do (outgoingheart-beats):
0 means it cannot send heart-beats
otherwise it is the smallest number of milliseconds between heart-beatsthat it can guarantee
The second number represents what the sender of the frame would liketo get (incoming heart-beats):
0 means it does not want to receive heart-beats
otherwise it is the desired number of milliseconds between heart-beats
Theheart-beat header is OPTIONAL. A missingheart-beat header MUST betreated the same way as a “heart-beat:0,0” header, that is: the party cannotsend and does not want to receive heart-beats.
Theheart-beat header provides enough information so that each party canfind out if heart-beats can be used, in which direction, and with whichfrequency.
More formally, the initial frames look like:
CONNECTheart-beat:<cx>,<cy>CONNECTEDheart-beat:<sx>,<sy>For heart-beats from the client to the server:
if<cx> is 0 (the client cannot send heart-beats) or<sy> is 0 (theserver does not want to receive heart-beats) then there will be none
otherwise, there will be heart-beats every MAX(<cx>,<sy>) milliseconds
In the other direction,<sx> and<cy> are used the same way.
Regarding the heart-beats themselves, any new data received over the networkconnection is an indication that the remote end is alive. In a givendirection, if heart-beats are expected every<n> milliseconds:
the sender MUST send new data over the network connection at least every<n> milliseconds
if the sender has no real STOMP frame to send, it MUST send an end-of-line (EOL)
if, inside a time window of at least<n> milliseconds, the receiver didnot receive any new data, it MAY consider the connection as dead
because of timing inaccuracies, the receiver SHOULD be tolerant and takeinto account an error margin
A client MAY send a frame not in this list, but for such a frame a STOMP 1.2server MAY respond with anERROR frame and then close the connection.
TheSEND frame sends a message to a destination in the messaging system. Ithas one REQUIRED header,destination, which indicates where to send themessage. The body of theSEND frame is the message to be sent. For example:
SENDdestination:/queue/acontent-type:text/plainhello queue a^@This sends a message to a destination named/queue/a. Note that STOMP treatsthis destination as an opaque string and no delivery semantics are assumed bythe name of a destination. You should consult your STOMP server'sdocumentation to find out how to construct a destination name which gives youthe delivery semantics that your application needs.
The reliability semantics of the message are also server specific and willdepend on the destination value being used and the other message headerssuch as thetransaction header or other server specific message headers.
SEND supports atransaction header which allows for transactional sends.
SEND frames SHOULD include acontent-length header and acontent-type header if a body is present.
An application MAY add any arbitrary user defined headers to theSEND frame.User defined headers are typically used to allow consumers to filtermessages based on the application defined headers using a selectoron aSUBSCRIBE frame. The user defined headers MUST be passed throughin theMESSAGE frame.
If the server cannot successfully process theSEND frame for any reason,the server MUST send the client anERROR frame and then close the connection.
TheSUBSCRIBE frame is used to register to listen to a given destination.Like theSEND frame, theSUBSCRIBE frame requires adestination headerindicating the destination to which the client wants to subscribe. Anymessages received on the subscribed destination will henceforth be deliveredasMESSAGE frames from the server to the client. Theack header controlsthe message acknowledgment mode.
Example:
SUBSCRIBEid:0destination:/queue/fooack:client^@If the server cannot successfully create the subscription,the server MUST send the client anERROR frame and then close the connection.
STOMP servers MAY support additional server specific headers to customize thedelivery semantics of the subscription. Consult your server's documentation fordetails.
Since a single connection can have multiple open subscriptions with aserver, anid header MUST be included in the frame to uniquely identifythe subscription. Theid header allows the client and server to relatesubsequentMESSAGE orUNSUBSCRIBE frames to the original subscription.
Within the same connection, different subscriptions MUST use differentsubscription identifiers.
The valid values for theack header areauto,client, orclient-individual. If the header is not set, it defaults toauto.
When theack mode isauto, then the client does not need to send theserverACK frames for the messages it receives. The server will assume theclient has received the message as soon as it sends it to the client.This acknowledgment mode can cause messages being transmitted to the clientto get dropped.
When theack mode isclient, then the client MUST send the serverACK frames for the messages it processes. If the connection fails before aclient sends anACK frame for the message the server will assume the messagehas not been processed and MAY redeliver the message to another client. TheACK frames sent by the client will be treated as a cumulative acknowledgment.This means the acknowledgment operates on the message specified in theACKframe and all messages sent to the subscription before theACK'ed message.
In case the client did not process some messages, it SHOULD sendNACK framesto tell the server it did not consume these messages.
When theack mode isclient-individual, the acknowledgment operates justlike theclient acknowledgment mode except that theACK orNACK framessent by the client are not cumulative. This means that anACK orNACKframe for a subsequent message MUST NOT cause a previous message to getacknowledged.
TheUNSUBSCRIBE frame is used to remove an existing subscription. Once thesubscription is removed the STOMP connections will no longer receive messagesfrom that subscription.
Since a single connection can have multiple open subscriptions with aserver, anid header MUST be included in the frame to uniquely identifythe subscription to remove. This header MUST match the subscriptionidentifier of an existing subscription.
Example:
UNSUBSCRIBEid:0^@ACK is used to acknowledge consumption of a message from a subscriptionusingclient orclient-individual acknowledgment. Any messages receivedfrom such a subscription will not be considered to have been consumed untilthe message has been acknowledged via anACK.
TheACK frame MUST include anid header matching theack header of theMESSAGE being acknowledged. Optionally, atransaction header MAY bespecified, indicating that the message acknowledgment SHOULD be part of thenamed transaction.
ACKid:12345transaction:tx1^@NACK is the opposite ofACK. It is used to tell the server that theclient did not consume the message. The server can then either send themessage to a different client, discard it, or put it in a dead letter queue.The exact behavior is server specific.
NACK takes the same headers asACK:id (REQUIRED) andtransaction(OPTIONAL).
NACK applies either to one single message (if the subscription'sackmode isclient-individual) or to all messages sent before and not yetACK'ed orNACK'ed (if the subscription'sack mode isclient).
BEGIN is used to start a transaction. Transactions in this case apply tosending and acknowledging - any messages sent or acknowledged during atransaction will be processed atomically based on the transaction.
BEGINtransaction:tx1^@Thetransaction header is REQUIRED, and the transaction identifier will beused forSEND,COMMIT,ABORT,ACK, andNACK frames to bind them tothe named transaction. Within the same connection, different transactions MUSTuse different transaction identifiers.
Any started transactions which have not been committed will be implicitlyaborted if the client sends aDISCONNECT frame or if the TCP connectionfails for any reason.
COMMIT is used to commit a transaction in progress.
COMMITtransaction:tx1^@Thetransaction header is REQUIRED and MUST specify the identifier of thetransaction to commit.
ABORT is used to roll back a transaction in progress.
ABORTtransaction:tx1^@Thetransaction header is REQUIRED and MUST specify the identifier of thetransaction to abort.
A client can disconnect from the server at anytime by closing the socket butthere is no guarantee that the previously sent frames have been received bythe server. To do a graceful shutdown, where the client is assured that allprevious frames have been received by the server, the client SHOULD:
send aDISCONNECT frame with areceipt header set. Example:
DISCONNECTreceipt:77^@wait for theRECEIPT frame response to theDISCONNECT. Example:
RECEIPTreceipt-id:77^@close the socket.
Note that, if the server closes its end of the socket too quickly, theclient might never receive the expectedRECEIPT frame. See theConnection Lingering section for more information.
Clients MUST NOT send any more frames after theDISCONNECT frame is sent.
The server will, on occasion, send frames to the client (in addition to theinitialCONNECTED frame). These frames MAY be one of:
MESSAGE frames are used to convey messages from subscriptions to the client.
TheMESSAGE frame MUST include adestination header indicating thedestination the message was sent to. If the message has been sent usingSTOMP, thisdestination header SHOULD be identical to the one used in thecorrespondingSEND frame.
TheMESSAGE frame MUST also contain amessage-id header with a uniqueidentifier for that message and asubscription header matching theidentifier of the subscription that is receiving the message.
If the message is received from a subscription that requires explicitacknowledgment (eitherclient orclient-individual mode) then theMESSAGE frame MUST also contain anack header with an arbitraryvalue. This header will be used to relate the message to a subsequentACK orNACK frame.
The frame body contains the contents of the message:
MESSAGEsubscription:0message-id:007destination:/queue/acontent-type:text/plainhello queue a^@MESSAGE frames SHOULD include acontent-length header and acontent-type header if a body is present.
MESSAGE frames will also include all user defined headers that were presentwhen the message was sent to the destination in addition to the serverspecific headers that MAY get added to the frame. Consult your server'sdocumentation to find out the server specific headers that it adds tomessages.
ARECEIPT frame is sent from the server to the client once a server hassuccessfully processed a client frame that requests a receipt. ARECEIPTframe MUST include the headerreceipt-id, where the value is the value ofthereceipt header in the frame which this is a receipt for.
RECEIPTreceipt-id:message-12345^@ARECEIPT frame is an acknowledgment that the corresponding client framehas beenprocessed by the server. Since STOMP is stream based, the receiptis also a cumulative acknowledgment that all the previous frames have beenreceived by the server. However, these previous frames may not yet befullyprocessed. If the client disconnects, previously received framesSHOULD continue to get processed by the server.
The server MAY sendERROR frames if something goes wrong. In this case, itMUST then close the connection just after sending theERROR frame. See thenext section aboutconnection lingering.
TheERROR frame SHOULD contain amessage header with a short descriptionof the error, and the body MAY contain more detailed information (or MAY beempty).
ERRORreceipt-id:message-12345content-type:text/plaincontent-length:170message:malformed frame receivedThe message:-----MESSAGEdestined:/queue/areceipt:message-12345Hello queue a!-----Did not contain a destination header, which is REQUIREDfor message propagation.^@If the error is related to a specific frame sent from the client, the serverSHOULD add additional headers to help identify the original frame that causedthe error. For example, if the frame included a receipt header, theERRORframe SHOULD set thereceipt-id header to match the value of thereceiptheader of the frame which the error is related to.
ERROR frames SHOULD include acontent-length header and acontent-type header if a body is present.
In addition to thestandard headers described above(content-length,content-type andreceipt), here are all the headersdefined in this specification that each frame MUST or MAY use:
CONNECT orSTOMPaccept-version,hostlogin,passcode,heart-beatCONNECTEDversionsession,server,heart-beatSENDdestinationtransactionSUBSCRIBEdestination,idackUNSUBSCRIBEidACK orNACKidtransactionBEGIN orCOMMIT orABORTtransactionDISCONNECTreceiptMESSAGEdestination,message-id,subscriptionackRECEIPTreceipt-idERRORmessageIn addition, theSEND andMESSAGE frames MAY include arbitrary userdefined headers that SHOULD be considered as being part of the carriedmessage. Also, theERROR frame SHOULD include additional headers to helpidentify the original frame that caused the error.
Finally, STOMP servers MAY use additional headers to give access to featureslike persistency or expiration. Consult your server's documentation fordetails.
A STOMP session can be more formally described using theBackus-Naur Form (BNF) grammar used in HTTP/1.1RFC 2616.
NULL = <US-ASCII null (octet 0)>LF = <US-ASCII line feed (aka newline) (octet 10)>CR = <US-ASCII carriage return (octet 13)>EOL = [CR] LF OCTET = <any 8-bit sequence of data>frame-stream = 1*frameframe = command EOL *( header EOL ) EOL *OCTET NULL *( EOL )command = client-command | server-commandclient-command = "SEND" | "SUBSCRIBE" | "UNSUBSCRIBE" | "BEGIN" | "COMMIT" | "ABORT" | "ACK" | "NACK" | "DISCONNECT" | "CONNECT" | "STOMP"server-command = "CONNECTED" | "MESSAGE" | "RECEIPT" | "ERROR"header = header-name ":" header-valueheader-name = 1*<any OCTET except CR or LF or ":">header-value = *<any OCTET except CR or LF or ":">This specification is licensed under theCreative Commons Attribution v3.0license.