Skip to content

Commit 1952387

Browse files
committed
Make AMQP address v2 format user friendly
This commit is a follow up of #11604 This commit changes the AMQP address format v2 from ``` /e/:exchange/:routing-key /e/:exchange /q/:queue ``` to ``` /exchanges/:exchange/:routing-key /exchanges/:exchange /queues/:queue ``` Advantages: 1. more user friendly 2. matches nicely with the plural forms of HTTP API v1 and HTTP API v2 This plural form is still non-overlapping with AMQP address format v1. Although it might feel unusual at first to send a message to `/queues/q1`, if you think about `queues` just being a namespace or entity type, this address format makes sense.
1 parent a91c6ad commit 1952387

File tree

5 files changed

+50
-47
lines changed

5 files changed

+50
-47
lines changed

deps/rabbit/src/rabbit_amqp_session.erl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2427,9 +2427,9 @@ ensure_source(#'v1_0.source'{address = Address,
24272427
durable = Durable},
24282428
Vhost, User, PermCache, TopicPermCache) ->
24292429
case Address of
2430-
{utf8, <<"/q/", QNameBinQuoted/binary>>} ->
2430+
{utf8, <<"/queues/", QNameBinQuoted/binary>>} ->
24312431
%% The only possible v2 source address format is:
2432-
%% /q/:queue
2432+
%% /queues/:queue
24332433
try rabbit_uri:urldecode(QNameBinQuoted) of
24342434
QNameBin ->
24352435
QName = queue_resource(Vhost, QNameBin),
@@ -2549,9 +2549,9 @@ check_exchange(XNameBin, RKey, QNameBin, User, Vhost, PermCache0) ->
25492549
address_v1_permitted() ->
25502550
rabbit_deprecated_features:is_permitted(amqp_address_v1).
25512551

2552-
target_address_version({utf8, <<"/e/", _/binary>>}) ->
2552+
target_address_version({utf8, <<"/exchanges/", _/binary>>}) ->
25532553
2;
2554-
target_address_version({utf8, <<"/q/", _/binary>>}) ->
2554+
target_address_version({utf8, <<"/queues/", _/binary>>}) ->
25552555
2;
25562556
target_address_version(undefined) ->
25572557
%% anonymous terminus
@@ -2561,9 +2561,9 @@ target_address_version(_Address) ->
25612561
1.
25622562

25632563
%% The possible v2 target address formats are:
2564-
%% /e/:exchange/:routing-key
2565-
%% /e/:exchange
2566-
%% /q/:queue
2564+
%% /exchanges/:exchange/:routing-key
2565+
%% /exchanges/:exchange
2566+
%% /queues/:queue
25672567
%% <null>
25682568
ensure_target_v2({utf8, String}, Vhost) ->
25692569
case parse_target_v2_string(String) of
@@ -2586,7 +2586,7 @@ parse_target_v2_string(String) ->
25862586
{error, bad_address}
25872587
end.
25882588

2589-
parse_target_v2_string0(<<"/e/", Rest/binary>>) ->
2589+
parse_target_v2_string0(<<"/exchanges/", Rest/binary>>) ->
25902590
Key = cp_slash,
25912591
Pattern = try persistent_term:get(Key)
25922592
catch error:badarg ->
@@ -2609,10 +2609,10 @@ parse_target_v2_string0(<<"/e/", Rest/binary>>) ->
26092609
_ ->
26102610
{error, bad_address}
26112611
end;
2612-
parse_target_v2_string0(<<"/q/">>) ->
2612+
parse_target_v2_string0(<<"/queues/">>) ->
26132613
%% empty queue name is invalid
26142614
{error, bad_address};
2615-
parse_target_v2_string0(<<"/q/", QNameBinQuoted/binary>>) ->
2615+
parse_target_v2_string0(<<"/queues/", QNameBinQuoted/binary>>) ->
26162616
QNameBin = rabbit_uri:urldecode(QNameBinQuoted),
26172617
{ok, ?DEFAULT_EXCHANGE_NAME, QNameBin, QNameBin};
26182618
parse_target_v2_string0(_) ->

