rabbitmq_http_api_client 1.13.0 → 2.1.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: d0b9cc95320a9b5267b3ca4e0c0afc635bc07d4b1a06d4a684568dc887f8538e
4
- data.tar.gz: 6a99738452b35246c258b11e76b92b9d58be9ea184611600d677681677becc73
3
+ metadata.gz: b27e07a1d996952430cd53fa4c8eb1fc942a0c9126274bbd4436db5274a69764
4
+ data.tar.gz: a4d4b7429098509a8d971c8ed994555d24e99eb827e87179113cb50bf009a4bf
5
5
  SHA512:
6
- metadata.gz: 288d82241e7bcbf7ba6ec4fff269b0ad2f9bbdb4c6c51317675a3a29504926d793e8211489ab521f79237977770c96a49b1e1061f38c9af42b039c7185249edb
7
- data.tar.gz: 2b2ecfc8fb8fe35522571bc836d77324ba20991afaacc4f151cece7efb856d537e0a7c3d0474a3b79fe695760e44073e4692ef0a9d3a73eb54f63ecf028869bd
6
+ metadata.gz: 85efb6fca0ae57d98876a8db4124852f1c4c7911f428c92aac4d5607c3c93e5466dd04d81f2df27d77a59929581d477469c5605e15e287e8cd73f51ae78a5fb0
7
+ data.tar.gz: a185c9007cc1f45e1f0d0f9d25d3ad4adf91f1ebfb72469a1eeec70448ef25a5502c383e319ccf218a72b005738782f1bfdc909ca6bc4ecb3ecc90c0a51ac143
data/ChangeLog.md CHANGED
@@ -1,7 +1,91 @@
1
- ## Changes Between 1.12.0 and 1.13.0 (March 5th, 2020)
1
+ ## Changes Between 2.1.0 and 2.2.0 (in development)
2
2
 
3
3
  No changes yet.
4
4
 
