From 516a97115bc064422e7b2c52cc73565b0c0600da Mon Sep 17 00:00:00 2001 From: David Ansari Date: Tue, 27 Feb 2024 10:50:38 +0100 Subject: [PATCH] Fix AMQP 0.9.1 headers regression Fixes https://github.com/rabbitmq/rabbitmq-server/discussions/10620 Up to RabbitMQ 3.12: * When an AMQP 0.9.1 publisher sends a message with P_basic.headers unset, RabbitMQ will deliver an AMQP 0.9.1 message with P_basic.headers unset. * When an AMQP 0.9.1 publisher sends a message with P_basic.headers being an empty list ([]), RabbitMQ will deliver an AMQP 0.9.1 message with P_basic.headers being an empty list ([]). In 3.13 including message containers, the 1st behaviour stayed the same while the 2nd behaviour changed to: * When an AMQP 0.9.1 publisher sends a message with P_basic.headers being an empty list ([]), RabbitMQ will deliver an AMQP 0.9.1 message with P_basic.headers unset. This commit fixes this regression by using the same behaviour as in 3.12. (cherry picked from commit 8a2a7406de68daca397f0d6503070b51f4c53a6e) --- deps/rabbit/src/mc_amqpl.erl | 2 +- deps/rabbit/test/quorum_queue_SUITE.erl | 36 +++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/deps/rabbit/src/mc_amqpl.erl b/deps/rabbit/src/mc_amqpl.erl index 5a6a65a3b5fb..23e7802a81ad 100644 --- a/deps/rabbit/src/mc_amqpl.erl +++ b/deps/rabbit/src/mc_amqpl.erl @@ -412,7 +412,7 @@ protocol_state(#content{properties = #'P_basic'{headers = H00} = B0} = C, end, Headers0, Anns), Headers = case Headers1 of [] -> - undefined; + H00; _ -> %% Dedup lists:usort(fun({Key1, _, _}, {Key2, _, _}) -> diff --git a/deps/rabbit/test/quorum_queue_SUITE.erl b/deps/rabbit/test/quorum_queue_SUITE.erl index 4bfc3d0f06b1..0aa68d222857 100644 --- a/deps/rabbit/test/quorum_queue_SUITE.erl +++ b/deps/rabbit/test/quorum_queue_SUITE.erl @@ -166,8 +166,8 @@ all_tests() -> consumer_priorities, cancel_consumer_gh_3729, cancel_and_consume_with_same_tag, - validate_messages_on_queue - + validate_messages_on_queue, + amqpl_headers ]. memory_tests() -> @@ -3332,6 +3332,38 @@ validate_messages_on_queue(Config) -> ok. +amqpl_headers(Config) -> + [Server | _] = Servers = rabbit_ct_broker_helpers:get_node_configs(Config, nodename), + Ch = rabbit_ct_client_helpers:open_channel(Config, Server), + QQ = ?config(queue_name, Config), + ?assertEqual({'queue.declare_ok', QQ, 0, 0}, + declare(Ch, QQ, [{<<"x-queue-type">>, longstr, <<"quorum">>}])), + + Headers1Sent = undefined, + Headers2Sent = [], + [ok = amqp_channel:cast( + Ch, + #'basic.publish'{routing_key = QQ}, + #amqp_msg{props = #'P_basic'{headers = HeadersSent, + delivery_mode = 2}}) || + HeadersSent <- [Headers1Sent, Headers2Sent]], + RaName = ra_name(QQ), + wait_for_messages_ready(Servers, RaName, 2), + + {#'basic.get_ok'{}, + #amqp_msg{props = #'P_basic'{headers = Headers1Received}} + } = amqp_channel:call(Ch, #'basic.get'{queue = QQ}), + + {#'basic.get_ok'{delivery_tag = DeliveryTag}, + #amqp_msg{props = #'P_basic'{headers = Headers2Received}} + } = amqp_channel:call(Ch, #'basic.get'{queue = QQ}), + + ?assertEqual(Headers1Sent, Headers1Received), + ?assertEqual(Headers2Sent, Headers2Received), + + ok = amqp_channel:cast(Ch, #'basic.ack'{delivery_tag = DeliveryTag, + multiple = true}). + leader_locator_client_local(Config) -> [Server1 | _] = Servers = rabbit_ct_broker_helpers:get_node_configs(Config, nodename), Q = ?config(queue_name, Config),