deps/rabbit/test/amqp_address_SUITE.erl

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,14 @@ end_per_testcase(Testcase, Config) ->
9797
rabbit_ct_helpers:testcase_finished(Config, Testcase).
9898

9999
%% Test v2 target address
100-
%% /e/:exchange/:routing-key
100+
%% /exchanges/:exchange/:routing-key
101101
target_exchange_routing_key(Config) ->
102102
XName = <<"👉"/utf8>>,
103103
RKey = <<"🗝️"/utf8>>,
104104
target_exchange_routing_key0(XName, RKey, Config).
105105

106106
%% Test v2 target address
107-
%% /e/:exchange/:routing-key
107+
%% /exchanges/:exchange/:routing-key
108108
%% where both :exchange and :routing-key contains a "/" character.
109109
target_exchange_routing_key_with_slash(Config) ->
110110
XName = <<"my/exchange">>,
@@ -141,7 +141,7 @@ target_exchange_routing_key0(XName, RKey, Config) ->
141141
ok = cleanup(Init).
142142

143143
%% Test v2 target address
144-
%% /e/:exchange/
144+
%% /exchanges/:exchange/
145145
%% Routing key is empty.
146146
target_exchange_routing_key_empty(Config) ->
147147
XName = <<"amq.fanout">>,
@@ -167,7 +167,7 @@ target_exchange_routing_key_empty(Config) ->
167167
ok = cleanup(Init).
168168

169169
%% Test v2 target address
170-
%% /e/:exchange
170+
%% /exchanges/:exchange
171171
%% Routing key is empty.
172172
target_exchange(Config) ->
173173
XName = <<"amq.fanout">>,
@@ -193,7 +193,7 @@ target_exchange(Config) ->
193193
ok = cleanup(Init).
194194

195195
%% Test v2 target address
196-
%% /e/:exchange
196+
%% /exchanges/:exchange
197197
%% where the target exchange does not exist.
198198
target_exchange_absent(Config) ->
199199
XName = <<"🎈"/utf8>>,
@@ -220,13 +220,13 @@ target_exchange_absent(Config) ->
220220
ok = amqp10_client:close_connection(Connection).
221221

222222
%% Test v2 target and source address
223-
%% /q/:queue
223+
%% /queues/:queue
224224
queue(Config) ->
225225
QName = <<"🎈"/utf8>>,
226226
queue0(QName, Config).
227227

228228
%% Test v2 target and source address
229-
%% /q/:queue
229+
%% /queues/:queue
230230
%% where :queue contains a "/" character.
231231
queue_with_slash(Config) ->
232232
QName = <<"my/queue">>,
@@ -252,7 +252,7 @@ queue0(QName, Config) ->
252252
ok = cleanup(Init).
253253

254254
%% Test v2 target address
255-
%% /q/:queue
255+
%% /queues/:queue
256256
%% where the target queue does not exist.
257257
target_queue_absent(Config) ->
258258
QName = <<"🎈"/utf8>>,
@@ -279,7 +279,7 @@ target_queue_absent(Config) ->
279279
ok = amqp10_client:close_connection(Connection).
280280

281281
%% Test v2 target address 'null' and 'to'
282-
%% /e/:exchange/:routing-key
282+
%% /exchanges/:exchange/:routing-key
283283
%% with varying routing keys.
284284
target_per_message_exchange_routing_key(Config) ->
285285
QName = atom_to_binary(?FUNCTION_NAME),
@@ -315,7 +315,7 @@ target_per_message_exchange_routing_key(Config) ->
315315
ok = cleanup(Init).
316316

317317
%% Test v2 target address 'null' and 'to'
318-
%% /e/:exchange
318+
%% /exchanges/:exchange
319319
%% with varying exchanges.
320320
target_per_message_exchange(Config) ->
321321
XFanout = <<"amq.fanout">>,
@@ -349,7 +349,7 @@ target_per_message_exchange(Config) ->
349349
ok = cleanup(Init).
350350