5
+
6
+ ## Changes Between 2.0.0 and 2.1.0 (February 12, 2022)
7
+
8
+ ### Handle Responses that Do Not Contain a Body
9
+
10
+ GitHub issue: [#52](https://github.com/ruby-amqp/rabbitmq_http_api_client/issues/52)
11
+
12
+ ### Support for Management of Topic Permissions
13
+
14
+ Contributed by @bagedevimo.
15
+
16
+ GitHub issue: [#57](https://github.com/ruby-amqp/rabbitmq_http_api_client/issues/57)
17
+
18
+ ### Upgraded Faraday Middleware
19
+
20
+ Faraday (a dependency) has been upgraded to `1.2.x` to eliminate some deprecation warnings.
21
+
22
+
23
+ ## Changes Between 1.15.0 and 2.0.0 (May 21, 2021)
24
+
25
+ ### Health Check Endpoint Changes
26
+
27
+ `RabbitMQ::HTTP::Client#aliveness_test` has been removed. The endpoint has been deprecated
28
+ in favor of [more focussed health check endpoints](https://www.rabbitmq.com/monitoring.html#health-checks):
29
+
30
+ ``` ruby
31
+ c = RabbitMQ::HTTP::Client.new("http://username:s3kRe7@localhost:15672")
32
+
33
+ # Returns a pair of [success, details]. Details will be nil
34
+ # if the check succeeds.
35
+ #
36
+ # Checks for any alarms across the cluster
37
+ passed, details = c.health.check_alarms
38
+
39
+ # alarms on the given node
40
+ passed, details = c.health.check_local_alarms
41
+
42
+ # is this node essential for an online quorum of any quorum queues?
43
+ passed, details = c.health.check_if_node_is_quorum_critical
44
+
45
+ # do any certificates used by this node's TLS listeners expire within
46
+ # three months?
47
+ passed, details = c.health.check_certificate_expiration(3, "months")
48
+ ```
49
+
50
+ See the list of methods in `RabbitMQ::HTTP::HealthChecks` to find out what other
51
+ health checks are available.
52
+
53
+ ### User Tags Type Change
54
+
55
+ User tags returned by the `RabbitMQ::HTTP::Client#list_users` and `RabbitMQ::HTTP::Client#user_info`
56
+ methods are now arrays of strings instead of comma-separated strings.
57
+
58
+ Internally the method encodes both command-separated strings and JSON arrays in API responses
59
+ to support response types from RabbitMQ 3.9 and earlier versions.
60
+
61
+ See [rabbitmq/rabbitmq-server#2676](https://github.com/rabbitmq/rabbitmq-server/pull/2676) for details.
62
+
63
+ ## Changes Between 1.14.0 and 1.15.0 (February 16th, 2021)
64
+ ### Content Length Detection Changes
65
+
66
+ When deserialising response bodies, the client now uses actual body length instead of
67
+ the value of the `content-length` header.
68
+
69
+ Contributed by Ryan @rquant Quant.
70
+
71
+ GitHub issue: [#49](https://github.com/ruby-amqp/rabbitmq_http_api_client/pull/49)
72
+
73
+
74
+ ## Changes Between 1.13.0 and 1.14.0 (July 8th, 2020)
75
+
76
+ ### URI.escape is No Longer Used
77
+
78
+ Deprecated `URI.escape` has been replaced with `Addressable::URI.escape_component`.
79
+ This introduces `addressable` as a new dependency.
80
+
81
+ ### Dependency Bump
82
+
83
+ Note: Faraday will now raise a `Faraday::ResourceNotFound` instead of `Faraday::Error::ResourceNotFound`.
84
+
85
+ GitHub issue: [#45](https://github.com/ruby-amqp/rabbitmq_http_api_client/pull/45)
86
+
87
+ Contributed by Niels Jansen.
88
+
5
89
  ## Changes Between 1.12.0 and 1.13.0 (March 5th, 2020)
6
90
 
7
91
  ### Pagination Support
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2019 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.2 through 2.7.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.12.0'
35
+ gem 'rabbitmq_http_api_client', '>= 2.0.0'
36
36
  ```
37
37
 
38
38
  And then execute:
@@ -371,4 +371,4 @@ and rabbitmq-management plugin enabled.
371
371
 
372
372
  Double-licensed under the MIT and Mozilla Public License (same as RabbitMQ).
373
373
 
374
- (c) Michael S. Klishin, 2012-2019.
374
+ (c) Michael S. Klishin, 2012-2020.
@@ -0,0 +1,70 @@
1
+ require "hashie"
2
+ require "faraday"
3
+ require "faraday_middleware"
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_middleware"
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,38 @@
1
+ require "hashie"
2
+ require "faraday"
3
+ require "faraday_middleware"
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.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 { |i| Hashie::Mash.new(i) }
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,7 +1,7 @@
1
1
  module RabbitMQ
2
2
  module HTTP
3
3
  class Client
4
- VERSION = "1.13.0"
4
+ VERSION = "2.1.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
4
  require "faraday_middleware"
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
 
@@ -62,7 +72,7 @@ module RabbitMQ
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
78
  def list_extensions(query = {})
@@ -86,11 +96,11 @@ module RabbitMQ
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
106
  def list_channels(query = {})
@@ -98,14 +108,14 @@ module RabbitMQ
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
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
121
  decode_resource_collection(@connection.get(path, query))
@@ -113,13 +123,13 @@ module RabbitMQ
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,40 +137,40 @@ 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
150
  def list_bindings_by_source(vhost, exchange, query = {})
141
- decode_resource_collection(@connection.get("exchanges/#{uri_encode(vhost)}/#{uri_encode(exchange)}/bindings/source", 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
154
  def list_bindings_by_destination(vhost, exchange, query = {})
145
- decode_resource_collection(@connection.get("exchanges/#{uri_encode(vhost)}/#{uri_encode(exchange)}/bindings/destination", 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
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
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
@@ -168,20 +178,20 @@ module RabbitMQ
168
178
  end
169
179
 
170
180
  def delete_queue(vhost, name)
171
- decode_resource(@connection.delete("queues/#{uri_encode(vhost)}/#{uri_encode(name)}"))
181
+ decode_resource(@connection.delete("queues/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"))
172
182
  end
173
183
 
174
184
  def list_queue_bindings(vhost, queue, query = {})
175
- decode_resource_collection(@connection.get("queues/#{uri_encode(vhost)}/#{uri_encode(queue)}/bindings", query))
185
+ decode_resource_collection(@connection.get("queues/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(queue)}/bindings", query))
176
186
  end
177
187
 
178
188
  def purge_queue(vhost, name)
179
- @connection.delete("queues/#{uri_encode(vhost)}/#{uri_encode(name)}/contents")
189
+ @connection.delete("queues/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}/contents")
180
190
  Hashie::Mash.new
181
191
  end
182
192
 
183
193
  def get_messages(vhost, name, options)
184
- response = @connection.post("queues/#{uri_encode(vhost)}/#{uri_encode(name)}/get") do |req|
194
+ response = @connection.post("queues/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}/get") do |req|
185
195
  req.headers['Content-Type'] = "application/json"
186
196
  req.body = MultiJson.dump(options)
187
197
  end
@@ -192,22 +202,22 @@ module RabbitMQ
192
202
  path = if vhost.nil?
193
203
  "bindings"
194
204
  else
195
- "bindings/#{uri_encode(vhost)}"
205
+ "bindings/#{encode_uri_path_segment(vhost)}"
196
206
  end
197
207
 
198
208
  decode_resource_collection(@connection.get(path, query))
199
209
  end
200
210
 
201
211
  def list_bindings_between_queue_and_exchange(vhost, queue, exchange, query = {})
202
- decode_resource_collection(@connection.get("bindings/#{uri_encode(vhost)}/e/#{uri_encode(exchange)}/q/#{uri_encode(queue)}", query))
212
+ 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
213
  end
204
214
 
205
215
  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)}"))
216
+ 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
217
  end
208
218
 
209
219
  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|
220
+ resp = @connection.post("bindings/#{encode_uri_path_segment(vhost)}/e/#{encode_uri_path_segment(exchange)}/q/#{encode_uri_path_segment(queue)}") do |req|
211
221
  req.headers['Content-Type'] = 'application/json'
212
222
  req.body = MultiJson.dump({:routing_key => routing_key, :arguments => arguments})
213
223
  end
@@ -215,21 +225,21 @@ module RabbitMQ
215
225
  end
216
226
 
217
227
  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)}")
228
+ 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
229
  resp.success?
220
230
  end
221
231
 
222
232
  def list_bindings_between_exchanges(vhost, destination_exchange, source_exchange, query = {})
223
- decode_resource_collection(@connection.get("bindings/#{uri_encode(vhost)}/e/#{uri_encode(source_exchange)}/e/#{uri_encode(destination_exchange)}", query))
233
+ 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
234
  end
225
235
 
226
236
  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)}"))
237
+ 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
238
  end
229
239
 
230
240
 
231
241
  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|
242
+ 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
243
  req.headers['Content-Type'] = 'application/json'
234
244
  req.body = MultiJson.dump({:routing_key => routing_key, :arguments => arguments})
235
245
  end
@@ -237,7 +247,7 @@ module RabbitMQ
237
247
  end
238
248
 
239
249
  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)}")
250
+ 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
251
  resp.success?
242
252
  end
243
253
 
@@ -247,25 +257,25 @@ module RabbitMQ
247
257
  end
248
258
 
249
259
  def vhost_info(name)
250
- decode_resource(@connection.get("vhosts/#{uri_encode(name)}"))
260
+ decode_resource(@connection.get("vhosts/#{encode_uri_path_segment(name)}"))
251
261
  end
252
262
 
253
263
  def create_vhost(name)
254
- response = @connection.put("vhosts/#{uri_encode(name)}") do |req|
264
+ response = @connection.put("vhosts/#{encode_uri_path_segment(name)}") do |req|
255
265
  req.headers['Content-Type'] = "application/json"
256
266
  end
257
267
  decode_resource(response)
258
268
  end
259
269
 
260
270
  def delete_vhost(name)
261
- decode_resource(@connection.delete("vhosts/#{uri_encode(name)}"))
271
+ decode_resource(@connection.delete("vhosts/#{encode_uri_path_segment(name)}"))
262
272
  end
263
273
 
264
274
 
265
275
 
266
276
  def list_permissions(vhost = nil, query = {})
267
277
  path = if vhost
268
- "vhosts/#{uri_encode(vhost)}/permissions"
278
+ "vhosts/#{encode_uri_path_segment(vhost)}/permissions"
269
279
  else
270
280
  "permissions"
271
281
  end
@@ -274,11 +284,11 @@ module RabbitMQ
274
284
  end
275
285
 
276
286
  def list_permissions_of(vhost, user)
277
- decode_resource(@connection.get("permissions/#{uri_encode(vhost)}/#{uri_encode(user)}"))
287
+ decode_resource(@connection.get("permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"))
278
288
  end
279
289
 
280
290
  def update_permissions_of(vhost, user, attributes)
281
- response = @connection.put("permissions/#{uri_encode(vhost)}/#{uri_encode(user)}") do |req|
291
+ response = @connection.put("permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}") do |req|
282
292
  req.headers['Content-Type'] = "application/json"
283
293
  req.body = MultiJson.dump(attributes)
284
294
  end
@@ -286,23 +296,56 @@ module RabbitMQ
286
296
  end
287
297
 
288
298
  def clear_permissions_of(vhost, user)
289
- decode_resource(@connection.delete("permissions/#{uri_encode(vhost)}/#{uri_encode(user)}"))
299
+ decode_resource(@connection.delete("permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"))
300
+ end
301
+
302
+ def list_topic_permissions(vhost = nil, query = {})
303
+ path = if vhost
304
+ "vhosts/#{encode_uri_path_segment(vhost)}/topic-permissions"
305
+ else
306
+ "topic-permissions"
307
+ end
308
+
309
+ decode_resource_collection(@connection.get(path, query))
290
310
  end
291
311
 
312
+ def list_topic_permissions_of(vhost, user)
313
+ path = "topic-permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}"
314
+ decode_resource_collection(@connection.get(path))
315
+ end
292
316
 
317
+ def update_topic_permissions_of(vhost, user, attributes)
318
+ response = @connection.put("topic-permissions/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(user)}") do |req|
319
+ req.headers['Content-Type'] = "application/json"
320
+ req.body = MultiJson.dump(attributes)
321
+ end
322
+
323
+ nil
324
+ end
293
325
 
294
326
  def list_users(query = {})
295
- decode_resource_collection(@connection.get("users", query))
327
+ results = decode_resource_collection(@connection.get("users", query))
328
+
329
+ # HTTP API will return tags as an array starting with RabbitMQ 3.9
330
+ results.map do |u|
331
+ u.tags = u.tags.split(",") if u.tags.is_a?(String)
332
+ u
333
+ end
296
334
  end
297
335
 
298
336
  def user_info(name)
299
- decode_resource(@connection.get("users/#{uri_encode(name)}"))
337
+ result = decode_resource(@connection.get("users/#{encode_uri_path_segment(name)}"))
338
+
339
+ # HTTP API will return tags as an array starting with RabbitMQ 3.9
340
+ result.tags = result.tags.split(",") if result.tags.is_a?(String)
341
+
342
+ result
300
343
  end
301
344
 
302
345
  def update_user(name, attributes)
303
346
  attributes[:tags] ||= ""
304
347
 
305
- response = @connection.put("users/#{uri_encode(name)}") do |req|
348
+ response = @connection.put("users/#{encode_uri_path_segment(name)}") do |req|
306
349
  req.headers['Content-Type'] = "application/json"
307
350
  req.body = MultiJson.dump(attributes)
308
351
  end
@@ -311,11 +354,11 @@ module RabbitMQ
311
354
  alias create_user update_user
312
355
 
313
356
  def delete_user(name)
314
- decode_resource(@connection.delete("users/#{uri_encode(name)}"))
357
+ decode_resource(@connection.delete("users/#{encode_uri_path_segment(name)}"))
315
358
  end
316
359
 
317
360
  def user_permissions(name, query = {})
318
- decode_resource_collection(@connection.get("users/#{uri_encode(name)}/permissions", query))
361
+ decode_resource_collection(@connection.get("users/#{encode_uri_path_segment(name)}/permissions", query))
319
362
  end
320
363
 
321
364
  def whoami
@@ -326,7 +369,7 @@ module RabbitMQ
326
369
 
327
370
  def list_policies(vhost = nil, query = {})
328
371
  path = if vhost
329
- "policies/#{uri_encode(vhost)}"
372
+ "policies/#{encode_uri_path_segment(vhost)}"
330
373
  else
331
374
  "policies"
332
375
  end
@@ -336,15 +379,15 @@ module RabbitMQ
336
379
 
337
380
  def list_policies_of(vhost, name = nil, query = {})
338
381
  path = if name
339
- "policies/#{uri_encode(vhost)}/#{uri_encode(name)}"
382
+ "policies/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"
340
383
  else
341
- "policies/#{uri_encode(vhost)}"
384
+ "policies/#{encode_uri_path_segment(vhost)}"
342
385
  end
343
386
  decode_resource_collection(@connection.get(path, query))
344
387
  end
345
388
 
346
389
  def update_policies_of(vhost, name, attributes)
347
- response = @connection.put("policies/#{uri_encode(vhost)}/#{uri_encode(name)}") do |req|
390
+ response = @connection.put("policies/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}") do |req|
348
391
  req.headers['Content-Type'] = "application/json"
349
392
  req.body = MultiJson.dump(attributes)
350
393
  end
@@ -352,7 +395,7 @@ module RabbitMQ
352
395
  end
353
396
 
354
397
  def clear_policies_of(vhost, name)
355
- decode_resource(@connection.delete("policies/#{uri_encode(vhost)}/#{uri_encode(name)}"))
398
+ decode_resource(@connection.delete("policies/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"))
356
399
  end
357
400
 
358
401
 
@@ -360,7 +403,7 @@ module RabbitMQ
360
403
 
361
404
  def list_parameters(component = nil, query = {})
362
405
  path = if component
363
- "parameters/#{uri_encode(component)}"
406
+ "parameters/#{encode_uri_path_segment(component)}"
364
407
  else
365
408
  "parameters"
366
409
  end
@@ -369,15 +412,15 @@ module RabbitMQ
369
412
 
370
413
  def list_parameters_of(component, vhost, name = nil, query = {})
371
414
  path = if name
372
- "parameters/#{uri_encode(component)}/#{uri_encode(vhost)}/#{uri_encode(name)}"
415
+ "parameters/#{encode_uri_path_segment(component)}/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"
373
416
  else
374
- "parameters/#{uri_encode(component)}/#{uri_encode(vhost)}"
417
+ "parameters/#{encode_uri_path_segment(component)}/#{encode_uri_path_segment(vhost)}"
375
418
  end
376
419
  decode_resource_collection(@connection.get(path, query))
377
420
  end
378
421
 
379
422
  def update_parameters_of(component, vhost, name, attributes)
380
- response = @connection.put("parameters/#{uri_encode(component)}/#{uri_encode(vhost)}/#{uri_encode(name)}") do |req|
423
+ response = @connection.put("parameters/#{encode_uri_path_segment(component)}/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}") do |req|
381
424
  req.headers['Content-Type'] = "application/json"
382
425
  req.body = MultiJson.dump(attributes)
383
426
  end
@@ -385,17 +428,9 @@ module RabbitMQ
385
428
  end
386
429
 
387
430
  def clear_parameters_of(component, vhost, name)
388
- decode_resource(@connection.delete("parameters/#{uri_encode(component)}/#{uri_encode(vhost)}/#{uri_encode(name)}"))
389
- end
390
-
391
-
392
-
393
- def aliveness_test(vhost)
394
- r = @connection.get("aliveness-test/#{uri_encode(vhost)}")
395
- r.body["status"] == "ok"
431
+ decode_resource(@connection.delete("parameters/#{encode_uri_path_segment(component)}/#{encode_uri_path_segment(vhost)}/#{encode_uri_path_segment(name)}"))
396
432
  end
397
433
 
398
-
399
434
  protected
400
435
 
401
436
  def initialize_connection(endpoint, options = {})
@@ -407,7 +442,8 @@ module RabbitMQ
407
442
  adapter = options.delete(:adapter) || Faraday.default_adapter
408
443
 
409
444
  @connection = Faraday.new(options) do |conn|
410
- conn.basic_auth user, password
445
+ conn.request :basic_auth, user, password
446
+
411
447
  conn.use FaradayMiddleware::FollowRedirects, :limit => 3
412
448
  conn.use Faraday::Response::RaiseError
413
449
  conn.response :json, :content_type => /\bjson$/
@@ -416,29 +452,20 @@ module RabbitMQ
416
452
  end
417
453
  end
418
454
 
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}]"))
455
+ def encode_uri_path_segment(segment)
456
+ @request_helper.encode_uri_path_segment(segment)
422
457
  end
423
458
 
424
459
  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
460
+ @response_helper.decode_resource(response)
436
461
  end
437
462
 
438
- def decode_resource_collection(response)
439
- collection = response.body.is_a?(Array) ? response.body : response.body.fetch('items')
463
+ def decode_response_body(body)
464
+ @response_helper.decode_response_body(body)
465
+ end
440
466
 
441
- collection.map { |i| Hashie::Mash.new(i) }
467
+ def decode_resource_collection(response)
468
+ @response_helper.decode_resource_collection(response)
442
469
  end
443
470
  end # Client
444
471
  end # HTTP
metadata CHANGED
@@ -1,83 +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.13.0
4
+ version: 2.1.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: 2020-03-05 00:00:00.000000000 Z
11
+ date: 2022-02-11 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
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0.15'
48
- - - "<"
59
+ - - "~>"
49
60
  - !ruby/object:Gem::Version
50
- version: '1'
61
+ version: '1.3'
51
62
  type: :runtime
52
63
  prerelease: false
53
64
  version_requirements: !ruby/object:Gem::Requirement
54
65
  requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- version: '0.15'
58
- - - "<"
66
+ - - "~>"
59
67
  - !ruby/object:Gem::Version
60
- version: '1'
68
+ version: '1.3'
61
69
  - !ruby/object:Gem::Dependency
62
70
  name: faraday_middleware
63
71
  requirement: !ruby/object:Gem::Requirement
64
72
  requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- version: 0.13.0
68
- - - "<"
73
+ - - "~>"
69
74
  - !ruby/object:Gem::Version
70
- version: '1'
75
+ version: '1.2'
71
76
  type: :runtime
72
77
  prerelease: false
73
78
  version_requirements: !ruby/object:Gem::Requirement
74
79
  requirements:
75
- - - ">="
76
- - !ruby/object:Gem::Version
77
- version: 0.13.0
78
- - - "<"
80
+ - - "~>"
79
81
  - !ruby/object:Gem::Version
80
- version: '1'
82
+ version: '1.2'
81
83
  description: RabbitMQ HTTP API client for Ruby
82
84
  email:
83
85
  - michael@clojurewerkz.org
@@ -89,13 +91,16 @@ files:
89
91
  - LICENSE.txt
90
92
  - README.md
91
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
92
97
  - lib/rabbitmq/http/client/version.rb
93
98
  homepage: http://github.com/ruby-amqp/rabbitmq_http_api_client
94
99
  licenses:
95
100
  - MIT
96
- - Mozilla Public License
101
+ - MPL-2.0
97
102
  metadata: {}
98
- post_install_message:
103
+ post_install_message:
99
104
  rdoc_options: []
100
105
  require_paths:
101
106
  - lib
@@ -110,8 +115,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
115
  - !ruby/object:Gem::Version
111
116
  version: '0'
112
117
  requirements: []
113
- rubygems_version: 3.0.3
114
- signing_key:
118
+ rubygems_version: 3.1.4
119
+ signing_key:
115
120
  specification_version: 4
116
121
  summary: RabbitMQ HTTP API client for Ruby
117
122
  test_files: []