rabbitmq_http_api_client 1.12.0 → 3.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4bb6d6b0972f2f811e0a010aa2c41b8fbf64d7d056b380e513848970290f9593
4
- data.tar.gz: 2ed34cedaf2289ec3c1d63ec10abedd91ce748e68996495867373db1f5e2a133
3
+ metadata.gz: b9fe9cd3da39f8ad9d88cab48895b67278e5df0e5df8f5a397660bc6c73af671
4
+ data.tar.gz: cd233d873f713a5ec50a751a8a58992920f3f03761c8f18b313207febf57acb3
5
5
  SHA512:
6
- metadata.gz: 0d8e6de34019754d1b032b9cee0709504a6104bf9210031314b9535229ec2c85f129cce436c520947290ea58e6ba620bfd1c0fff6b805275833cad20d6f892e6
7
- data.tar.gz: 6e12a66d286621b511a2d20ea148cb90812c196222be39eed12d9d8c2ce42160fd2f893e3dbc2c521182c569cfb77caca9fca88e2492aec1da56da02b206d040
6
+ metadata.gz: a72745520c25dfbc6f5133dc6978b2ff4739ec3f8f56c4e344497a75f9716f7930d1c17fbf93f07a4e544818567d987f5d795ec2ede94e191a030627b2cb835a
7
+ data.tar.gz: 53c18efe60eec7b84f3e0738e6d7e04b76a796cdf6a15746fb9574cbf7becb5a379891fff9a9a8d88475df3e2bf619aa7d227ec6de872e37a5acaa66ba00152a
data/ChangeLog.md CHANGED
@@ -1,6 +1,129 @@
1
- ## Changes Between 1.12.0 and 1.13.0 (unreleased)
1
+ ## Changes Between 2.2.0 and 3.0.0 (July 20, 2024)
2
2
 