351351
%% Test v2 target address 'null' and 'to'
352-
%% /q/:queue
352+
%% /queues/:queue
353353
target_per_message_queue(Config) ->
354354
Q1 = <<"q1">>,
355355
Q2 = <<"q2">>,
@@ -418,17 +418,17 @@ bad_v2_addresses() ->
418418
<<0>>,
419419
<<"/">>,
420420
<<"//">>,
421-
<<"/q">>,
422-
<<"/q/">>,
421+
<<"/queues">>,
422+
<<"/queues/">>,
423423
<<"/queue/">>,
424-
<<"/e">>,
424+
<<"/exchanges">>,
425425
%% default exchange in v2 target address is disallowed
426-
<<"/e/">>,
427-
<<"/e//">>,
428-
<<"/e//mykey">>,
429-
<<"/e/amq.default">>,
430-
<<"/e/amq.default/">>,
431-
<<"/e/amq.default/mykey">>,
426+
<<"/exchanges/">>,
427+
<<"/exchanges//">>,
428+
<<"/exchanges//mykey">>,
429+
<<"/exchanges/amq.default">>,
430+
<<"/exchanges/amq.default/">>,
431+
<<"/exchanges/amq.default/mykey">>,
432432
<<"/ex/✋"/utf8>>,
433433
<<"/exchange">>,
434434
<<"/exchange/">>,
@@ -438,13 +438,13 @@ bad_v2_addresses() ->
438438
<<"/exchange/amq.default/key/">>,
439439
<<"/exchange/amq.default/key/mykey">>,
440440
%% The following addresses should be percent encoded, but aren't.
441-
<<"/q/missing%encoding">>,
442-
<<"/q/missing/encoding">>,
443-
<<"/q/✋"/utf8>>,
444-
<<"/e/missing%encoding">>,
445-
<<"/e/missing/encoding/routingkey">>,
446-
<<"/e/exchange/missing%encoding">>,
447-
<<"/e/✋"/utf8>>
441+
<<"/queues/missing%encoding">>,
442+
<<"/queues/missing/encoding">>,
443+
<<"/queues/✋"/utf8>>,
444+
<<"/exchanges/missing%encoding">>,
445+
<<"/exchanges/missing/encoding/routingkey">>,
446+
<<"/exchanges/exchange/missing%encoding">>,
447+
<<"/exchanges/✋"/utf8>>
448448
].
449449

450450
%% Test v2 target address 'null' with an invalid 'to' addresses.
@@ -535,7 +535,7 @@ target_bad_address0(TargetAddress, Config) ->
535535
ok = amqp10_client:close_connection(Connection).
536536

537537
%% Test v2 source address
538-
%% /q/:queue
538+
%% /queues/:queue
539539
%% where the source queue does not exist.
540540
source_queue_absent(Config) ->
541541
QName = <<"🎈"/utf8>>,

deps/rabbitmq_amqp_client/src/rabbitmq_amqp_address.erl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@
1414
unicode:unicode_binary().
1515
exchange(ExchangeName) ->
1616
ExchangeNameQuoted = uri_string:quote(ExchangeName),
17-
<<"/e/", ExchangeNameQuoted/binary>>.
17+
<<"/exchanges/", ExchangeNameQuoted/binary>>.
1818

1919
-spec exchange(unicode:unicode_binary(), unicode:unicode_binary()) ->
2020
unicode:unicode_binary().
2121
exchange(ExchangeName, RoutingKey) ->
2222
ExchangeNameQuoted = uri_string:quote(ExchangeName),
2323
RoutingKeyQuoted = uri_string:quote(RoutingKey),
24-
<<"/e/", ExchangeNameQuoted/binary, "/", RoutingKeyQuoted/binary>>.
24+
<<"/exchanges/", ExchangeNameQuoted/binary, "/", RoutingKeyQuoted/binary>>.
2525

2626
-spec queue(unicode:unicode_binary()) ->
2727
unicode:unicode_binary().
2828
queue(QueueName) ->
2929
QueueNameQuoted = uri_string:quote(QueueName),
30-
<<"/q/", QueueNameQuoted/binary>>.
30+
<<"/queues/", QueueNameQuoted/binary>>.

