bunny 3.4.0 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ChangeLog.md +59 -2
- data/README.md +2 -2
- data/lib/bunny/channel.rb +54 -17
- data/lib/bunny/delivery_info.rb +13 -6
- data/lib/bunny/exchange.rb +0 -3
- data/lib/bunny/queue.rb +0 -3
- data/lib/bunny/session.rb +13 -1
- data/lib/bunny/transport.rb +7 -7
- data/lib/bunny/version.rb +1 -1
- data/lib/bunny.rb +3 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d0192b4541ec169e249317d397768bf5e945b43c08b797559a47adb5aa16d553
|
|
4
|
+
data.tar.gz: 6a460e9bdbb8ee073c28f6aa7c9bdcc4ab017929d6a6e298eb49ba01db1059df
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a01fbb4c9cbfe312b803026b86dca339b1ba306aa1ad3f44cb77abaf26f28ec823a57bee2231ca1b29de03e5b31355a70e2a6b8eb066be465f9fb85f052fa616
|
|
7
|
+
data.tar.gz: 3b752e1f17c5d40a155c49fbdf53f437ad450a4c31a74ffc791b8dfd5079029b0f5242dc0d573b349ce7248d7474ae15211e214a8797b0487759d7a69a0aadfe
|
data/ChangeLog.md
CHANGED
|
@@ -1,11 +1,68 @@
|
|
|
1
|
+
## Changes between Bunny 3.5.0 and 3.6.0 (Nov 9, 2026)
|
|
2
|
+
|
|
3
|
+
### `amq-protocol` Bump to `2.10.0`
|
|
4
|
+
|
|
5
|
+
[`2.10.0` release notes](https://github.com/ruby-amqp/amq-protocol/releases/tag/v2.10.0).
|
|
6
|
+
|
|
7
|
+
`amqps://` URIs without `?verify=` no longer disable peer verification.
|
|
8
|
+
|
|
9
|
+
### TLSv1.2 Is Now a Minimum, Not a Pinned Version
|
|
10
|
+
|
|
11
|
+
Without an explicit `tls_protocol`, TLS 1.3 is no longer ruled out.
|
|
12
|
+
|
|
13
|
+
GitHub issue: [#760](https://github.com/ruby-amqp/bunny/issues/760)
|
|
14
|
+
|
|
15
|
+
### New `tls_min_version` and `tls_max_version` Options
|
|
16
|
+
|
|
17
|
+
They set the range of TLS versions to negotiate and accept strings as well as symbols.
|
|
18
|
+
`tls_protocol`, which pins a single version, is deprecated in their favor and now emits a warning.
|
|
19
|
+
|
|
20
|
+
### Stale Delivery Tags Are Not Acknowledged After `Channel#reopen` or Connection Recovery
|
|
21
|
+
|
|
22
|
+
Delivery tags now keep increasing across a reopen or recovery instead of restarting at 1.
|
|
23
|
+
Acknowledgements for tags from before it are dropped instead of closing the channel or
|
|
24
|
+
acknowledging a different delivery.
|
|
25
|
+
|
|
26
|
+
GitHub issue: [#710](https://github.com/ruby-amqp/bunny/issues/710)
|
|
27
|
+
|
|
28
|
+
### `Channel#reopen` No Longer Leaks a Consumer Work Pool Thread
|
|
29
|
+
|
|
30
|
+
Topology recovery replaced the consumer work pool `Channel#reopen` had just started, leaking its thread.
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## Changes between Bunny 3.4.0 and 3.5.0 (Oct 25, 2026)
|
|
34
|
+
|
|
35
|
+
### `no_declare: true` Is Respected by Topology Recovery
|
|
36
|
+
|
|
37
|
+
Queues and exchanges instantiated with `no_declare: true` are no longer redeclared during recovery.
|
|
38
|
+
|
|
39
|
+
GitHub issue: [#751](https://github.com/ruby-amqp/bunny/issues/751)
|
|
40
|
+
|
|
41
|
+
### `basic.cancel-ok` for Server-Initiated Consumer Cancellations
|
|
42
|
+
|
|
43
|
+
For RabbitMQ versions that declare a corresponding capability, Bunny now responds to a
|
|
44
|
+
server-sent `basic.cancel` with a `basic.cancel-ok`.
|
|
45
|
+
|
|
46
|
+
See [rabbitmq/rabbitmq-server#17734](https://github.com/rabbitmq/rabbitmq-server/issues/17734) and [rabbitmq/rabbitmq-java-client#2113](https://github.com/rabbitmq/rabbitmq-java-client/issues/2113) for context.
|
|
47
|
+
|
|
48
|
+
### `Bunny::Session#server_has_capability?`
|
|
49
|
+
|
|
50
|
+
New `Bunny::Session#server_has_capability?` takes a capability name as a symbol.
|
|
51
|
+
|
|
52
|
+
### `Bunny::DeliveryInfo#to_s` and `#inspect` Use Channel and Consumer Identifiers
|
|
53
|
+
|
|
54
|
+
`Bunny::DeliveryInfo#to_s` and `#inspect` now include the channel number and consumer tag
|
|
55
|
+
but avoid printing the actual data structures.
|
|
56
|
+
|
|
57
|
+
See [ruby-amqp/kicks#48](https://github.com/ruby-amqp/kicks/pull/48) for background.
|
|
58
|
+
|
|
59
|
+
|
|
1
60
|
## Changes between Bunny 3.3.0 and 3.4.0 (Sep 18, 2026)
|
|
2
61
|
|
|
3
62
|
### Ruby 3.2 or Later Is Now Required
|
|
4
63
|
|
|
5
64
|
`required_ruby_version` was raised from `3.0` to `3.2`.
|
|
6
65
|
|
|
7
|
-
Ruby `3.0` and `3.1` have reached end of life and are no longer tested against.
|
|
8
|
-
|
|
9
66
|
|
|
10
67
|
### Client Certificate Chains
|
|
11
68
|
|
data/README.md
CHANGED
|
@@ -95,7 +95,7 @@ may introduce, e.g. the idempotency of `queue.delete` operations.
|
|
|
95
95
|
To use Bunny in a project managed with Bundler:
|
|
96
96
|
|
|
97
97
|
``` ruby
|
|
98
|
-
gem "bunny", ">= 3.
|
|
98
|
+
gem "bunny", ">= 3.5"
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
### With Rubygems
|
|
@@ -218,7 +218,7 @@ and steps to reproduce (or failing test cases).
|
|
|
218
218
|
## Other Ruby RabbitMQ Clients
|
|
219
219
|
|
|
220
220
|
The other widely used Ruby RabbitMQ client is [March Hare](http://rubymarchhare.info) (JRuby-only).
|
|
221
|
-
It's a mature library that requires RabbitMQ 3.
|
|
221
|
+
It's a mature library that requires RabbitMQ 3.13.x or later.
|
|
222
222
|
|
|
223
223
|
|
|
224
224
|
## Contributing
|
data/lib/bunny/channel.rb
CHANGED
|
@@ -196,6 +196,7 @@ module Bunny
|
|
|
196
196
|
end
|
|
197
197
|
|
|
198
198
|
@status = :opening
|
|
199
|
+
@status_mutex = Mutex.new
|
|
199
200
|
@connection.register_channel(self)
|
|
200
201
|
|
|
201
202
|
@queues = Hash.new
|
|
@@ -233,6 +234,11 @@ module Bunny
|
|
|
233
234
|
@next_publish_seq_no = 0
|
|
234
235
|
@delivery_tag_offset = 0
|
|
235
236
|
|
|
237
|
+
# Delivery tags restart at 1 on a reopened or recovered channel. Shifting them
|
|
238
|
+
# by the highest tag seen so far keeps them unique, see #guarding_against_stale_delivery_tags.
|
|
239
|
+
@consumer_delivery_tag_offset = 0
|
|
240
|
+
@last_consumer_delivery_tag = 0
|
|
241
|
+
|
|
236
242
|
@uncaught_exception_handler = Proc.new do |e, consumer|
|
|
237
243
|
@logger.error "Uncaught exception from consumer #{consumer.to_s}: #{e.inspect} @ #{e.backtrace[0]}"
|
|
238
244
|
end
|
|
@@ -255,6 +261,8 @@ module Bunny
|
|
|
255
261
|
@threads_waiting_on_continuations = Set.new
|
|
256
262
|
@threads_waiting_on_confirms_continuations = Set.new
|
|
257
263
|
@threads_waiting_on_basic_get_continuations = Set.new
|
|
264
|
+
# Set before the channel is open again, so that no stale tag slips through
|
|
265
|
+
@consumer_delivery_tag_offset = @last_consumer_delivery_tag
|
|
258
266
|
|
|
259
267
|
@connection.open_channel(self)
|
|
260
268
|
# clear last channel error
|
|
@@ -290,6 +298,8 @@ module Bunny
|
|
|
290
298
|
end
|
|
291
299
|
end
|
|
292
300
|
|
|
301
|
+
# once channel.close is on the wire, the server rejects any other frame on this channel
|
|
302
|
+
@status_mutex.synchronize { @status = :closing }
|
|
293
303
|
@connection.close_channel(self)
|
|
294
304
|
@status = :closed
|
|
295
305
|
@work_pool.shutdown
|
|
@@ -523,7 +533,6 @@ module Bunny
|
|
|
523
533
|
|
|
524
534
|
q = find_queue(name) || Bunny::Queue.new(self, name, opts)
|
|
525
535
|
|
|
526
|
-
record_queue(q) unless opts[:passive]
|
|
527
536
|
register_queue(q)
|
|
528
537
|
end
|
|
529
538
|
|
|
@@ -652,7 +661,6 @@ module Bunny
|
|
|
652
661
|
)
|
|
653
662
|
q = find_queue(name) || Bunny::Queue.new(self, name, final_opts)
|
|
654
663
|
|
|
655
|
-
record_queue(q)
|
|
656
664
|
register_queue(q)
|
|
657
665
|
end
|
|
658
666
|
|
|
@@ -1043,10 +1051,12 @@ module Bunny
|
|
|
1043
1051
|
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
|
1044
1052
|
# @api public
|
|
1045
1053
|
def basic_reject(delivery_tag, requeue = false)
|
|
1046
|
-
|
|
1047
|
-
|
|
1054
|
+
guarding_against_stale_delivery_tags(delivery_tag) do |tag|
|
|
1055
|
+
raise_if_no_longer_open!
|
|
1056
|
+
@connection.send_frame(AMQ::Protocol::Basic::Reject.encode(@id, tag, requeue))
|
|
1048
1057
|
|
|
1049
|
-
|
|
1058
|
+
nil
|
|
1059
|
+
end
|
|
1050
1060
|
end
|
|
1051
1061
|
|
|
1052
1062
|
# Acknowledges a delivery (message).
|
|
@@ -1089,9 +1099,9 @@ module Bunny
|
|
|
1089
1099
|
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
|
1090
1100
|
# @api public
|
|
1091
1101
|
def basic_ack(delivery_tag, multiple = false)
|
|
1092
|
-
guarding_against_stale_delivery_tags(delivery_tag) do
|
|
1102
|
+
guarding_against_stale_delivery_tags(delivery_tag) do |tag|
|
|
1093
1103
|
raise_if_no_longer_open!
|
|
1094
|
-
@connection.send_frame(AMQ::Protocol::Basic::Ack.encode(@id,
|
|
1104
|
+
@connection.send_frame(AMQ::Protocol::Basic::Ack.encode(@id, tag, multiple))
|
|
1095
1105
|
|
|
1096
1106
|
nil
|
|
1097
1107
|
end
|
|
@@ -1151,10 +1161,10 @@ module Bunny
|
|
|
1151
1161
|
# @see http://rubybunny.info/articles/extensions.html RabbitMQ Extensions guide
|
|
1152
1162
|
# @api public
|
|
1153
1163
|
def basic_nack(delivery_tag, multiple = false, requeue = false)
|
|
1154
|
-
guarding_against_stale_delivery_tags(delivery_tag) do
|
|
1164
|
+
guarding_against_stale_delivery_tags(delivery_tag) do |tag|
|
|
1155
1165
|
raise_if_no_longer_open!
|
|
1156
1166
|
@connection.send_frame(AMQ::Protocol::Basic::Nack.encode(@id,
|
|
1157
|
-
|
|
1167
|
+
tag,
|
|
1158
1168
|
multiple,
|
|
1159
1169
|
requeue))
|
|
1160
1170
|
|
|
@@ -2036,7 +2046,8 @@ module Bunny
|
|
|
2036
2046
|
#
|
|
2037
2047
|
# @api private
|
|
2038
2048
|
def maybe_reinitialize_consumer_pool!
|
|
2039
|
-
|
|
2049
|
+
# keep a pool that is already running, e.g. the one #reopen has just started
|
|
2050
|
+
unless @consumers.empty? || @work_pool.running?
|
|
2040
2051
|
@work_pool = ConsumerWorkPool.new(@work_pool.size, @work_pool.abort_on_exception)
|
|
2041
2052
|
@work_pool.start
|
|
2042
2053
|
end
|
|
@@ -2130,6 +2141,15 @@ module Bunny
|
|
|
2130
2141
|
pending_server_named_queue_declaration?
|
|
2131
2142
|
end
|
|
2132
2143
|
|
|
2144
|
+
# @private
|
|
2145
|
+
def send_basic_cancel_ok(consumer_tag)
|
|
2146
|
+
tag = consumer_tag.to_s
|
|
2147
|
+
payload = [AMQ::Protocol::Basic::CancelOk.index, tag.bytesize, tag].pack("NCa*")
|
|
2148
|
+
@status_mutex.synchronize do
|
|
2149
|
+
@connection.send_frame(AMQ::Protocol::MethodFrame.new(payload, @id)) if open?
|
|
2150
|
+
end
|
|
2151
|
+
end
|
|
2152
|
+
|
|
2133
2153
|
# @private
|
|
2134
2154
|
def handle_method(method)
|
|
2135
2155
|
@logger.debug { "Channel#handle_frame on channel #{@id}: #{method.inspect}" }
|
|
@@ -2171,6 +2191,8 @@ module Bunny
|
|
|
2171
2191
|
when AMQ::Protocol::Basic::ConsumeOk then
|
|
2172
2192
|
@continuations.push(method)
|
|
2173
2193
|
when AMQ::Protocol::Basic::Cancel then
|
|
2194
|
+
send_basic_cancel_ok(method.consumer_tag) if @connection.server_has_capability?(:accept_consumer_cancel_ok)
|
|
2195
|
+
|
|
2174
2196
|
if consumer = @consumers[method.consumer_tag]
|
|
2175
2197
|
@work_pool.submit do
|
|
2176
2198
|
begin
|
|
@@ -2237,7 +2259,7 @@ module Bunny
|
|
|
2237
2259
|
|
|
2238
2260
|
# @private
|
|
2239
2261
|
def handle_basic_get_ok(basic_get_ok, properties, content)
|
|
2240
|
-
basic_get_ok.delivery_tag = basic_get_ok.delivery_tag
|
|
2262
|
+
basic_get_ok.delivery_tag = next_consumer_delivery_tag(basic_get_ok.delivery_tag)
|
|
2241
2263
|
@basic_get_continuations.push([basic_get_ok, properties, content])
|
|
2242
2264
|
end
|
|
2243
2265
|
|
|
@@ -2257,9 +2279,11 @@ module Bunny
|
|
|
2257
2279
|
@last_consumer = consumer
|
|
2258
2280
|
end
|
|
2259
2281
|
|
|
2282
|
+
# the server counts deliveries for unknown consumers as well
|
|
2283
|
+
delivery_tag = next_consumer_delivery_tag(basic_deliver.delivery_tag)
|
|
2260
2284
|
if consumer
|
|
2261
2285
|
@work_pool.submit do
|
|
2262
|
-
deliver_to_consumer(consumer, basic_deliver, properties, content)
|
|
2286
|
+
deliver_to_consumer(consumer, basic_deliver, properties, content, delivery_tag)
|
|
2263
2287
|
end
|
|
2264
2288
|
else
|
|
2265
2289
|
@logger.warn "No consumer for tag #{basic_deliver.consumer_tag} on channel #{@id}!"
|
|
@@ -2267,9 +2291,9 @@ module Bunny
|
|
|
2267
2291
|
end
|
|
2268
2292
|
|
|
2269
2293
|
# @private
|
|
2270
|
-
def deliver_to_consumer(consumer, basic_deliver, properties, content)
|
|
2294
|
+
def deliver_to_consumer(consumer, basic_deliver, properties, content, delivery_tag = basic_deliver.delivery_tag)
|
|
2271
2295
|
begin
|
|
2272
|
-
consumer.call(DeliveryInfo.new(basic_deliver, consumer, self), MessageProperties.new(properties), content)
|
|
2296
|
+
consumer.call(DeliveryInfo.new(basic_deliver, consumer, self, delivery_tag), MessageProperties.new(properties), content)
|
|
2273
2297
|
rescue StandardError => e
|
|
2274
2298
|
@uncaught_exception_handler.call(e, consumer) if @uncaught_exception_handler
|
|
2275
2299
|
end
|
|
@@ -2717,11 +2741,24 @@ module Bunny
|
|
|
2717
2741
|
Concurrent::ContinuationQueue.new
|
|
2718
2742
|
end
|
|
2719
2743
|
|
|
2744
|
+
# @private
|
|
2745
|
+
def next_consumer_delivery_tag(tag)
|
|
2746
|
+
@last_consumer_delivery_tag = tag + @consumer_delivery_tag_offset
|
|
2747
|
+
end
|
|
2748
|
+
|
|
2749
|
+
# A tag at or below the offset was delivered before the channel was reopened or recovered.
|
|
2750
|
+
# RabbitMQ has requeued that delivery already, and acknowledging it here would close the channel
|
|
2751
|
+
# with an unknown delivery tag, or acknowledge a different delivery.
|
|
2720
2752
|
# @private
|
|
2721
2753
|
def guarding_against_stale_delivery_tags(tag, &block)
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2754
|
+
return unless tag.is_a?(Integer)
|
|
2755
|
+
# 0 with multiple set covers all outstanding deliveries
|
|
2756
|
+
return block.call(tag) if tag.zero?
|
|
2757
|
+
# read once, a concurrent #open may change it
|
|
2758
|
+
offset = @consumer_delivery_tag_offset
|
|
2759
|
+
return if tag <= offset
|
|
2760
|
+
|
|
2761
|
+
block.call(tag - offset)
|
|
2725
2762
|
end
|
|
2726
2763
|
end # Channel
|
|
2727
2764
|
end # Bunny
|
data/lib/bunny/delivery_info.rb
CHANGED
|
@@ -22,10 +22,11 @@ module Bunny
|
|
|
22
22
|
attr_reader :channel
|
|
23
23
|
|
|
24
24
|
# @private
|
|
25
|
-
def initialize(basic_deliver, consumer, channel)
|
|
25
|
+
def initialize(basic_deliver, consumer, channel, delivery_tag = basic_deliver.delivery_tag)
|
|
26
26
|
@basic_deliver = basic_deliver
|
|
27
27
|
@consumer = consumer
|
|
28
28
|
@channel = channel
|
|
29
|
+
@delivery_tag = delivery_tag
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
# Iterates over delivery properties
|
|
@@ -39,7 +40,7 @@ module Bunny
|
|
|
39
40
|
def [](k)
|
|
40
41
|
case k
|
|
41
42
|
when :consumer_tag then @basic_deliver.consumer_tag
|
|
42
|
-
when :delivery_tag then @
|
|
43
|
+
when :delivery_tag then @delivery_tag
|
|
43
44
|
when :redelivered then @basic_deliver.redelivered
|
|
44
45
|
when :exchange then @basic_deliver.exchange
|
|
45
46
|
when :routing_key then @basic_deliver.routing_key
|
|
@@ -53,7 +54,7 @@ module Bunny
|
|
|
53
54
|
def to_hash
|
|
54
55
|
@hash ||= {
|
|
55
56
|
consumer_tag: @basic_deliver.consumer_tag,
|
|
56
|
-
delivery_tag: @
|
|
57
|
+
delivery_tag: @delivery_tag,
|
|
57
58
|
redelivered: @basic_deliver.redelivered,
|
|
58
59
|
exchange: @basic_deliver.exchange,
|
|
59
60
|
routing_key: @basic_deliver.routing_key,
|
|
@@ -64,12 +65,12 @@ module Bunny
|
|
|
64
65
|
|
|
65
66
|
# @private
|
|
66
67
|
def to_s
|
|
67
|
-
|
|
68
|
+
printable_hash.to_s
|
|
68
69
|
end
|
|
69
70
|
|
|
70
71
|
# @private
|
|
71
72
|
def inspect
|
|
72
|
-
|
|
73
|
+
printable_hash.inspect
|
|
73
74
|
end
|
|
74
75
|
|
|
75
76
|
# @return [String] Consumer tag this delivery is for
|
|
@@ -79,7 +80,7 @@ module Bunny
|
|
|
79
80
|
|
|
80
81
|
# @return [String] Delivery identifier that is used to acknowledge, reject and nack deliveries
|
|
81
82
|
def delivery_tag
|
|
82
|
-
@
|
|
83
|
+
@delivery_tag
|
|
83
84
|
end
|
|
84
85
|
|
|
85
86
|
# @return [Boolean] true if this delivery is a redelivery (the message was requeued at least once)
|
|
@@ -97,5 +98,11 @@ module Bunny
|
|
|
97
98
|
def routing_key
|
|
98
99
|
@basic_deliver.routing_key
|
|
99
100
|
end
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
def printable_hash
|
|
105
|
+
to_hash.merge(consumer: @consumer&.consumer_tag, channel: @channel&.number)
|
|
106
|
+
end
|
|
100
107
|
end
|
|
101
108
|
end
|
data/lib/bunny/exchange.rb
CHANGED
|
@@ -108,9 +108,6 @@ module Bunny
|
|
|
108
108
|
|
|
109
109
|
# for basic.return dispatch and such
|
|
110
110
|
@channel.register_exchange(self)
|
|
111
|
-
# for topology recovery. A passive declaration does not own the exchange,
|
|
112
|
-
# so it must not overwrite what was recorded for it earlier
|
|
113
|
-
@channel.record_exchange(self) unless @options[:passive]
|
|
114
111
|
end
|
|
115
112
|
|
|
116
113
|
# @return [Boolean] true if this exchange was declared as durable (will survive broker restart).
|
data/lib/bunny/queue.rb
CHANGED
|
@@ -91,9 +91,6 @@ module Bunny
|
|
|
91
91
|
|
|
92
92
|
# for basic.deliver dispatch and such
|
|
93
93
|
@channel.register_queue(self)
|
|
94
|
-
# for topology recovery. A passive declaration does not own the queue,
|
|
95
|
-
# so it must not overwrite what was recorded for it earlier
|
|
96
|
-
@channel.record_queue(self) unless @options[:passive]
|
|
97
94
|
end
|
|
98
95
|
|
|
99
96
|
# @return [Boolean] true if this queue was declared as durable (will survive broker restart).
|
data/lib/bunny/session.rb
CHANGED
|
@@ -112,7 +112,9 @@ module Bunny
|
|
|
112
112
|
# @option connection_string_or_opts [String] :tls_key (nil) Path to client TLS/SSL private key file (.pem)
|
|
113
113
|
# @option connection_string_or_opts [Array<String>] :tls_ca_certificates Array of paths to TLS/SSL CA files (.pem), by default detected from OpenSSL configuration
|
|
114
114
|
# @option connection_string_or_opts [String] :verify_peer (true) Whether TLS peer verification should be performed
|
|
115
|
-
# @option connection_string_or_opts [Symbol] :tls_protocol (
|
|
115
|
+
# @option connection_string_or_opts [Symbol] :tls_protocol (nil) [DEPRECATED] Use :tls_min_version and :tls_max_version instead. Pins the TLS version (:TLSv1, :TLSv1_1, :TLSv1_2 or :TLSv1_3)
|
|
116
|
+
# @option connection_string_or_opts [Symbol, String] :tls_min_version (:TLSv1_2) Lowest TLS version to negotiate, ignored when :tls_protocol is set
|
|
117
|
+
# @option connection_string_or_opts [Symbol, String] :tls_max_version (nil) Highest TLS version to negotiate, ignored when :tls_protocol is set
|
|
116
118
|
# @option connection_string_or_opts [Integer] :channel_max (2047) Maximum number of channels allowed on this connection, minus 1 to account for the special channel 0.
|
|
117
119
|
# @option connection_string_or_opts [Integer] :continuation_timeout (15000) Timeout for client operations that expect a response (e.g. {Bunny::Queue#get}), in milliseconds.
|
|
118
120
|
# @option connection_string_or_opts [Integer] :connection_timeout (30) Timeout in seconds for connecting to the server.
|
|
@@ -251,6 +253,10 @@ module Bunny
|
|
|
251
253
|
if (options[:host] || options[:hostname]) && (options[:hosts] || options[:addresses])
|
|
252
254
|
@logger.warn "Connection options contain both a host and an array of hosts (addresses), please pick one."
|
|
253
255
|
end
|
|
256
|
+
|
|
257
|
+
if options[:tls_protocol] || options[:ssl_version]
|
|
258
|
+
warn "[DEPRECATION] `:tls_protocol` is deprecated. Please use `:tls_min_version` and `:tls_max_version` instead."
|
|
259
|
+
end
|
|
254
260
|
end
|
|
255
261
|
|
|
256
262
|
# @return [String] RabbitMQ hostname (or IP address) used
|
|
@@ -1593,6 +1599,12 @@ module Bunny
|
|
|
1593
1599
|
to_s
|
|
1594
1600
|
end
|
|
1595
1601
|
|
|
1602
|
+
# @param [Symbol] capability a server capability name
|
|
1603
|
+
# @return [Boolean] true if the server advertises the capability as supported
|
|
1604
|
+
def server_has_capability?(capability)
|
|
1605
|
+
(@server_capabilities || {})[capability.to_s] == true
|
|
1606
|
+
end
|
|
1607
|
+
|
|
1596
1608
|
protected
|
|
1597
1609
|
|
|
1598
1610
|
# @private
|
data/lib/bunny/transport.rb
CHANGED
|
@@ -42,7 +42,7 @@ module Bunny
|
|
|
42
42
|
# older OpenSSL versions won't support for TLS 1.3 and won't
|
|
43
43
|
# have this constant defined.
|
|
44
44
|
if defined?(OpenSSL::SSL::TLS1_3_VERSION)
|
|
45
|
-
TLS_VERSION_ALIASES["1.3"]
|
|
45
|
+
TLS_VERSION_ALIASES[:"1.3"] = OpenSSL::SSL::TLS1_3_VERSION
|
|
46
46
|
TLS_VERSION_ALIASES[:TLSv1_3] = OpenSSL::SSL::TLS1_3_VERSION
|
|
47
47
|
TLS_VERSION_ALIASES[OpenSSL::SSL::TLS1_3_VERSION] = OpenSSL::SSL::TLS1_3_VERSION
|
|
48
48
|
end
|
|
@@ -538,12 +538,11 @@ but prone to man-in-the-middle attacks. Please set verify_peer: true in producti
|
|
|
538
538
|
MSG
|
|
539
539
|
end
|
|
540
540
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
end
|
|
541
|
+
pinned = opts[:tls_protocol] || opts[:ssl_version]
|
|
542
|
+
min = pinned || opts[:tls_min_version] || :TLSv1_2
|
|
543
|
+
max = pinned || opts[:tls_max_version]
|
|
544
|
+
ctx.min_version = tls_version_constant(min)
|
|
545
|
+
ctx.max_version = tls_version_constant(max) if max
|
|
547
546
|
|
|
548
547
|
ctx
|
|
549
548
|
end
|
|
@@ -576,6 +575,7 @@ but prone to man-in-the-middle attacks. Please set verify_peer: true in producti
|
|
|
576
575
|
# OpenSSL::SSL::TLS1_3_VERSION and similar constants
|
|
577
576
|
# are just integers, so use the value itself as fallback since
|
|
578
577
|
# there is no class to case switch on
|
|
578
|
+
value = value.to_sym if value.is_a?(String)
|
|
579
579
|
TLS_VERSION_ALIASES[value] || value
|
|
580
580
|
end
|
|
581
581
|
|
data/lib/bunny/version.rb
CHANGED
data/lib/bunny.rb
CHANGED
|
@@ -71,7 +71,9 @@ module Bunny
|
|
|
71
71
|
# @option connection_string_or_opts [String] :tls_key (nil) Path to client TLS/SSL private key file (.pem)
|
|
72
72
|
# @option connection_string_or_opts [Array<String>] :tls_ca_certificates Array of paths to TLS/SSL CA files (.pem), by default detected from OpenSSL configuration
|
|
73
73
|
# @option connection_string_or_opts [String] :verify_peer (true) Whether TLS peer verification should be performed
|
|
74
|
-
# @option connection_string_or_opts [Symbol] :tls_protocol (
|
|
74
|
+
# @option connection_string_or_opts [Symbol] :tls_protocol (nil) [DEPRECATED] Use :tls_min_version and :tls_max_version instead. Pins the TLS version (:TLSv1, :TLSv1_1, :TLSv1_2 or :TLSv1_3)
|
|
75
|
+
# @option connection_string_or_opts [Symbol, String] :tls_min_version (:TLSv1_2) Lowest TLS version to negotiate, ignored when :tls_protocol is set
|
|
76
|
+
# @option connection_string_or_opts [Symbol, String] :tls_max_version (nil) Highest TLS version to negotiate, ignored when :tls_protocol is set
|
|
75
77
|
# @option connection_string_or_opts [Integer] :channel_max (2047) Maximum number of channels allowed on this connection, minus 1 to account for the special channel 0.
|
|
76
78
|
# @option connection_string_or_opts [Integer] :continuation_timeout (15000) Timeout for client operations that expect a response (e.g. {Bunny::Queue#get}), in milliseconds.
|
|
77
79
|
# @option connection_string_or_opts [Integer] :connection_timeout (30) Timeout in seconds for connecting to the server.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bunny
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris Duncan
|
|
@@ -19,14 +19,14 @@ dependencies:
|
|
|
19
19
|
requirements:
|
|
20
20
|
- - "~>"
|
|
21
21
|
- !ruby/object:Gem::Version
|
|
22
|
-
version: '2.
|
|
22
|
+
version: '2.10'
|
|
23
23
|
type: :runtime
|
|
24
24
|
prerelease: false
|
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
26
|
requirements:
|
|
27
27
|
- - "~>"
|
|
28
28
|
- !ruby/object:Gem::Version
|
|
29
|
-
version: '2.
|
|
29
|
+
version: '2.10'
|
|
30
30
|
- !ruby/object:Gem::Dependency
|
|
31
31
|
name: logger
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|