19
19
-rabbit_deprecated_feature (
20
20
{amqp_address_v1 ,
21
21
#{deprecation_phase => permitted_by_default ,
22
+ doc_url => " https://www.rabbitmq.com/docs/next/amqp#address" ,
22
23
messages =>
23
24
#{when_permitted =>
24
25
" RabbitMQ AMQP address version 1 is deprecated. "
25
- " Clients should use RabbitMQ AMQP address version 2." }}
26
+ " Clients should use RabbitMQ AMQP address version 2." ,
27
+ when_denied =>
28
+ " RabbitMQ AMQP address version 1 is unsupported. "
29
+ " Clients must use RabbitMQ AMQP address version 2."
30
+ }}
26
31
}).
27
32
28
33
-define (PROTOCOL , amqp10 ).
@@ -2422,12 +2427,24 @@ ensure_source(#'v1_0.source'{address = Address,
2422
2427
durable = Durable },
2423
2428
Vhost , User , PermCache , TopicPermCache ) ->
2424
2429
case Address of
2430
+ {utf8 , <<" /q/" , QNameBinQuoted /binary >>} ->
2431
+ % % The only possible v2 source address format is:
2432
+ % % /q/:queue
2433
+ try rabbit_uri :urldecode (QNameBinQuoted ) of
2434
+ QNameBin ->
2435
+ QName = queue_resource (Vhost , QNameBin ),
2436
+ ok = exit_if_absent (QName ),
2437
+ {ok , QName , PermCache , TopicPermCache }
2438
+ catch error :_ ->
2439
+ {error , {bad_address , Address }}
2440
+ end ;
2425
2441
{utf8 , SourceAddr } ->
2426
2442
case address_v1_permitted () of
2427
- true -> ensure_source_v1 (
2428
- SourceAddr , Vhost , User , Durable , PermCache , TopicPermCache );
2429
- false -> ensure_source_v2 (
2430
- SourceAddr , Vhost , PermCache , TopicPermCache )
2443
+ true ->
2444
+ ensure_source_v1 (SourceAddr , Vhost , User , Durable ,
2445
+ PermCache , TopicPermCache );
2446
+ false ->
2447
+ {error , {amqp_address_v1_not_permitted , Address }}
2431
2448
end ;
2432
2449
_ ->
2433
2450
{error , {bad_address , Address }}
@@ -2467,19 +2484,10 @@ ensure_source_v1(Address,
2467
2484
Err
2468
2485
end
2469
2486
end ;
2470
- {error , _ } ->
2471
- ensure_source_v2 ( Address , Vhost , PermCache0 , TopicPermCache0 )
2487
+ {error , _ } = Err ->
2488
+ Err
2472
2489
end .
2473
2490
2474
- % % The only possible v2 source address format is:
2475
- % % /queue/:queue
2476
- ensure_source_v2 (<<" /queue/" , QNameBin /binary >>, Vhost , PermCache , TopicPermCache ) ->
2477
- QName = queue_resource (Vhost , QNameBin ),
2478
- ok = exit_if_absent (QName ),
2479
- {ok , QName , PermCache , TopicPermCache };
2480
- ensure_source_v2 (Address , _ , _ , _ ) ->
2481
- {error , {bad_address , Address }}.
2482
-
2483
2491
-spec ensure_target (# 'v1_0.target' {},
2484
2492
rabbit_types :vhost (),
2485
2493
rabbit_types :user (),
@@ -2495,29 +2503,28 @@ ensure_target(#'v1_0.target'{dynamic = true}, _, _, _) ->
2495
2503
ensure_target (# 'v1_0.target' {address = Address ,
2496
2504
durable = Durable },
2497
2505
Vhost , User , PermCache ) ->
2498
- case address_v1_permitted () of
2499
- true ->
2500
- try_target_v1 (Address , Vhost , User , Durable , PermCache );
2501
- false ->
2502
- try_target_v2 (Address , Vhost , User , PermCache )
2503
- end .
2504
-
2505
- try_target_v1 (Address , Vhost , User , Durable , PermCache0 ) ->
2506
- case ensure_target_v1 (Address , Vhost , User , Durable , PermCache0 ) of
2507
- {ok , XNameBin , RKey , QNameBin , PermCache } ->
2508
- check_exchange (XNameBin , RKey , QNameBin , User , Vhost , PermCache );
2509
- {error , _ } ->
2510
- try_target_v2 (Address , Vhost , User , PermCache0 )
2511
- end .
2512
-
2513
- try_target_v2 (Address , Vhost , User , PermCache ) ->
2514
- case ensure_target_v2 (Address , Vhost ) of
2515
- {ok , to , RKey , QNameBin } ->
2516
- {ok , to , RKey , QNameBin , PermCache };
2517
- {ok , XNameBin , RKey , QNameBin } ->
2518
- check_exchange (XNameBin , RKey , QNameBin , User , Vhost , PermCache );
2519
- {error , _ } = Err ->
2520
- Err
2506
+ case target_address_version (Address ) of
2507
+ 2 ->
2508
+ case ensure_target_v2 (Address , Vhost ) of
2509
+ {ok , to , RKey , QNameBin } ->
2510
+ {ok , to , RKey , QNameBin , PermCache };
2511
+ {ok , XNameBin , RKey , QNameBin } ->
2512
+ check_exchange (XNameBin , RKey , QNameBin , User , Vhost , PermCache );
2513
+ {error , _ } = Err ->
2514
+ Err
2515
+ end ;
2516
+ 1 ->
2517
+ case address_v1_permitted () of
2518
+ true ->
2519
+ case ensure_target_v1 (Address , Vhost , User , Durable , PermCache ) of
2520
+ {ok , XNameBin , RKey , QNameBin , PermCache1 } ->
2521
+ check_exchange (XNameBin , RKey , QNameBin , User , Vhost , PermCache1 );
2522
+ {error , _ } = Err ->
2523
+ Err
2524
+ end ;
2525
+ false ->
2526
+ {error , {amqp_address_v1_not_permitted , Address }}
2527
+ end
2521
2528
end .
2522
2529
2523
2530
check_exchange (XNameBin , RKey , QNameBin , User , Vhost , PermCache0 ) ->
@@ -2539,29 +2546,24 @@ check_exchange(XNameBin, RKey, QNameBin, User, Vhost, PermCache0) ->
2539
2546
exit_not_found (XName )
2540
2547
end .
2541
2548
2542
- ensure_target_v1 ({utf8 , Address }, Vhost , User , Durable , PermCache0 ) ->
2543
- case rabbit_routing_parser :parse_endpoint (Address , true ) of
2544
- {ok , Dest } ->
2545
- {QNameBin , PermCache } = ensure_terminus (
2546
- target , Dest , Vhost , User , Durable , PermCache0 ),
2547
- {XNameList1 , RK } = rabbit_routing_parser :parse_routing (Dest ),
2548
- XNameBin = unicode :characters_to_binary (XNameList1 ),
2549
- RoutingKey = case RK of
2550
- undefined -> subject ;
2551
- [] -> subject ;
2552
- _ -> unicode :characters_to_binary (RK )
2553
- end ,
2554
- {ok , XNameBin , RoutingKey , QNameBin , PermCache };
2555
- {error , _ } = Err ->
2556
- Err
2557
- end ;
2558
- ensure_target_v1 (Address , _ , _ , _ , _ ) ->
2559
- {error , {bad_address , Address }}.
2549
+ address_v1_permitted () ->
2550
+ rabbit_deprecated_features :is_permitted (amqp_address_v1 ).
2551
+
2552
+ target_address_version ({utf8 , <<" /e/" , _ /binary >>}) ->
2553
+ 2 ;
2554
+ target_address_version ({utf8 , <<" /q/" , _ /binary >>}) ->
2555
+ 2 ;
2556
+ target_address_version (undefined ) ->
2557
+ % % anonymous terminus
2558
+ % % https://docs.oasis-open.org/amqp/anonterm/v1.0/cs01/anonterm-v1.0-cs01.html#doc-anonymous-relay
2559
+ 2 ;
2560
+ target_address_version (_Address ) ->
2561
+ 1 .
2560
2562
2561
2563
% % The possible v2 target address formats are:
2562
- % % /exchange /:exchange/key /:routing-key
2563
- % % /exchange /:exchange
2564
- % % /queue /:queue
2564
+ % % /e /:exchange/:routing-key
2565
+ % % /e /:exchange
2566
+ % % /q /:queue
2565
2567
% % <null>
2566
2568
ensure_target_v2 ({utf8 , String }, Vhost ) ->
2567
2569
case parse_target_v2_string (String ) of
@@ -2576,42 +2578,64 @@ ensure_target_v2({utf8, String}, Vhost) ->
2576
2578
ensure_target_v2 (undefined , _ ) ->
2577
2579
% % anonymous terminus
2578
2580
% % https://docs.oasis-open.org/amqp/anonterm/v1.0/cs01/anonterm-v1.0-cs01.html#doc-anonymous-relay
2579
- {ok , to , to , undefined };
2580
- ensure_target_v2 (Address , _ ) ->
2581
- {error , {bad_address , Address }}.
2581
+ {ok , to , to , undefined }.
2582
+
2583
+ parse_target_v2_string (String ) ->
2584
+ try parse_target_v2_string0 (String )
2585
+ catch error :_ ->
2586
+ {error , bad_address }
2587
+ end .
2582
2588
2583
- parse_target_v2_string (<<" /exchange/" , Rest /binary >>) ->
2584
- case split_exchange_target (Rest ) of
2585
- {? DEFAULT_EXCHANGE_NAME , _ } ->
2589
+ parse_target_v2_string0 (<<" /e/" , Rest /binary >>) ->
2590
+ Key = cp_slash ,
2591
+ Pattern = try persistent_term :get (Key )
2592
+ catch error :badarg ->
2593
+ Cp = binary :compile_pattern (<<" /" >>),
2594
+ ok = persistent_term :put (Key , Cp ),
2595
+ Cp
2596
+ end ,
2597
+ case binary :split (Rest , Pattern , [global ]) of
2598
+ [? DEFAULT_EXCHANGE_NAME | _ ] ->
2586
2599
{error , bad_address };
2587
- { <<" amq.default" >>, _ } ->
2600
+ [ <<" amq.default" >> | _ ] ->
2588
2601
{error , bad_address };
2589
- {XNameBin , RKey } ->
2590
- {ok , XNameBin , RKey , undefined }
2602
+ [XNameBinQuoted ] ->
2603
+ XNameBin = rabbit_uri :urldecode (XNameBinQuoted ),
2604
+ {ok , XNameBin , <<>>, undefined };
2605
+ [XNameBinQuoted , RKeyQuoted ] ->
2606
+ XNameBin = rabbit_uri :urldecode (XNameBinQuoted ),
2607
+ RKey = rabbit_uri :urldecode (RKeyQuoted ),
2608
+ {ok , XNameBin , RKey , undefined };
2609
+ _ ->
2610
+ {error , bad_address }
2591
2611
end ;
2592
- parse_target_v2_string (<<" /queue /" >>) ->
2612
+ parse_target_v2_string0 (<<" /q /" >>) ->
2593
2613
% % empty queue name is invalid
2594
2614
{error , bad_address };
2595
- parse_target_v2_string (<<" /queue/" , QNameBin /binary >>) ->
2615
+ parse_target_v2_string0 (<<" /q/" , QNameBinQuoted /binary >>) ->
2616
+ QNameBin = rabbit_uri :urldecode (QNameBinQuoted ),
2596
2617
{ok , ? DEFAULT_EXCHANGE_NAME , QNameBin , QNameBin };
2597
- parse_target_v2_string (_ ) ->
2618
+ parse_target_v2_string0 (_ ) ->
2598
2619
{error , bad_address }.
2599
2620
2600
- % % Empty exchange name (default exchange) is valid.
2601
- split_exchange_target (Target ) ->
2602
- Key = cp_amqp_target_address ,
2603
- Pattern = try persistent_term :get (Key )
2604
- catch error :badarg ->
2605
- Cp = binary :compile_pattern (<<" /key/" >>),
2606
- ok = persistent_term :put (Key , Cp ),
2607
- Cp
2608
- end ,
2609
- case binary :split (Target , Pattern ) of
2610
- [XNameBin ] ->
2611
- {XNameBin , <<>>};
2612
- [XNameBin , RoutingKey ] ->
2613
- {XNameBin , RoutingKey }
2614
- end .
2621
+ ensure_target_v1 ({utf8 , Address }, Vhost , User , Durable , PermCache0 ) ->
2622
+ case rabbit_routing_parser :parse_endpoint (Address , true ) of
2623
+ {ok , Dest } ->
2624
+ {QNameBin , PermCache } = ensure_terminus (
2625
+ target , Dest , Vhost , User , Durable , PermCache0 ),
2626
+ {XNameList1 , RK } = rabbit_routing_parser :parse_routing (Dest ),
2627
+ XNameBin = unicode :characters_to_binary (XNameList1 ),
2628
+ RoutingKey = case RK of
2629
+ undefined -> subject ;
2630
+ [] -> subject ;
2631
+ _ -> unicode :characters_to_binary (RK )
2632
+ end ,
2633
+ {ok , XNameBin , RoutingKey , QNameBin , PermCache };
2634
+ {error , _ } = Err ->
2635
+ Err
2636
+ end ;
2637
+ ensure_target_v1 (Address , _ , _ , _ , _ ) ->
2638
+ {error , {bad_address , Address }}.
2615
2639
2616
2640
handle_outgoing_mgmt_link_flow_control (
2617
2641
# management_link {delivery_count = DeliveryCountSnd } = Link0 ,
@@ -3355,14 +3379,24 @@ error_not_found(Resource) ->
3355
3379
condition = ? V_1_0_AMQP_ERROR_NOT_FOUND ,
3356
3380
description = {utf8 , Description }}.
3357
3381
3358
- address_v1_permitted () ->
3359
- rabbit_deprecated_features :is_permitted (amqp_address_v1 ).
3360
-
3361
3382
-spec cap_credit (rabbit_queue_type :credit ()) ->
3362
3383
0 ..? LINK_CREDIT_RCV_FROM_QUEUE_MAX .
3363
3384
cap_credit (DesiredCredit ) ->
3364
3385
min (DesiredCredit , ? LINK_CREDIT_RCV_FROM_QUEUE_MAX ).
3365
3386
3387
+ ensure_mc_cluster_compat (Mc ) ->
3388
+ IsEnabled = rabbit_feature_flags :is_enabled (message_containers_store_amqp_v1 ),
3389
+ case IsEnabled of
3390
+ true ->
3391
+ Mc ;
3392
+ false ->
3393
+ McEnv = #{message_containers_store_amqp_v1 => IsEnabled },
3394
+ % % other nodes in the cluster may not understand the new internal
3395
+ % % amqp mc format - in this case we convert to AMQP legacy format
3396
+ % % for compatibility
3397
+ mc :convert (mc_amqpl , Mc , McEnv )
3398
+ end .
3399
+
3366
3400
format_status (
3367
3401
#{state := # state {cfg = Cfg ,
3368
3402
outgoing_pending = OutgoingPending ,
@@ -3407,16 +3441,3 @@ format_status(
3407
3441
permission_cache => PermissionCache ,
3408
3442
topic_permission_cache => TopicPermissionCache },
3409
3443
maps :update (state , State , Status ).
3410
-
3411
- ensure_mc_cluster_compat (Mc ) ->
3412
- IsEnabled = rabbit_feature_flags :is_enabled (message_containers_store_amqp_v1 ),
3413
- case IsEnabled of
3414
- true ->
3415
- Mc ;
3416
- false ->
3417
- McEnv = #{message_containers_store_amqp_v1 => IsEnabled },
3418
- % % other nodes in the cluster may not understand the new internal
3419
- % % amqp mc format - in this case we convert to AMQP legacy format
3420
- % % for compatibility
3421
- mc :convert (mc_amqpl , Mc , McEnv )
3422
- end .
0 commit comments