deps/rabbitmq_mqtt/src/mc_mqtt.erl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ convert_from(mc_amqp, Sections, Env) ->
8787
#'v1_0.properties'{reply_to = {utf8, Address}} ->
8888
MqttX = maps:get(mqtt_x, Env, ?DEFAULT_MQTT_EXCHANGE),
8989
case Address of
90-
<<"/e/", MqttX:(byte_size(MqttX))/binary, "/", RoutingKeyQuoted/binary>> ->
90+
<<"/exchanges/",
91+
MqttX:(byte_size(MqttX))/binary,
92+
"/",
93+
RoutingKeyQuoted/binary>> ->
9194
try rabbit_uri:urldecode(RoutingKeyQuoted) of
9295
RoutingKey ->
9396
MqttTopic = rabbit_mqtt_util:amqp_to_mqtt(RoutingKey),
@@ -263,7 +266,7 @@ convert_to(mc_amqp, #mqtt_msg{qos = Qos,
263266
%% We assume here that Exchange doesn't contain characters
264267
%% that need to be quoted. This is a reasonable assumption
265268
%% given that amq.topic is the default MQTT topic exchange.
266-
Address = <<"/e/", Exchange/binary, "/", TopicQuoted/binary>>,
269+
Address = <<"/exchanges/", Exchange/binary, "/", TopicQuoted/binary>>,
267270
{utf8, Address};
268271
_ ->
269272
undefined

deps/rabbitmq_mqtt/test/mc_mqtt_SUITE.erl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,12 +237,12 @@ amqp_to_mqtt_reply_to(_Config) ->
237237
Key = mqtt_x,
238238
Env = #{Key => <<"mqtt-topic-exchange">>},
239239

240-
AmqpProps1 = #'v1_0.properties'{reply_to = {utf8, <<"/e/mqtt-topic-exchange/my.routing.key">>}},
240+
AmqpProps1 = #'v1_0.properties'{reply_to = {utf8, <<"/exchanges/mqtt-topic-exchange/my.routing.key">>}},
241241
#mqtt_msg{props = Props1} = amqp_to_mqtt([AmqpProps1, Val], Env),
242242
?assertEqual({ok, <<"my/routing/key">>},
243243
maps:find('Response-Topic', Props1)),
244244

245-
AmqpProps2 = #'v1_0.properties'{reply_to = {utf8, <<"/e/NON-mqtt-topic-exchange/my.routing.key">>}},
245+
AmqpProps2 = #'v1_0.properties'{reply_to = {utf8, <<"/exchanges/NON-mqtt-topic-exchange/my.routing.key">>}},
246246
#mqtt_msg{props = Props2} = amqp_to_mqtt([AmqpProps2, Val]),
247247
?assertEqual(error,
248248
maps:find('Response-Topic', Props2)),
@@ -251,14 +251,14 @@ amqp_to_mqtt_reply_to(_Config) ->
251251
%% The AMQP client must percent encode the AMQP reply_to address URI. We expect the
252252
%% AMQP -> MQTT conversion to percent decode because an MQTT response topic is not percent encoded.
253253
RoutingKeyQuoted = uri_string:quote(RoutingKey),
254-
AmqpProps3 = #'v1_0.properties'{reply_to = {utf8, <<"/e/mqtt-topic-exchange/", RoutingKeyQuoted/binary>>}},
254+
AmqpProps3 = #'v1_0.properties'{reply_to = {utf8, <<"/exchanges/mqtt-topic-exchange/", RoutingKeyQuoted/binary>>}},
255255
#mqtt_msg{props = Props3} = amqp_to_mqtt([AmqpProps3, Val], Env),
256256
?assertEqual({ok, <<"my/sp%$@cial/routing/key">>},
257257
maps:find('Response-Topic', Props3)),
258258

259259
%% If the AMQP client did not percent encode the AMQP reply_to address URI as required,
260260
%% then the reply_to should be ignored by the conversion.
261-
AmqpProps4 = #'v1_0.properties'{reply_to = {utf8, <<"/e/mqtt-topic-exchange/", RoutingKey/binary>>}},
261+
AmqpProps4 = #'v1_0.properties'{reply_to = {utf8, <<"/exchanges/mqtt-topic-exchange/", RoutingKey/binary>>}},
262262
#mqtt_msg{props = Props4} = amqp_to_mqtt([AmqpProps4, Val], Env),
263263
?assertEqual(error,
264264
maps:find('Response-Topic', Props4)).

0 commit comments

Comments
 (0)