3
- No changes yet.
3
+ ### Why the Major Version Bump?
4
+
5
+ This release adopts a new major version of Faraday and targets
6
+ only [community supported RabbitMQ versions](https://www.rabbitmq.com/release-information),
7
+ which at this time means `3.13.x`.
8
+
9
+ While there are no major breaking changes in the library itself,
10
+ these two changes and more than two years that have passed since 2.0.0
11
+ warrant a major version bump.
12
+
13
+ ### Support for Faraday 2.x
14
+
15
+ Contributed by @shashankmehra.
16
+
17
+ GitHub issue: [#63](https://github.com/ruby-amqp/rabbitmq_http_api_client/pull/63)
18
+
19
+ ### Queue Deletion: Support for if-unused and if-empty
20
+
21
+ Contributed by @shashankmehra.
22
+
23
+ GitHub issue: [#62](https://github.com/ruby-amqp/rabbitmq_http_api_client/pull/62)
24
+
25
+
26
+ ## Changes Between 2.1.0 and 2.2.0 (May 19, 2022)
27
+
28
+ Test suite and CI automation changes.
29
+
30
+
31
+ ## Changes Between 2.0.0 and 2.1.0 (February 12, 2022)
32
+
33
+ ### Handle Responses that Do Not Contain a Body
34
+
35
+ GitHub issue: [#52](https://github.com/ruby-amqp/rabbitmq_http_api_client/issues/52)
36
+
37
+ ### Support for Management of Topic Permissions
38
+
39
+ Contributed by @bagedevimo.
40
+
41
+ GitHub issue: [#57](https://github.com/ruby-amqp/rabbitmq_http_api_client/issues/57)
42
+
43
+ ### Upgraded Faraday Middleware
44
+
45
+ Faraday (a dependency) has been upgraded to `1.2.x` to eliminate some deprecation warnings.
46
+
47
+
48
+ ## Changes Between 1.15.0 and 2.0.0 (May 21, 2021)
49
+
50
+ ### Health Check Endpoint Changes
51
+
52
+ `RabbitMQ::HTTP::Client#aliveness_test` has been removed. The endpoint has been deprecated
53
+ in favor of [more focussed health check endpoints](https://www.rabbitmq.com/monitoring.html#health-checks):
54
+
55
+ ``` ruby
56
+ c = RabbitMQ::HTTP::Client.new("http://username:s3kRe7@localhost:15672")
57
+
58
+ # Returns a pair of [success, details]. Details will be nil
59
+ # if the check succeeds.
60
+ #
61
+ # Checks for any alarms across the cluster
62
+ passed, details = c.health.check_alarms
63
+
64
+ # alarms on the given node
65
+ passed, details = c.health.check_local_alarms
66
+
67
+ # is this node essential for an online quorum of any quorum queues?
68
+ passed, details = c.health.check_if_node_is_quorum_critical
69
+
70
+ # do any certificates used by this node's TLS listeners expire within
71
+ # three months?
72
+ passed, details = c.health.check_certificate_expiration(3, "months")
73
+ ```
74
+
75
+ See the list of methods in `RabbitMQ::HTTP::HealthChecks` to find out what other
76
+ health checks are available.
77
+
78
+ ### User Tags Type Change
79
+
80
+ User tags returned by the `RabbitMQ::HTTP::Client#list_users` and `RabbitMQ::HTTP::Client#user_info`
81
+ methods are now arrays of strings instead of comma-separated strings.
82
+
83
+ Internally the method encodes both command-separated strings and JSON arrays in API responses
84
+ to support response types from RabbitMQ 3.9 and earlier versions.
85
+
86
+ See [rabbitmq/rabbitmq-server#2676](https://github.com/rabbitmq/rabbitmq-server/pull/2676) for details.
87
+
88
+ ## Changes Between 1.14.0 and 1.15.0 (February 16th, 2021)
89
+ ### Content Length Detection Changes
90
+
91
+ When deserialising response bodies, the client now uses actual body length instead of
92
+ the value of the `content-length` header.
93
+
94
+ Contributed by Ryan @rquant Quant.
95
+
96
+ GitHub issue: [#49](https://github.com/ruby-amqp/rabbitmq_http_api_client/pull/49)
97
+
98
+
99
+ ## Changes Between 1.13.0 and 1.14.0 (July 8th, 2020)
100
+
101
+ ### URI.escape is No Longer Used
102
+
103
+ Deprecated `URI.escape` has been replaced with `Addressable::URI.escape_component`.
104
+ This introduces `addressable` as a new dependency.
105
+
106
+ ### Dependency Bump
107
+
108
+ Note: Faraday will now raise a `Faraday::ResourceNotFound` instead of `Faraday::Error::ResourceNotFound`.
109
+
110
+ GitHub issue: [#45](https://github.com/ruby-amqp/rabbitmq_http_api_client/pull/45)
111
+
112
+ Contributed by Niels Jansen.
113
+
114
+ ## Changes Between 1.12.0 and 1.13.0 (March 5th, 2020)
115
+
116
+ ### Pagination Support
117
+
118
+ GitHub issue: [#43](https://github.com/ruby-amqp/rabbitmq_http_api_client/pull/43)
119
+
120
+ Contributed by Rustam Sharshenov.
121
+
122
+ ### Dependency Updates
123
+
124
+ GitHub issue: [#42](https://github.com/ruby-amqp/rabbitmq_http_api_client/pull/42)
125
+
126
+ Contributed by @hatch-carl.
4
127
 
5
128
 
6
129
  ## Changes Between 1.11.0 and 1.12.0 (March 12th, 2019)
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2017 Michael Klishin
1
+ Copyright (c) 2012-2020 Michael Klishin
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -18,12 +18,12 @@ and will support more HTTP API features in the future
18
18
 
19
19
  ## Supported Ruby Versions
20
20
 
21
- * CRuby 2.0 through 2.4.x
21
+ * CRuby 2.5 through 3.x
22
22
  * JRuby 9K
23
-
23
+
24
24
  ## Supported RabbitMQ Versions
25
25
 
26
- * RabbitMQ 3.x
26
+ All [supported RabbitMQ release series](https://www.rabbitmq.com/versions.html).
27
27
 
28
28
  All versions require [RabbitMQ Management UI plugin](http://www.rabbitmq.com/management.html) to be installed and enabled.
29
29
 
@@ -32,7 +32,7 @@ All versions require [RabbitMQ Management UI plugin](http://www.rabbitmq.com/man
32
32
  Add this line to your application's Gemfile:
33
33
 
34
34
  ``` ruby
35
- gem 'rabbitmq_http_api_client', '>= 1.11.0'
35
+ gem 'rabbitmq_http_api_client', '>= 2.2.0'
36
36
  ```
37
37
 
38
38
  And then execute:
@@ -116,7 +116,6 @@ h = client.overview
116
116
  # List cluster nodes with detailed status info for each one of them
117
117
  nodes = client.list_nodes
118
118
  n = nodes.first
119
- puts n.sockets_used
120
119
  puts n.mem_used
121
120
  puts n.run_queue
122
121
 
@@ -127,7 +126,7 @@ puts n.proc_used
127
126
  puts n.fd_total
128
127
 
129
128
  # Get Management Plugin extension list
130
- xs = client.list_extensions
129
+ xs = client.list_extensions
131
130
 
132
131
  # List all the entities (vhosts, queues, exchanges, bindings, users, etc)
133
132
  defs = client.list_definitions
@@ -259,7 +258,7 @@ puts b.vhost
259
258
  # List all bindings in a vhost
260
259
  bs = client.list_bindings("/")
261
260
 
262
- # List all binsings between an exchange and a queue
261
+ # List all bindings between an exchange and a queue
263
262
  bs = client.list_bindings_between_queue_and_exchange("/", "collector1.megacorp.local", "log.events")
264
263
  ```
265
264
 
@@ -347,8 +346,21 @@ ps = client.clear_permissions_of("/", "guest")
347
346
 
348
347
  ## Running Tests
349
348
 
350
- bundle install
351
- bundle exec rspec -cfd spec
349
+ Before running the test suites, run a script that will set up the local node:
350
+
351
+ ``` shell
352
+ export RUBY_RABBITMQ_HTTP_API_CLIENT_RABBITMQCTL="rabbitmqctl"
353
+ export RUBY_RABBITMQ_HTTP_API_CLIENT_RABBITMQ_PLUGINS="rabbitmq-plugins"
354
+
355
+ ./bin/ci/before_build.sh
356
+ ```
357
+
358
+ To run all specs:
359
+
360
+ ``` shell
361
+ bundle install
362
+ bundle exec rspec -cfd spec
363
+ ```
352
364
 
353
365
  The test suite assumes that RabbitMQ is running locally with stock settings
354
366
  and rabbitmq-management plugin enabled.
@@ -371,5 +383,4 @@ and rabbitmq-management plugin enabled.
371
383
 
372
384
  Double-licensed under the MIT and Mozilla Public License (same as RabbitMQ).
373
385
 
374
- (c) Michael S. Klishin, 2012-2017.
375
-
386
+ (c) Michael S. Klishin, 2012-2020.
@@ -0,0 +1,70 @@
1
+ require "hashie"
2
+ require "faraday"
3
+ require "faraday/follow_redirects"
4
+ require "multi_json"
5
+ require "uri"
6
+
7
+ module RabbitMQ
8
+ module HTTP
9
+ class HealthChecks
10
+
11
+ def initialize(client)
12
+ @client = client
13
+ @request_helper = @client.request_helper
14
+ @response_helper = @client.response_helper
15
+ end
16
+
17
+ def check_alarms
18
+ health_check_for("health/checks/alarms")
19
+ end
20
+
21
+ def check_local_alarms
22
+ health_check_for("health/checks/local-alarms")
23
+ end
24
+
25
+ def check_virtual_hosts
26
+ health_check_for("health/checks/virtual-hosts")
27
+ end
28
+
29
+ def check_if_node_is_quorum_critical
30
+ health_check_for("health/checks/node-is-quorum-critical")
31
+ end
32
+
33
+ def check_if_node_is_mirror_sync_critical
34
+ health_check_for("health/checks/node-is-mirror-sync-critical")
35
+ end
36
+
37
+ def check_port_listener(port)
38
+ health_check_for("health/checks/port-listener/#{encode_uri_path_segment(port)}")
39
+ end
40
+
41
+ def check_protocol_listener(proto)
42
+ health_check_for("health/checks/protocol-listener/#{encode_uri_path_segment(proto)}")
43
+ end
44
+
45
+ TIME_UNITS = %w(days weeks months years)
46
+
47
+ def check_certificate_expiration(within, unit)
48
+ raise ArgumentError.new("supported time units are #{TIME_UNITS.join(', ')}, given: #{unit}") if !TIME_UNITS.include?(unit)
49
+ raise ArgumentError.new("the number of time units must be a positive integer") if within <= 0
50
+
51
+ health_check_for("health/checks/certificate-expiration/#{@request_helper.encode_uri_path_segment(within)}/#{@request_helper.encode_uri_path_segment(unit)}")
52
+ end
53
+
54
+
55
+ def health_check_for(path)
56
+ begin
57
+ _ = @response_helper.decode_resource(@client.connection.get(path))
58
+ [true, nil]
59
+ rescue Faraday::ServerError => se
60
+ # health check endpoints respond with a 503 if the server fails
61
+ if se.response_status == 503
62
+ [false, @response_helper.decode_response_body(se.response[:body])]
63
+ else
64
+ raise se
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,19 @@
1
+ require "hashie"
2
+ require "faraday"
3
+ require "faraday/follow_redirects"
4
+ require "multi_json"
5
+ require "uri"
6
+
7
+ module RabbitMQ
8
+ module HTTP
9
+ class RequestHelper
10
+ def encode_uri_path_segment(segment)
11
+ # Correctly escapes spaces, see ruby-amqp/rabbitmq_http_api_client#28.
12
+ #
13
+ # Note that slashes also must be escaped since this is a single URI path segment,
14
+ # not an entire path.
15
+ Addressable::URI.encode_component(segment, Addressable::URI::CharacterClasses::UNRESERVED)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ require "hashie"
2
+ require "faraday"
3
+ require "faraday/follow_redirects"
4
+ require "multi_json"
5
+ require "uri"
6
+
7
+ module RabbitMQ
8
+ module HTTP
9
+ class ResponseHelper
10
+
11
+ def initialize(client)
12
+ @client = client
13
+ end
14
+
15
+ def decode_resource(response)
16
+ if response.nil? || response.body.nil? || response.body.empty?
17
+ Hashie::Mash.new
18
+ else
19
+ decode_response_body(response.body)
20
+ end
21
+ end
22
+
23
+ def decode_response_body(body)
24
+ if body.empty?
25
+ Hashie::Mash.new
26
+ else
27
+ Hashie::Mash.new(body)
28
+ end
29
+ end
30
+
31
+ def decode_resource_collection(response)
32
+ collection = response.body.is_a?(Array) ? response.body : response.body.fetch('items')
33
+
34
+ collection.map do |i|
35
+ if i == []
36
+ Hashie::Mash.new()
37
+ else
38
+ Hashie::Mash.new(i)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,7 +1,7 @@
1
1
  module RabbitMQ
2
2
  module HTTP
3
3
  class Client
4
- VERSION = "1.12.0"
4
+ VERSION = "3.0.0"
5
5
  end
6
6
  end
7
7
  end
@@ -1,9 +1,14 @@
1
+ require "addressable/uri"
1
2
  require "hashie"
2
3
  require "faraday"
3
- require "faraday_middleware"
4
+ require "faraday/follow_redirects"
4
5
  require "multi_json"
5
6
  require "uri"
6
7
 
8
+ require_relative "client/request_helper"
9
+ require_relative "client/response_helper"
10
+ require_relative "client/health_checks"
11
+
7
12
  module RabbitMQ
8
13
  module HTTP
9
14
  class Client
@@ -12,7 +17,8 @@ module RabbitMQ
12
17
  # API
13
18
  #
14
19
 
15
- attr_reader :endpoint
20
+ attr_reader :endpoint, :health
21
+ attr_reader :connection, :request_helper, :response_helper
16
22
 
17
23
  def self.connect(endpoint, options = {})
18
24
  new(endpoint, options)
@@ -22,6 +28,10 @@ module RabbitMQ
22
28
  @endpoint = endpoint
23
29
  @options = options
24
30
 
31
+ @request_helper = RequestHelper.new()
32
+ @response_helper = ResponseHelper.new(self)
33
+ @health = HealthChecks.new(self)
34
+
25
35
  initialize_connection(endpoint, options)
26
36
  end
27
37
 
@@ -57,16 +67,16 @@ module RabbitMQ
57
67
  reduce(Hash.new) { |acc, lnr| acc[lnr.protocol] = lnr.port; acc }
58
68
  end
59
69
 
60
- def list_nodes
61
- decode_resource_collection(@connection.get("nodes"))
70
+ def list_nodes(query = {})
71
+ decode_resource_collection(@connection.get("nodes", query))
62
72
  end
63
73
 
64
74
  def node_info(name)
65
- decode_resource(@connection.get("nodes/#{uri_encode(name)}"))
75
+ decode_resource(@connection.get("nodes/#{encode_uri_path_segment(name)}"))
66
76
  end
67
77
 
68
- def list_extensions
69
- decode_resource_collection(@connection.get("extensions"))
78
+ def list_extensions(query = {})
79
+ decode_resource_collection(@connection.get("extensions", query))
70
80
  end
71
81
 
72
82
  def list_definitions
@@ -81,45 +91,45 @@ module RabbitMQ
81
91
  response.success?
82
92
  end
83
93
 
84
- def list_connections
85
- decode_resource_collection(@connection.get("connections"))
94
+ def list_connections(query = {})
95
+ decode_resource_collection(@connection.get("connections", query))
86
96
  end
87
97
 
88
98
  def connection_info(name)
89
- decode_resource(@connection.get("connections/#{uri_encode(name)}"))
99
+ decode_resource(@connection.get("connections/#{encode_uri_path_segment(name)}"))
90
100
  end
91
101
 
92
102
  def close_connection(name)
93
- decode_resource(@connection.delete("connections/#{uri_encode(name)}"))
103
+ decode_resource(@connection.delete("connections/#{encode_uri_path_segment(name)}"))
94
104
  end
95
105
 
96
- def list_channels
97
- decode_resource_collection(@connection.get("channels"))
106
+ def list_channels(query = {})
107
+ decode_resource_collection(@connection.get("channels", query))
98
108
  end
99
109
 
100
110
  def channel_info(name)
101
- decode_resource(@connection.get("channels/#{uri_encode(name)}"))
111
+ decode_resource(@connection.get("channels/#{encode_uri_path_segment(name)}"))
102
112
  end
103
113
 
104
- def list_exchanges(vhost = nil)
114
+ def list_exchanges(vhost = nil, query = {})
105
115
  path = if vhost.nil?
106
116
  "exchanges"
107
117
  else
108
- "exchanges/#{uri_encode(vhost)}"
118
+ "exchanges/#{encode_uri_path_segment(vhost)}"
109
119
  end
110
120
 
111
- decode_resource_collection(@connection.get(path))
121
+ decode_resource_collection(@connection.get(path, query))
112
122
  end
113
123
 
114
124
  def declare_exchange(vhost, name, attributes = {})
115
125
  opts = {
116
- :type => "direct",
117
- :auto_delete => false,
118
- :durable => true,
119
- :arguments => {}
126
+ type: "direct",
127
+ auto_delete: false,
128
+ durable: true,
129
+ arguments: {}
120
130
  }.merge(attributes)
121
131
 
122
- response = @connection.put("exchanges/#{uri_encode(vhost)}/#{uri_encode(name)}") do |req|
132
+ response = @connection.put("exchanges/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}") do |req|
123
133
  req.headers['Content-Type'] = 'application/json'
124
134
  req.body = MultiJson.dump(opts)
125
135
  end
@@ -127,87 +137,91 @@ module RabbitMQ
127
137
  end
128
138
 
129
139
  def delete_exchange(vhost, name, if_unused = false)
130
- response = @connection.delete("exchanges/#{uri_encode(vhost)}/#{uri_encode(name)}") do |req|
140
+ response = @connection.delete("exchanges/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}") do |req|
131
141
  req.params["if-unused"] = true if if_unused
132
142
  end
133
143
  decode_resource(response)
134
144
  end
135
145
 
136
146
  def exchange_info(vhost, name)
137
- decode_resource(@connection.get("exchanges/#{uri_encode(vhost)}/#{uri_encode(name)}"))
147
+ decode_resource(@connection.get("exchanges/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"))
138
148
  end
139
149
 
140
- def list_bindings_by_source(vhost, exchange)
141
- decode_resource_collection(@connection.get("exchanges/#{uri_encode(vhost)}/#{uri_encode(exchange)}/bindings/source"))
150
+ def list_bindings_by_source(vhost, exchange, query = {})
151
+ decode_resource_collection(@connection.get("exchanges/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(exchange)}/bindings/source", query))
142
152
  end
143
153
 
144
- def list_bindings_by_destination(vhost, exchange)
145
- decode_resource_collection(@connection.get("exchanges/#{uri_encode(vhost)}/#{uri_encode(exchange)}/bindings/destination"))
154
+ def list_bindings_by_destination(vhost, exchange, query = {})
155
+ decode_resource_collection(@connection.get("exchanges/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(exchange)}/bindings/destination", query))
146
156
  end
147
157
 
148
- def list_queues(vhost = nil)
158
+ def list_queues(vhost = nil, query = {})
149
159
  path = if vhost.nil?
150
160
  "queues"
151
161
  else
152
- "queues/#{uri_encode(vhost)}"
162
+ "queues/#{encode_uri_path_segment(vhost)}"
153
163
  end
154
164
 
155
- decode_resource_collection(@connection.get(path))
165
+ decode_resource_collection(@connection.get(path, query))
156
166
  end
157
167
 
158
168
  def queue_info(vhost, name)
159
- decode_resource(@connection.get("queues/#{uri_encode(vhost)}/#{uri_encode(name)}"))
169
+ decode_resource(@connection.get("queues/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"))
160
170
  end
161
171
 
162
172
  def declare_queue(vhost, name, attributes)
163
- response = @connection.put("queues/#{uri_encode(vhost)}/#{uri_encode(name)}") do |req|
173
+ response = @connection.put("queues/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}") do |req|
164
174
  req.headers['Content-Type'] = "application/json"
165
175
  req.body = MultiJson.dump(attributes)
166
176
  end
167
177
  decode_resource(response)
168
178
  end
169
179
 
170
- def delete_queue(vhost, name)
171
- decode_resource(@connection.delete("queues/#{uri_encode(vhost)}/#{uri_encode(name)}"))
180
+ def delete_queue(vhost, name, if_unused = false, if_empty = false)
181
+ response = @connection.delete("queues/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}") do |req|
182
+ req.params["if-unused"] = true if if_unused
183
+ req.params["if-empty"] = true if if_empty
184
+ end
185
+ decode_resource(response)
172
186
  end
173
187
 
174
- def list_queue_bindings(vhost, queue)
175
- decode_resource_collection(@connection.get("queues/#{uri_encode(vhost)}/#{uri_encode(queue)}/bindings"))
188
+ def list_queue_bindings(vhost, queue, query = {})
189
+ decode_resource_collection(@connection.get("queues/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(queue)}/bindings", query))
176
190
  end
177
191
 
178
192
  def purge_queue(vhost, name)
179
- @connection.delete("queues/#{uri_encode(vhost)}/#{uri_encode(name)}/contents")
193
+ @connection.delete("queues/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}/contents")
180
194
  Hashie::Mash.new
181
195
  end
182
196
 
183
197
  def get_messages(vhost, name, options)
184
- response = @connection.post("queues/#{uri_encode(vhost)}/#{uri_encode(name)}/get") do |req|
198
+ response = @connection.post("queues/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}/get") do |req|
185
199
  req.headers['Content-Type'] = "application/json"
186
200
  req.body = MultiJson.dump(options)
187
201
  end
188
202
  decode_resource_collection(response)
189
203
  end
190
204
 
191
- def list_bindings(vhost = nil)
205
+ def list_bindings(vhost = nil, query = {})
192
206
  path = if vhost.nil?
193
207
  "bindings"
194
208
  else
195
- "bindings/#{uri_encode(vhost)}"
209
+ "bindings/#{encode_uri_path_segment(vhost)}"
196
210
  end
197
211
 
198
- decode_resource_collection(@connection.get(path))
212
+ decode_resource_collection(@connection.get(path, query))
199
213
  end
200
214
 
201
- def list_bindings_between_queue_and_exchange(vhost, queue, exchange)
202
- decode_resource_collection(@connection.get("bindings/#{uri_encode(vhost)}/e/#{uri_encode(exchange)}/q/#{uri_encode(queue)}"))
215
+ def list_bindings_between_queue_and_exchange(vhost, queue, exchange, query = {})
216
+ decode_resource_collection(@connection.get("bindings/#{encode_uri_path_segment(vhost)}/e/#{encode_uri_path_segment(exchange)}/q/#{encode_uri_path_segment(queue)}", query))
203
217
  end
204
218
 
205
219
  def queue_binding_info(vhost, queue, exchange, properties_key)
206
- decode_resource(@connection.get("bindings/#{uri_encode(vhost)}/e/#{uri_encode(exchange)}/q/#{uri_encode(queue)}/#{uri_encode(properties_key)}"))
220
+ decode_resource(@connection.get("bindings/#{encode_uri_path_segment(vhost)}/e/#{encode_uri_path_segment(exchange)}/q/#{encode_uri_path_segment(queue)}/#{encode_uri_path_segment(properties_key)}"))
207
221
  end
208
222
 
209
223
  def bind_queue(vhost, queue, exchange, routing_key, arguments = [])
210
- resp = @connection.post("bindings/#{uri_encode(vhost)}/e/#{uri_encode(exchange)}/q/#{uri_encode(queue)}") do |req|
224
+ resp = @connection.post("bindings/#{encode_uri_path_segment(vhost)}/e/#{encode_uri_path_segment(exchange)}/q/#{encode_uri_path_segment(queue)}") do |req|
211
225
  req.headers['Content-Type'] = 'application/json'
212
226
  req.body = MultiJson.dump({:routing_key => routing_key, :arguments => arguments})
213
227
  end
@@ -215,21 +229,21 @@ module RabbitMQ
215
229
  end
216
230
 
217
231
  def delete_queue_binding(vhost, queue, exchange, properties_key)
218
- resp = @connection.delete("bindings/#{uri_encode(vhost)}/e/#{uri_encode(exchange)}/q/#{uri_encode(queue)}/#{uri_encode(properties_key)}")
232
+ resp = @connection.delete("bindings/#{encode_uri_path_segment(vhost)}/e/#{encode_uri_path_segment(exchange)}/q/#{encode_uri_path_segment(queue)}/#{encode_uri_path_segment(properties_key)}")
219
233
  resp.success?
220
234
  end
221
235
 
222
- def list_bindings_between_exchanges(vhost, destination_exchange, source_exchange)
223
- decode_resource_collection(@connection.get("bindings/#{uri_encode(vhost)}/e/#{uri_encode(source_exchange)}/e/#{uri_encode(destination_exchange)}"))
236
+ def list_bindings_between_exchanges(vhost, destination_exchange, source_exchange, query = {})
237
+ decode_resource_collection(@connection.get("bindings/#{encode_uri_path_segment(vhost)}/e/#{encode_uri_path_segment(source_exchange)}/e/#{encode_uri_path_segment(destination_exchange)}", query))
224
238
  end
225
239
 
226
240
  def exchange_binding_info(vhost, destination_exchange, source_exchange, properties_key)
227
- decode_resource(@connection.get("bindings/#{uri_encode(vhost)}/e/#{uri_encode(source_exchange)}/e/#{uri_encode(destination_exchange)}/#{uri_encode(properties_key)}"))
241
+ decode_resource(@connection.get("bindings/#{encode_uri_path_segment(vhost)}/e/#{encode_uri_path_segment(source_exchange)}/e/#{encode_uri_path_segment(destination_exchange)}/#{encode_uri_path_segment(properties_key)}"))
228
242
  end
229
243
 
230
244
 
231
245
  def bind_exchange(vhost, destination_exchange, source_exchange, routing_key, arguments = [])
232
- resp = @connection.post("bindings/#{uri_encode(vhost)}/e/#{uri_encode(source_exchange)}/e/#{uri_encode(destination_exchange)}") do |req|
246
+ resp = @connection.post("bindings/#{encode_uri_path_segment(vhost)}/e/#{encode_uri_path_segment(source_exchange)}/e/#{encode_uri_path_segment(destination_exchange)}") do |req|
233
247
  req.headers['Content-Type'] = 'application/json'
234
248
  req.body = MultiJson.dump({:routing_key => routing_key, :arguments => arguments})
235
249
  end
@@ -237,48 +251,48 @@ module RabbitMQ
237
251
  end
238
252
 
239
253
  def delete_exchange_binding(vhost, destination_exchange, source_exchange, properties_key)
240
- resp = @connection.delete("bindings/#{uri_encode(vhost)}/e/#{uri_encode(source_exchange)}/e/#{uri_encode(destination_exchange)}/#{uri_encode(properties_key)}")
254
+ resp = @connection.delete("bindings/#{encode_uri_path_segment(vhost)}/e/#{encode_uri_path_segment(source_exchange)}/e/#{encode_uri_path_segment(destination_exchange)}/#{encode_uri_path_segment(properties_key)}")
241
255
  resp.success?
242
256
  end
243
257
 
244
258
 
245
- def list_vhosts
246
- decode_resource_collection(@connection.get("vhosts"))
259
+ def list_vhosts(query = {})
260
+ decode_resource_collection(@connection.get("vhosts", query))
247
261
  end
248
262
 
249
263
  def vhost_info(name)
250
- decode_resource(@connection.get("vhosts/#{uri_encode(name)}"))
264
+ decode_resource(@connection.get("vhosts/#{encode_uri_path_segment(name)}"))
251
265
  end
252
266
 
253
267
  def create_vhost(name)
254
- response = @connection.put("vhosts/#{uri_encode(name)}") do |req|
268
+ response = @connection.put("vhosts/#{encode_uri_path_segment(name)}") do |req|
255
269
  req.headers['Content-Type'] = "application/json"
256
270
  end
257
271
  decode_resource(response)
258
272
  end
259
273
 
260
274
  def delete_vhost(name)
261
- decode_resource(@connection.delete("vhosts/#{uri_encode(name)}"))
275
+ decode_resource(@connection.delete("vhosts/#{encode_uri_path_segment(name)}"))
262
276
  end
263
277
 
264
278
 
265
279
 
266
- def list_permissions(vhost = nil)
280
+ def list_permissions(vhost = nil, query = {})
267
281
  path = if vhost
268
- "vhosts/#{uri_encode(vhost)}/permissions"
282
+ "vhosts/#{encode_uri_path_segment(vhost)}/permissions"
269
283
  else
270
284
  "permissions"
271
285
  end
272
286
 
273
- decode_resource_collection(@connection.get(path))
287
+ decode_resource_collection(@connection.get(path, query))
274
288
  end
275
289
 
276
290
  def list_permissions_of(vhost, user)
277
- decode_resource(@connection.get("permissions/#{uri_encode(vhost)}/#{uri_encode(user)}"))
291
+ decode_resource(@connection.get("permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"))
278
292
  end
279
293
 
280
294
  def update_permissions_of(vhost, user, attributes)
281
- response = @connection.put("permissions/#{uri_encode(vhost)}/#{uri_encode(user)}") do |req|
295
+ response = @connection.put("permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}") do |req|
282
296
  req.headers['Content-Type'] = "application/json"
283
297
  req.body = MultiJson.dump(attributes)
284
298
  end
@@ -286,23 +300,60 @@ module RabbitMQ
286
300
  end
287
301
 
288
302
  def clear_permissions_of(vhost, user)
289
- decode_resource(@connection.delete("permissions/#{uri_encode(vhost)}/#{uri_encode(user)}"))
303
+ decode_resource(@connection.delete("permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"))
304
+ end
305
+
306
+ def list_topic_permissions(vhost = nil, query = {})
307
+ path = if vhost
308
+ "vhosts/#{encode_uri_path_segment(vhost)}/topic-permissions"
309
+ else
310
+ "topic-permissions"
311
+ end
312
+
313
+ decode_resource_collection(@connection.get(path, query))
314
+ end
315
+
316
+ def list_topic_permissions_of(vhost, user)
317
+ path = "topic-permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"
318
+ decode_resource_collection(@connection.get(path))
290
319
  end
291
320
 
321
+ def update_topic_permissions_of(vhost, user, attributes)
322
+ response = @connection.put("topic-permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}") do |req|
323
+ req.headers['Content-Type'] = "application/json"
324
+ req.body = MultiJson.dump(attributes)
325
+ end
292
326
 
327
+ nil
328
+ end
293
329
 
294
- def list_users
295
- decode_resource_collection(@connection.get("users"))
330
+ def delete_topic_permissions_of(vhost, user)
331
+ decode_resource(@connection.delete("topic-permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"))
332
+ end
333
+
334
+ def list_users(query = {})
335
+ results = decode_resource_collection(@connection.get("users", query))
336
+
337
+ # HTTP API will return tags as an array starting with RabbitMQ 3.9
338
+ results.map do |u|
339
+ u.tags = u.tags.split(",") if u.tags.is_a?(String)
340
+ u
341
+ end
296
342
  end
297
343
 
298
344
  def user_info(name)
299
- decode_resource(@connection.get("users/#{uri_encode(name)}"))
345
+ result = decode_resource(@connection.get("users/#{encode_uri_path_segment(name)}"))
346
+
347
+ # HTTP API will return tags as an array starting with RabbitMQ 3.9
348
+ result.tags = result.tags.split(",") if result.tags.is_a?(String)
349
+
350
+ result
300
351
  end
301
352
 
302
353
  def update_user(name, attributes)
303
354
  attributes[:tags] ||= ""
304
355
 
305
- response = @connection.put("users/#{uri_encode(name)}") do |req|
356
+ response = @connection.put("users/#{encode_uri_path_segment(name)}") do |req|
306
357
  req.headers['Content-Type'] = "application/json"
307
358
  req.body = MultiJson.dump(attributes)
308
359
  end
@@ -311,11 +362,11 @@ module RabbitMQ
311
362
  alias create_user update_user
312
363
 
313
364
  def delete_user(name)
314
- decode_resource(@connection.delete("users/#{uri_encode(name)}"))
365
+ decode_resource(@connection.delete("users/#{encode_uri_path_segment(name)}"))
315
366
  end
316
367
 
317
- def user_permissions(name)
318
- decode_resource_collection(@connection.get("users/#{uri_encode(name)}/permissions"))
368
+ def user_permissions(name, query = {})
369
+ decode_resource_collection(@connection.get("users/#{encode_uri_path_segment(name)}/permissions", query))
319
370
  end
320
371
 
321
372
  def whoami
@@ -324,27 +375,27 @@ module RabbitMQ
324
375
 
325
376
 
326
377
 
327
- def list_policies(vhost = nil)
378
+ def list_policies(vhost = nil, query = {})
328
379
  path = if vhost
329
- "policies/#{uri_encode(vhost)}"
380
+ "policies/#{encode_uri_path_segment(vhost)}"
330
381
  else
331
382
  "policies"
332
383
  end
333
384
 
334
- decode_resource_collection(@connection.get(path))
385
+ decode_resource_collection(@connection.get(path, query))
335
386
  end
336
387
 
337
- def list_policies_of(vhost, name = nil)
388
+ def list_policies_of(vhost, name = nil, query = {})
338
389
  path = if name
339
- "policies/#{uri_encode(vhost)}/#{uri_encode(name)}"
390
+ "policies/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"
340
391
  else
341
- "policies/#{uri_encode(vhost)}"
392
+ "policies/#{encode_uri_path_segment(vhost)}"
342
393
  end
343
- decode_resource_collection(@connection.get(path))
394
+ decode_resource_collection(@connection.get(path, query))
344
395
  end
345
396
 
346
397
  def update_policies_of(vhost, name, attributes)
347
- response = @connection.put("policies/#{uri_encode(vhost)}/#{uri_encode(name)}") do |req|
398
+ response = @connection.put("policies/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}") do |req|
348
399
  req.headers['Content-Type'] = "application/json"
349
400
  req.body = MultiJson.dump(attributes)
350
401
  end
@@ -352,32 +403,32 @@ module RabbitMQ
352
403
  end
353
404
 
354
405
  def clear_policies_of(vhost, name)
355
- decode_resource(@connection.delete("policies/#{uri_encode(vhost)}/#{uri_encode(name)}"))
406
+ decode_resource(@connection.delete("policies/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"))
356
407
  end
357
408
 
358
409
 
359
410
 
360
411
 
361
- def list_parameters(component = nil)
412
+ def list_parameters(component = nil, query = {})
362
413
  path = if component
363
- "parameters/#{uri_encode(component)}"
414
+ "parameters/#{encode_uri_path_segment(component)}"
364
415
  else
365
416
  "parameters"
366
417
  end
367
- decode_resource_collection(@connection.get(path))
418
+ decode_resource_collection(@connection.get(path, query))
368
419
  end
369
420
 
370
- def list_parameters_of(component, vhost, name = nil)
421
+ def list_parameters_of(component, vhost, name = nil, query = {})
371
422
  path = if name
372
- "parameters/#{uri_encode(component)}/#{uri_encode(vhost)}/#{uri_encode(name)}"
423
+ "parameters/#{encode_uri_path_segment(component)}/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"
373
424
  else
374
- "parameters/#{uri_encode(component)}/#{uri_encode(vhost)}"
425
+ "parameters/#{encode_uri_path_segment(component)}/#{encode_uri_path_segment(vhost)}"
375
426
  end
376
- decode_resource_collection(@connection.get(path))
427
+ decode_resource_collection(@connection.get(path, query))
377
428
  end
378
429
 
379
430
  def update_parameters_of(component, vhost, name, attributes)
380
- response = @connection.put("parameters/#{uri_encode(component)}/#{uri_encode(vhost)}/#{uri_encode(name)}") do |req|
431
+ response = @connection.put("parameters/#{encode_uri_path_segment(component)}/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}") do |req|
381
432
  req.headers['Content-Type'] = "application/json"
382
433
  req.body = MultiJson.dump(attributes)
383
434
  end
@@ -385,17 +436,9 @@ module RabbitMQ
385
436
  end
386
437
 
387
438
  def clear_parameters_of(component, vhost, name)
388
- decode_resource(@connection.delete("parameters/#{uri_encode(component)}/#{uri_encode(vhost)}/#{uri_encode(name)}"))
439
+ decode_resource(@connection.delete("parameters/#{encode_uri_path_segment(component)}/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"))
389
440
  end
390
441
 
391
-
392
-
393
- def aliveness_test(vhost)
394
- r = @connection.get("aliveness-test/#{uri_encode(vhost)}")
395
- r.body["status"] == "ok"
396
- end
397
-
398
-
399
442
  protected
400
443
 
401
444
  def initialize_connection(endpoint, options = {})
@@ -404,11 +447,12 @@ module RabbitMQ
404
447
  user = uri.user || options.delete(:username) || "guest"
405
448
  password = uri.password || options.delete(:password) || "guest"
406
449
  options = options.merge(:url => uri.to_s)
407
- adapter = options.delete(:adapter) || Faraday.default_adapter
450
+ adapter = options.delete(:adapter) || Faraday.default_adapter || :httpclient
408
451
 
409
452
  @connection = Faraday.new(options) do |conn|
410
- conn.basic_auth user, password
411
- conn.use FaradayMiddleware::FollowRedirects, :limit => 3
453
+ conn.request :authorization, :basic, user, password
454
+
455
+ conn.use Faraday::FollowRedirects::Middleware, :limit => 3
412
456
  conn.use Faraday::Response::RaiseError
413
457
  conn.response :json, :content_type => /\bjson$/
414
458
 
@@ -416,27 +460,20 @@ module RabbitMQ
416
460
  end
417
461
  end
418
462
 
419
- def uri_encode(s)
420
- # correctly escapes spaces, unlike CGI.escape, see ruby-amqp/rabbitmq_http_api_client#28
421
- URI.escape(s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
463
+ def encode_uri_path_segment(segment)
464
+ @request_helper.encode_uri_path_segment(segment)
422
465
  end
423
466
 
424
467
  def decode_resource(response)
425
- case response.headers["content-length"]
426
- when nil then Hashie::Mash.new
427
- when 0 then Hashie::Mash.new
428
- when "0" then Hashie::Mash.new
429
- else
430
- if response.body.empty?
431
- Hashie::Mash.new
432
- else
433
- Hashie::Mash.new(response.body)
434
- end
435
- end
468
+ @response_helper.decode_resource(response)
469
+ end
470
+
471
+ def decode_response_body(body)
472
+ @response_helper.decode_response_body(body)
436
473
  end
437
474
 
438
475
  def decode_resource_collection(response)
439
- response.body.map { |i| Hashie::Mash.new(i) }
476
+ @response_helper.decode_resource_collection(response)
440
477
  end
441
478
  end # Client
442
479
  end # HTTP
metadata CHANGED
@@ -1,71 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabbitmq_http_api_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.12.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Klishin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-12 00:00:00.000000000 Z
11
+ date: 2024-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: addressable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.7'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: hashie
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - "~>"
18
32
  - !ruby/object:Gem::Version
19
- version: '3.6'
33
+ version: '4.1'
20
34
  type: :runtime
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
38
  - - "~>"
25
39
  - !ruby/object:Gem::Version
26
- version: '3.6'
40
+ version: '4.1'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: multi_json
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: 1.13.1
47
+ version: '1.15'
34
48
  type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: 1.13.1
54
+ version: '1.15'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: faraday
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: 0.15.4
61
+ version: '2.9'
48
62
  type: :runtime
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: 0.15.4
68
+ version: '2.9'
55
69
  - !ruby/object:Gem::Dependency
56
- name: faraday_middleware
70
+ name: faraday-follow_redirects
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: 0.13.0
75
+ version: '0.3'
62
76
  type: :runtime
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: 0.13.0
82
+ version: '0.3'
69
83
  description: RabbitMQ HTTP API client for Ruby
70
84
  email:
71
85
  - michael@clojurewerkz.org
@@ -77,13 +91,16 @@ files:
77
91
  - LICENSE.txt
78
92
  - README.md
79
93
  - lib/rabbitmq/http/client.rb
94
+ - lib/rabbitmq/http/client/health_checks.rb
95
+ - lib/rabbitmq/http/client/request_helper.rb
96
+ - lib/rabbitmq/http/client/response_helper.rb
80
97
  - lib/rabbitmq/http/client/version.rb
81
98
  homepage: http://github.com/ruby-amqp/rabbitmq_http_api_client
82
99
  licenses:
83
100
  - MIT
84
- - Mozilla Public License
101
+ - MPL-2.0
85
102
  metadata: {}
86
- post_install_message:
103
+ post_install_message:
87
104
  rdoc_options: []
88
105
  require_paths:
89
106
  - lib
@@ -98,8 +115,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
115
  - !ruby/object:Gem::Version
99
116
  version: '0'
100
117
  requirements: []
101
- rubygems_version: 3.0.2
102
- signing_key:
118
+ rubygems_version: 3.5.9
119
+ signing_key:
103
120
  specification_version: 4
104
121
  summary: RabbitMQ HTTP API client for Ruby
105
122
  test_files: []