3scale_client 2.9.0 → 2.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/3scale/client.rb +24 -9
- data/lib/3scale/client/http_client.rb +22 -10
- data/lib/3scale/client/version.rb +1 -1
- data/lib/3scale/rack_query.rb +37 -0
- data/test/client_test.rb +61 -2
- metadata +3 -3
- data/VERSION +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0c46a8b42107a91987d9861498f796287909fb5
|
4
|
+
data.tar.gz: 5d43b1ee44766fe2057fec8eea21f5a30a8ac83f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c3b09b26c8ec29367f68fc231b52c3d7af036d8360179b968d50d231a2a1332ba5b0c11139539e4af6a711cb2716fe47972eaa34e66fb4ba8addc29c876e33b
|
7
|
+
data.tar.gz: 3d3136b451d4694fc00291d013e07dd1fd562f4c605caf1bc32a7c4f1e5ca6c6bb9808eed46f54909d7e551fea5f7260363d6ef5c75aca9ef4f00b85f9d6c717
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
+
## [2.10.0] - 2016-11-25
|
5
|
+
### Added
|
6
|
+
- Added support for 3scale extensions (experimental or non-standard
|
7
|
+
features that are not part of the official API). You just need to
|
8
|
+
add the `:extensions` symbol and the value to the hash of options that
|
9
|
+
the client methods accept. The value is itself a hash containing the
|
10
|
+
parameter names as keys and the parameter values as values.
|
11
|
+
|
4
12
|
## [2.9.0] - 2016-10-21
|
5
13
|
This version drops support for Ruby versions < 2.1 and JRuby < 9.1.1.0.
|
6
14
|
|
data/lib/3scale/client.rb
CHANGED
@@ -7,6 +7,7 @@ require '3scale/client/version'
|
|
7
7
|
|
8
8
|
require '3scale/response'
|
9
9
|
require '3scale/authorize_response'
|
10
|
+
require '3scale/rack_query'
|
10
11
|
|
11
12
|
module ThreeScale
|
12
13
|
Error = Class.new(RuntimeError)
|
@@ -47,6 +48,9 @@ module ThreeScale
|
|
47
48
|
'def report(transactions: [], service_id: nil).'.freeze
|
48
49
|
private_constant :DEPRECATION_MSG_OLD_REPORT
|
49
50
|
|
51
|
+
EXTENSIONS_HEADER = '3scale-options'.freeze
|
52
|
+
private_constant :EXTENSIONS_HEADER
|
53
|
+
|
50
54
|
def initialize(options)
|
51
55
|
if options[:provider_key].nil? || options[:provider_key] =~ /^\s*$/
|
52
56
|
raise ArgumentError, 'missing :provider_key'
|
@@ -69,6 +73,7 @@ module ThreeScale
|
|
69
73
|
|
70
74
|
options_usage = options.delete :usage
|
71
75
|
options_log = options.delete :log
|
76
|
+
extensions = options.delete :extensions
|
72
77
|
|
73
78
|
options.each_pair do |param, value|
|
74
79
|
path += "&#{param}=#{CGI.escape(value.to_s)}"
|
@@ -86,7 +91,8 @@ module ThreeScale
|
|
86
91
|
path += "&#{log.join('&')}"
|
87
92
|
end
|
88
93
|
|
89
|
-
|
94
|
+
headers = extensions_to_header extensions if extensions
|
95
|
+
http_response = @http.get(path, headers: headers)
|
90
96
|
|
91
97
|
case http_response
|
92
98
|
when Net::HTTPSuccess,Net::HTTPConflict
|
@@ -148,7 +154,7 @@ module ThreeScale
|
|
148
154
|
# The signature of this method is a bit complicated because we decided to
|
149
155
|
# keep backwards compatibility with a previous version of the method:
|
150
156
|
# def report(*transactions)
|
151
|
-
def report(*reports, transactions: [], service_id: nil, **rest)
|
157
|
+
def report(*reports, transactions: [], service_id: nil, extensions: nil, **rest)
|
152
158
|
if (!transactions || transactions.empty?) && rest.empty?
|
153
159
|
raise ArgumentError, 'no transactions to report'
|
154
160
|
end
|
@@ -164,7 +170,8 @@ module ThreeScale
|
|
164
170
|
payload['provider_key'] = CGI.escape(provider_key)
|
165
171
|
payload['service_id'] = CGI.escape(service_id.to_s) if service_id
|
166
172
|
|
167
|
-
|
173
|
+
headers = extensions_to_header extensions if extensions
|
174
|
+
http_response = @http.post('/transactions.xml', payload, headers: headers)
|
168
175
|
|
169
176
|
case http_response
|
170
177
|
when Net::HTTPSuccess
|
@@ -189,6 +196,7 @@ module ThreeScale
|
|
189
196
|
# usage:: predicted usage. It is optional. It is a hash where the keys are metrics
|
190
197
|
# and the values their predicted usage.
|
191
198
|
# Example: {'hits' => 1, 'my_metric' => 100}
|
199
|
+
# extensions:: Optional. Hash of extension keys and values.
|
192
200
|
#
|
193
201
|
# == Return
|
194
202
|
#
|
@@ -210,9 +218,11 @@ module ThreeScale
|
|
210
218
|
# end
|
211
219
|
#
|
212
220
|
def authorize(options)
|
221
|
+
extensions = options.delete :extensions
|
213
222
|
path = "/transactions/authorize.xml" + options_to_params(options, ALL_PARAMS)
|
214
223
|
|
215
|
-
|
224
|
+
headers = extensions_to_header extensions if extensions
|
225
|
+
http_response = @http.get(path, headers: headers)
|
216
226
|
|
217
227
|
case http_response
|
218
228
|
when Net::HTTPSuccess,Net::HTTPConflict
|
@@ -259,9 +269,11 @@ module ThreeScale
|
|
259
269
|
# end
|
260
270
|
#
|
261
271
|
def oauth_authorize(options)
|
272
|
+
extensions = options.delete :extensions
|
262
273
|
path = "/transactions/oauth_authorize.xml" + options_to_params(options, OAUTH_PARAMS)
|
263
274
|
|
264
|
-
|
275
|
+
headers = extensions_to_header extensions if extensions
|
276
|
+
http_response = @http.get(path, headers: headers)
|
265
277
|
|
266
278
|
case http_response
|
267
279
|
when Net::HTTPSuccess,Net::HTTPConflict
|
@@ -275,10 +287,8 @@ module ThreeScale
|
|
275
287
|
|
276
288
|
private
|
277
289
|
|
278
|
-
|
279
|
-
|
280
|
-
OAUTH_PARAMS = [:app_id, :app_key, :service_id, :redirect_url, :usage, :hierarchy]
|
281
|
-
ALL_PARAMS = [:user_key, :app_id, :app_key, :service_id, :redirect_url, :usage, :hierarchy]
|
290
|
+
OAUTH_PARAMS = [:app_id, :app_key, :service_id, :redirect_url, :usage]
|
291
|
+
ALL_PARAMS = [:user_key, :app_id, :app_key, :service_id, :redirect_url, :usage]
|
282
292
|
REPORT_PARAMS = [:user_key, :app_id, :service_id, :timestamp]
|
283
293
|
|
284
294
|
def options_to_params(options, allowed_keys)
|
@@ -382,5 +392,10 @@ module ThreeScale
|
|
382
392
|
response.error!(node.content.to_s.strip, node['code'].to_s.strip)
|
383
393
|
response
|
384
394
|
end
|
395
|
+
|
396
|
+
# Encode extensions header
|
397
|
+
def extensions_to_header(extensions)
|
398
|
+
{ EXTENSIONS_HEADER => RackQuery.encode(extensions) }
|
399
|
+
end
|
385
400
|
end
|
386
401
|
end
|
@@ -39,20 +39,32 @@ module ThreeScale
|
|
39
39
|
@port = port
|
40
40
|
end
|
41
41
|
|
42
|
-
def get_request(path)
|
42
|
+
def get_request(path, headers: nil)
|
43
43
|
get = Net::HTTP::Get.new(path)
|
44
44
|
get.add_field(*USER_CLIENT_HEADER)
|
45
45
|
get.add_field('Host', @host)
|
46
|
+
add_request_headers(get, headers) if headers
|
46
47
|
get
|
47
48
|
end
|
48
49
|
|
49
|
-
def post_request(path, payload)
|
50
|
+
def post_request(path, payload, headers: nil)
|
50
51
|
post = Net::HTTP::Post.new(path)
|
51
52
|
post.add_field(*USER_CLIENT_HEADER)
|
52
53
|
post.add_field('Host', @host)
|
54
|
+
add_request_headers(post, headers) if headers
|
53
55
|
post.set_form_data(payload)
|
54
56
|
post
|
55
57
|
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def add_request_headers(req, headers)
|
62
|
+
if headers
|
63
|
+
headers.each do |hk, hv|
|
64
|
+
req.add_field(hk, hv)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
56
68
|
end
|
57
69
|
|
58
70
|
class NetHttpPersistent < BaseClient
|
@@ -77,15 +89,15 @@ module ThreeScale
|
|
77
89
|
@protocol = 'https'
|
78
90
|
end
|
79
91
|
|
80
|
-
def get(path)
|
92
|
+
def get(path, headers: nil)
|
81
93
|
uri = full_uri(path)
|
82
|
-
@http.request(uri, get_request(path))
|
94
|
+
@http.request(uri, get_request(path, headers: headers))
|
83
95
|
end
|
84
96
|
|
85
97
|
|
86
|
-
def post(path, payload)
|
98
|
+
def post(path, payload, headers: nil)
|
87
99
|
uri = full_uri(path)
|
88
|
-
@http.request(uri, post_request(path, payload))
|
100
|
+
@http.request(uri, post_request(path, payload, headers: headers))
|
89
101
|
end
|
90
102
|
|
91
103
|
def full_uri(path)
|
@@ -107,12 +119,12 @@ module ThreeScale
|
|
107
119
|
@http.use_ssl = true
|
108
120
|
end
|
109
121
|
|
110
|
-
def get(path)
|
111
|
-
@http.request get_request(path)
|
122
|
+
def get(path, headers: nil)
|
123
|
+
@http.request get_request(path, headers: headers)
|
112
124
|
end
|
113
125
|
|
114
|
-
def post(path, payload)
|
115
|
-
@http.request post_request(path, payload)
|
126
|
+
def post(path, payload, headers: nil)
|
127
|
+
@http.request post_request(path, payload, headers: headers)
|
116
128
|
end
|
117
129
|
end
|
118
130
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# A simple module to encode hashes of param keys and values as expected by
|
2
|
+
# Rack in its nested queries parsing.
|
3
|
+
#
|
4
|
+
module RackQuery
|
5
|
+
class << self
|
6
|
+
def encode(hash)
|
7
|
+
hash.flat_map do |hk, hv|
|
8
|
+
encode_value(CGI.escape(hk.to_s), hv)
|
9
|
+
end.join('&'.freeze)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def encode_value(rack_param, val)
|
15
|
+
if val.is_a? Array
|
16
|
+
encode_array(rack_param, val)
|
17
|
+
elsif val.is_a? Hash
|
18
|
+
encode_hash(rack_param, val)
|
19
|
+
else
|
20
|
+
"#{rack_param}=#{CGI.escape(val.to_s)}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def encode_array(rack_param, val)
|
25
|
+
rack_param = rack_param + '[]'
|
26
|
+
val.flat_map do |v|
|
27
|
+
encode_value(rack_param, v)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def encode_hash(rack_param, val)
|
32
|
+
val.flat_map do |k, v|
|
33
|
+
encode_value(rack_param + "[#{CGI.escape(k.to_s)}]", v)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/test/client_test.rb
CHANGED
@@ -267,7 +267,7 @@ class ThreeScale::ClientTest < MiniTest::Test
|
|
267
267
|
# calls.
|
268
268
|
urls = [:authorize, :authrep, :oauth_authorize].inject({}) do |acc, method|
|
269
269
|
acc[method] = "http://#{@host}/transactions/#{method}.xml?"\
|
270
|
-
"provider_key=1234abcd&app_id=foo
|
270
|
+
"provider_key=1234abcd&app_id=foo"
|
271
271
|
acc[method] << "&%5Busage%5D%5Bhits%5D=1" if method == :authrep
|
272
272
|
acc
|
273
273
|
end
|
@@ -317,7 +317,7 @@ class ThreeScale::ClientTest < MiniTest::Test
|
|
317
317
|
|
318
318
|
urls.each do |method, url|
|
319
319
|
FakeWeb.register_uri(:get, url, :status => ['200', 'OK'], :body => body)
|
320
|
-
response = @client.send(method, :app_id => 'foo', :hierarchy => 1)
|
320
|
+
response = @client.send(method, :app_id => 'foo', extensions: { :hierarchy => 1 })
|
321
321
|
assert_equal response.hierarchy, { 'parent1' => ['child1', 'child2'],
|
322
322
|
'parent2' => ['child3'] }
|
323
323
|
end
|
@@ -702,6 +702,65 @@ class ThreeScale::ClientTest < MiniTest::Test
|
|
702
702
|
assert_equal "su1.3scale.net", request["host"]
|
703
703
|
end
|
704
704
|
|
705
|
+
EXTENSIONS_HASH = {
|
706
|
+
'a special &=key' => 'a special =&value',
|
707
|
+
'ary' => [1,2],
|
708
|
+
'a hash' => { one: 'one', two: 'two' },
|
709
|
+
'combined' =>
|
710
|
+
{ v: 'v', nested: [1, { h: [ { hh: [ { hhh: :deep }, 'val' ] } ], h2: :h2 } ] }
|
711
|
+
}
|
712
|
+
private_constant :EXTENSIONS_HASH
|
713
|
+
EXTENSIONS_STR = "a+special+%26%3Dkey=a+special+%3D%26value&ary[]=1&ary[]=2&" \
|
714
|
+
"a+hash[one]=one&a+hash[two]=two&combined[v]=v&" \
|
715
|
+
"combined[nested][]=1&combined[nested][][h][][hh][][hhh]=deep&" \
|
716
|
+
"combined[nested][][h][][hh][]=val&combined[nested][][h2]=h2".freeze
|
717
|
+
private_constant :EXTENSIONS_STR
|
718
|
+
|
719
|
+
def test_authorize_with_extensions
|
720
|
+
body = '<status>
|
721
|
+
<authorized>true</authorized>
|
722
|
+
<plan>Ultimate</plan>
|
723
|
+
</status>'
|
724
|
+
FakeWeb.register_uri(:get,
|
725
|
+
"http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo",
|
726
|
+
:status => ['200', 'OK'], body: body)
|
727
|
+
|
728
|
+
@client.authorize(:app_id => 'foo', extensions: EXTENSIONS_HASH)
|
729
|
+
|
730
|
+
request = FakeWeb.last_request
|
731
|
+
assert_equal EXTENSIONS_STR, request[ThreeScale::Client.const_get('EXTENSIONS_HEADER')]
|
732
|
+
end
|
733
|
+
|
734
|
+
def test_authrep_with_extensions
|
735
|
+
body = '<status>
|
736
|
+
<authorized>true</authorized>
|
737
|
+
<plan>Ultimate</plan>
|
738
|
+
</status>'
|
739
|
+
FakeWeb.register_uri(:get,
|
740
|
+
"http://#{@host}/transactions/authrep.xml?provider_key=1234abcd&app_id=foo&%5Busage%5D%5Bhits%5D=1",
|
741
|
+
:status => ['200', 'OK'], body: body)
|
742
|
+
|
743
|
+
@client.authrep(:app_id => 'foo', extensions: EXTENSIONS_HASH)
|
744
|
+
|
745
|
+
request = FakeWeb.last_request
|
746
|
+
assert_equal EXTENSIONS_STR, request['3scale-options']
|
747
|
+
end
|
748
|
+
|
749
|
+
def test_report_with_extensions
|
750
|
+
FakeWeb.register_uri(:post, "http://#{@host}/transactions.xml",
|
751
|
+
:status => ['200', 'OK'])
|
752
|
+
|
753
|
+
transactions = [{ :app_id => 'app_id_1',
|
754
|
+
:usage => { 'hits' => 1 },
|
755
|
+
:timestamp => '2016-07-18 15:42:17 0200' }]
|
756
|
+
|
757
|
+
@client.report(transactions: transactions, service_id: 'a_service_id',
|
758
|
+
extensions: EXTENSIONS_HASH)
|
759
|
+
|
760
|
+
request = FakeWeb.last_request
|
761
|
+
assert_equal EXTENSIONS_STR, request['3scale-options']
|
762
|
+
end
|
763
|
+
|
705
764
|
private
|
706
765
|
|
707
766
|
#OPTIMIZE this tricky test helper relies on fakeweb catching the urls requested by the client
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: 3scale_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michal Cichra
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2016-
|
15
|
+
date: 2016-11-25 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: bundler
|
@@ -172,13 +172,13 @@ files:
|
|
172
172
|
- LICENCE
|
173
173
|
- README.md
|
174
174
|
- Rakefile
|
175
|
-
- VERSION
|
176
175
|
- gemfiles/rack_1.gemfile
|
177
176
|
- lib/3scale/authorize_response.rb
|
178
177
|
- lib/3scale/client.rb
|
179
178
|
- lib/3scale/client/http_client.rb
|
180
179
|
- lib/3scale/client/version.rb
|
181
180
|
- lib/3scale/middleware.rb
|
181
|
+
- lib/3scale/rack_query.rb
|
182
182
|
- lib/3scale/response.rb
|
183
183
|
- lib/3scale_client.rb
|
184
184
|
- test/benchmark.rb
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.8.2
|