RabbitMQ URI Specification
Overview
This specification defines an "amqp" URI scheme. Conforming URIs represent the information needed by AMQP 0-9-1 clients as well as some RabbitMQ plugins to connect to RabbitMQ nodes.
Introduction
The scope of this specification is limited to AMQP 0-9-1, the original protocol implemented by RabbitMQ. An AMQP 0-9-1 client connects to a RabbitMQ node in order to publish and consume messages according to the messaging model.
Several pieces of information are needed by a client to establish and negotiate an AMQP 0-9-1 connection. These connection parameters include:
The parameters needed to establish the underlying TCP/IP connection to the server (i.e. host address and port).
Information to authenticate the client. AMQP 0-9-1 uses SASL for authentication. Typically the
PLAIN
mechanism is used, and so the authentication parameters consist of a username and password.The name of the "virtual host" (or vhost) that specifies the namespace for entities (such as exchanges and queues) referred to by the protocol. Note that this is not virtual hosting in the HTTP sense.
A RabbitMQ client will typically obtain all these parameters from a configuration file or environment variables in order for it to set up the connection. So it is convenient if the connection parameters can be combined into a single character string, rather than as distinct configuration settings. That means that only one configuration setting is needed, and only one value has to be passed to the client library.
But combining the connection parameters into a single string requires a convention, understood by the client library, about exactly how the connection parameters are represented and delimited. It is desirable to standardise that convention, so that it may be implemented consistently by many AMQP 0-9-1 client libraries. An obvious basis for such a standard is the generic syntax for URIs defined in RFC3986.
The purpose of this specification is to define the "amqp" and "amqps" URI schemes which represent the AMQP 0-9-1 connection parameters within the generic URI syntax.
The "amqp" URI scheme
The syntax of an AMQP 0-9-1 URI is defined by the following ABNF rules. All names in these rules not defined here are taken from RFC3986.
amqp_URI = "amqp://" amqp_authority [ "/" vhost ] [ "?" query ]
amqp_authority = [ amqp_userinfo "@" ] host [ ":" port ]
amqp_userinfo = username [ ":" password ]
username = *( unreserved / pct-encoded / sub-delims )
password = *( unreserved / pct-encoded / sub-delims )
vhost = segment
Once a URI has been successfully parsed according to this syntax, the connection parameters are determined as described in the following sections.
Host
The host to which the underlying TCP connection is made is determined from the host component according to RFC3986, section 3.2.2. Note that according to the ABNF, the host component may not be absent, but it may be zero-length.
Port
The port number to which the underlying TCP connection is made is determined from the port component according to RFC3986. The port component may be absent, indicated by the lack of the ":" character separating it from the host. If it is absent, then the IANA-assigned port number for AMQP 0-9-1, 5672, should be substituted instead.
Username and password
If present, the username and password components should be
used in the SASL exchange that occurs via the
connection.secure
and connection.secure-ok
AMQP 0-9-1 methods.
Any percent-encoded octets in the username and password
should be decoded before they are used in the SASL exchange,
and the resulting octet sequences should be regarded as
UTF-8 encoded.
Both the username and password may be absent; their absence is indicated by the lack of the "@" character separating the amqp_userinfo from the host. If the username is present, the password may be absent; this is indicated by the lack of the ":" character separating it from the username. Zero-length usernames and passwords are not equivalent to absent usernames and passwords.
RFC3986 states that "A password appearing within the userinfo component is deprecated and should be considered an error" (section 7.5). While this is sound advice in the context of user-facing applications (e.g. web browsers) and for URIs that might be stored and displayed insecurely, it is not necessarily valid for backend applications. Many of those applications are "headless" services, and open RabbitMQ connections on behalf of the application as a whole rather than for specific users. So the username and password identify the application rather than a human user, and are likely to be included with connection parameters appearing in a secure store of configuration settings. User-facing applications, which make RabbitMQ connections on behalf of specific users, are also possible. In such cases the username and password may be provided by the user to identify themselves. But such applications are the exception rather than the rule. Thus authors of applications implementing this specification should not consider themselves bound by section 7.5 of RFC3986. Please also see the section on "Security Considerations" below.
Virtual Host
The virtual host (vhost) component is used as the basis for the
virtual-host field of the connection.open
AMQP 0-9-1 method. Any
percent-encoded octets in the vhost should be decoded before
the it is passed to the server.
Note that:
- The vhost component of the URI does not include the leading "/" character from the path. This makes it possible to refer to any vhost, not only those that begin with a "/" character.
- The vhost is a single segment. Therefore, any "/" characters that appear in the vhost name must be percent-encoded. URIs with multi-segment paths do not obey this specification.
The vhost component may be absent; this is indicated by the lack of a "/" character following the amqp_authority. An absent vhost component is not equivalent to an empty (i.e. zero-length) vhost name.
Handling of absent components
Certain URI components (the port, username, password, vhost and query) may be absent from a URI. The host may not be absent, but may be zero-length; for the purposes of this section, a zero-length host is treated as absent.
Apart from the port (which is covered in the section 2.2 above), this specification does not mandate how implementations should handle absent components. Possible approaches include, but are not limited to, the following:
- An absent component may be substituted with a default value.
- A user-facing application may prompt the user to provide the value for an absent component.
- An absent component may cause an error.
Furthermore, an application may follow different strategies for different components.
For example, the URI "amqp://", in which all components are absent, might result in an client library using a set of defaults which correspond to a connection to a local RabbitMQ server, authenticating as a guest user. This would be convenient for development purposes.
The "amqps" URI scheme
The "amqps" URI scheme is used to instruct a client to make an secured connection to the server.
The AMQP 0-9-1 specification assume that the underlying transport layer provides reliable byte stream-oriented virtual circuits. When it is not necessary to secure the traffic on the network, TCP/IP connections are typically used.
In cases where the traffic must be secured, TLS (see RFC5246) can be used. Current practice is simply to layer AMQP 0-9-1 on top of TLS to form "AMQPS" (analogously to the way HTTPS layers HTTP on top of TLS). AMQP 0-9-1 does not provide a way for a non-secured connection to be upgraded to a secured connection. So a server that supports both secured and non-secured connections must listen on distinct ports for the two types of connections.
Apart from the scheme identifier, the syntax of the "amqps" URI scheme is identical to that of the "amqp" URI scheme:
amqps_URI = "amqps://" amqp_authority [ "/" vhost ]
The interpretation of an amqps URI differs from the corresponding "plain" URI in two ways. In all other respects, the interpretation is the same.
- The client must act as a TLS client, and begin the TLS handshake as soon as the underlying TCP/IP connection has been established. All AMQP 0-9-1 protocol data is sent as TLS "application data". Other than this, normal AMQP 0-9-1 behaviour is followed.
- If the port number is absent from the URI, the IANA-assigned port number for "amqps", 5671, should be used.
Security Considerations
As discussed in the section 2.3 above, URIs will often be supplied to applications as configuration settings. In such contexts, if the password cannot be incorporated into the URI, then it will simply be supplied as a separate configuration setting. This reduces the benefit of the use of a URI without any increase in security. For this reason, this specification overrides RFC3986's deprecation of passwords within the userinfo component.
Developers should feel free use the password component whenever this does not impact security. Nonetheless, they should be aware that the contents of the password component may be sensitive, and they should avoid leaking it (e.g. the full URI should not appear in exception messages or log records, which might be visible to less privileged personnel).
Appendix A: Examples
Below is a table of examples that show how URIs should be parsed according to this specification. Many of these examples are intended to demonstrate edge cases in order to elucidate the specification and provide test cases for code that parses URIs. Each row shows a URI, and the resulting octet sequences for each component. Those octet sequences are enclosed in double quotes. Empty cells indicate absent components, as described in section 3.
URI | Username | Password | Host | Port | Vhost |
---|---|---|---|---|---|
amqp://user:pass@host:10000/vhost | "user" | "pass" | "host" | 10000 | "vhost" |
amqp://user:passw%23rd@host:10000/vhost | "user" | "passw#rd" | "host" | 10000 | "vhost" |
amqp://user%61:%61pass@ho%61st:10000/v%2fhost | "usera" | "apass" | "hoast" | 10000 | "v/host" |
amqp:// | |||||
amqp://:@/ | "" | "" | "" | ||
amqp://user@ | "user" | ||||
amqp://user:pass@ | "user" | "pass" | |||
amqp://host | "host" | ||||
amqp://:10000 | 10000 | ||||
amqp:///vhost | "vhost" | ||||
amqp://host/ | "host" | "" | |||
amqp://host/%2f | "host" | "/" | |||
amqp://[::1] | "[::1]" (i.e. the IPv6 address ::1) |
Appendix B: Query parameters
Clients may require further parameterisation to define how they should connect to servers. The standard URI query syntax may be used to provide additional information to the client.
Query parameters may be more implementation-specific than other URI parts; as such this document will not attempt to prescribe how they should be used. However, we have documented how the officially supported clients read URI query parameters.