3scale_client 2.0.1 → 2.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/3scale_client.gemspec +6 -6
- data/README.rdoc +37 -49
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/lib/{three_scale → 3scale}/authorize_response.rb +11 -7
- data/lib/{three_scale → 3scale}/client.rb +58 -50
- data/lib/3scale/response.rb +24 -0
- data/test/client_test.rb +102 -70
- data/test/remote_test.rb +34 -10
- metadata +7 -7
- data/lib/three_scale/response.rb +0 -21
data/3scale_client.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{3scale_client}
|
8
|
-
s.version = "2.
|
8
|
+
s.version = "2.2.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["Adam
|
12
|
-
s.date = %q{2010-
|
11
|
+
s.authors = ["Adam Cigánek"]
|
12
|
+
s.date = %q{2010-09-15}
|
13
13
|
s.description = %q{This gem allows to easily connect an application that provides a Web Service with the 3scale API Management System to authorize it's users and report the usage.
|
14
14
|
}
|
15
15
|
s.email = %q{adam@3scale.net}
|
@@ -23,9 +23,9 @@ Gem::Specification.new do |s|
|
|
23
23
|
"README.rdoc",
|
24
24
|
"Rakefile",
|
25
25
|
"VERSION",
|
26
|
-
"lib/
|
27
|
-
"lib/
|
28
|
-
"lib/
|
26
|
+
"lib/3scale/authorize_response.rb",
|
27
|
+
"lib/3scale/client.rb",
|
28
|
+
"lib/3scale/response.rb",
|
29
29
|
"test/client_test.rb",
|
30
30
|
"test/remote_test.rb"
|
31
31
|
]
|
data/README.rdoc
CHANGED
@@ -1,15 +1,10 @@
|
|
1
1
|
= Client for 3scale web service management system API
|
2
2
|
|
3
|
-
This
|
4
|
-
|
3
|
+
Please note: This version of the library targets the new API, which is currently in beta phase. Please contact 3scale support as support@3scale.net before you use it. You can also use older version (2.0.1) targeting the old API: http://github.com/3scale/3scale_ws_api_for_ruby/tree/v2.0.1.
|
4
|
+
|
5
5
|
== Installation
|
6
6
|
|
7
|
-
This library is distributed as a gem
|
8
|
-
unless it's already there:
|
9
|
-
|
10
|
-
gem source --add http://gemcutter.org
|
11
|
-
|
12
|
-
Then install the gem:
|
7
|
+
This library is distributed as a gem:
|
13
8
|
|
14
9
|
gem install 3scale_client
|
15
10
|
|
@@ -32,10 +27,10 @@ Because the object is stateless, you can create just one and store it globally.
|
|
32
27
|
|
33
28
|
=== Authorize
|
34
29
|
|
35
|
-
To authorize
|
36
|
-
|
30
|
+
To authorize an application, call the +authorize+ method passing it the application's id and
|
31
|
+
optionally a key:
|
37
32
|
|
38
|
-
response = client.authorize(:
|
33
|
+
response = client.authorize(:app_id => "the app id", :app_id => "the app key")
|
39
34
|
|
40
35
|
Then call the +success?+ method on the returned object to see if the authorization was
|
41
36
|
successful.
|
@@ -43,57 +38,55 @@ successful.
|
|
43
38
|
if response.success?
|
44
39
|
# All fine, proceeed.
|
45
40
|
else
|
46
|
-
# Something's wrong with this
|
41
|
+
# Something's wrong with this application.
|
47
42
|
end
|
48
43
|
|
49
|
-
If
|
50
|
-
the status of the
|
44
|
+
If both provider key and app id are valid, the response object contains additional
|
45
|
+
information about the status of the application:
|
51
46
|
|
52
|
-
# Returns the name of the plan the
|
47
|
+
# Returns the name of the plan the application is signed up to.
|
53
48
|
response.plan
|
54
49
|
|
55
|
-
If the plan has defined usage limits, the response contains details about
|
56
|
-
|
50
|
+
If the plan has defined usage limits, the response contains details about the usage broken
|
51
|
+
down by the metrics and usage limit periods.
|
57
52
|
|
58
|
-
# The
|
59
|
-
|
53
|
+
# The usage_reports array contains one element per each usage limit defined on the plan.
|
54
|
+
usage_report = response.usage_reports[0]
|
60
55
|
|
61
56
|
# The metric
|
62
|
-
|
57
|
+
usage_report.metric # "hits"
|
63
58
|
|
64
59
|
# The period the limit applies to
|
65
|
-
|
66
|
-
|
67
|
-
|
60
|
+
usage_report.period # :day
|
61
|
+
usage_report.period_start # "Wed Apr 28 00:00:00 +0200 2010"
|
62
|
+
usage_report.period_end # "Wed Apr 28 23:59:59 +0200 2010"
|
68
63
|
|
69
|
-
# The current value the
|
70
|
-
|
64
|
+
# The current value the application already consumed in the period
|
65
|
+
usage_report.current_value # 8032
|
71
66
|
|
72
67
|
# The maximal value allowed by the limit in the period
|
73
|
-
|
74
|
-
|
75
|
-
If the authorization failed, the +errors+ method contains one or more errors with more
|
76
|
-
detailed information:
|
77
|
-
|
78
|
-
error = response.errors[0]
|
68
|
+
usage_report.max_value # 10000
|
79
69
|
|
80
|
-
#
|
81
|
-
|
70
|
+
# If the limit is exceeded, this will be true, otherwise false:
|
71
|
+
usage_report.exceeded? # false
|
82
72
|
|
83
|
-
|
84
|
-
|
73
|
+
If the authorization failed, the +error_code+ returns system error code and +error_message+
|
74
|
+
human readable error description:
|
75
|
+
|
76
|
+
response.error_code # "usage_limits_exceeded"
|
77
|
+
response.error_message # "Usage limits are exceeded"
|
85
78
|
|
86
79
|
=== Report
|
87
80
|
|
88
81
|
To report usage, use the +report+ method. You can report multiple transaction at the same time:
|
89
82
|
|
90
|
-
response = client.report({:
|
91
|
-
{:
|
83
|
+
response = client.report({:app_id => "first app id", :usage => {'hits' => 1}},
|
84
|
+
{:app_id => "second app id", :usage => {'hits' => 1}})
|
92
85
|
|
93
|
-
The :
|
86
|
+
The :app_id and :usage parameters are required. Additionaly, you can specify a timestamp
|
94
87
|
of transaction:
|
95
88
|
|
96
|
-
response = client.report({:
|
89
|
+
response = client.report({:app_id => "app id", :usage => {'hits' => 1},
|
97
90
|
:timestamp => Time.local(2010, 4, 28, 12, 36)})
|
98
91
|
|
99
92
|
The timestamp can be either a Time object (from ruby's standard library) or something that
|
@@ -111,19 +104,14 @@ successful.
|
|
111
104
|
if response.success?
|
112
105
|
# All OK.
|
113
106
|
else
|
114
|
-
# There
|
107
|
+
# There was an error.
|
115
108
|
end
|
116
109
|
|
117
|
-
|
118
|
-
|
119
|
-
returns numeric index of the transaction this error corresponds to. For example, if you report
|
120
|
-
three transactions, first two are ok and the last one has invalid user key, there will be
|
121
|
-
an error in the +errors+ array with the +index+ equal to 2 (the indices start at 0):
|
110
|
+
In case of error, the +error_code+ returns system error code and +error_message+
|
111
|
+
human readable error description:
|
122
112
|
|
123
|
-
|
124
|
-
|
125
|
-
error.code # "user.invalid_key"
|
126
|
-
error.message # "User key is invalid"
|
113
|
+
response.error_code # "provider_key_invalid"
|
114
|
+
response.error_message # "provider key \"foo\" is invalid"
|
127
115
|
|
128
116
|
== Legal
|
129
117
|
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.2.4
|
@@ -2,14 +2,14 @@ require 'time'
|
|
2
2
|
|
3
3
|
module ThreeScale
|
4
4
|
class AuthorizeResponse < Response
|
5
|
-
def initialize
|
6
|
-
super
|
7
|
-
@
|
5
|
+
def initialize
|
6
|
+
super
|
7
|
+
@usage_reports = []
|
8
8
|
end
|
9
9
|
|
10
10
|
attr_accessor :plan
|
11
11
|
|
12
|
-
class
|
12
|
+
class UsageReport
|
13
13
|
attr_reader :metric
|
14
14
|
attr_reader :period
|
15
15
|
attr_reader :current_value
|
@@ -28,12 +28,16 @@ module ThreeScale
|
|
28
28
|
def period_end
|
29
29
|
@parsed_period_end ||= @period_end && Time.parse(@period_end)
|
30
30
|
end
|
31
|
+
|
32
|
+
def exceeded?
|
33
|
+
current_value > max_value
|
34
|
+
end
|
31
35
|
end
|
32
36
|
|
33
|
-
attr_reader :
|
37
|
+
attr_reader :usage_reports
|
34
38
|
|
35
|
-
def
|
36
|
-
@
|
39
|
+
def add_usage_report(options)
|
40
|
+
@usage_reports << UsageReport.new(options)
|
37
41
|
end
|
38
42
|
end
|
39
43
|
end
|
@@ -3,8 +3,8 @@ require 'uri'
|
|
3
3
|
require 'net/http'
|
4
4
|
require 'nokogiri'
|
5
5
|
|
6
|
-
require '
|
7
|
-
require '
|
6
|
+
require '3scale/response'
|
7
|
+
require '3scale/authorize_response'
|
8
8
|
|
9
9
|
module ThreeScale
|
10
10
|
Error = Class.new(RuntimeError)
|
@@ -24,10 +24,10 @@ module ThreeScale
|
|
24
24
|
#
|
25
25
|
# client = ThreeScale::Client.new(:provider_key => "your provider key")
|
26
26
|
#
|
27
|
-
# response = client.authorize(:
|
27
|
+
# response = client.authorize(:app_id => "an app id", :app_key => "a secret key")
|
28
28
|
#
|
29
29
|
# if response.success?
|
30
|
-
# response = client.report(:
|
30
|
+
# response = client.report(:app_id => "some app id", :usage => {"hits" => 1})
|
31
31
|
#
|
32
32
|
# if response.success?
|
33
33
|
# # all fine.
|
@@ -37,7 +37,7 @@ module ThreeScale
|
|
37
37
|
# end
|
38
38
|
#
|
39
39
|
class Client
|
40
|
-
DEFAULT_HOST = '
|
40
|
+
DEFAULT_HOST = 'su1.3scale.net'
|
41
41
|
|
42
42
|
def initialize(options)
|
43
43
|
if options[:provider_key].nil? || options[:provider_key] =~ /^\s*$/
|
@@ -58,7 +58,7 @@ module ThreeScale
|
|
58
58
|
# The parameters the transactions to report. Each transaction is a hash with
|
59
59
|
# these elements:
|
60
60
|
#
|
61
|
-
#
|
61
|
+
# app_id:: ID of the application to report the transaction for. This parameter is
|
62
62
|
# required.
|
63
63
|
# usage:: Hash of usage values. The keys are metric names and values are
|
64
64
|
# correspoding numeric values. Example: {'hits' => 1, 'transfer' => 1024}.
|
@@ -81,12 +81,12 @@ module ThreeScale
|
|
81
81
|
#
|
82
82
|
# == Examples
|
83
83
|
#
|
84
|
-
# # Report two transactions of two
|
85
|
-
# client.report({:
|
86
|
-
# {:
|
84
|
+
# # Report two transactions of two applications.
|
85
|
+
# client.report({:app_id => 'foo', :usage => {'hits' => 1}},
|
86
|
+
# {:app_id => 'bar', :usage => {'hits' => 1}})
|
87
87
|
#
|
88
88
|
# # Report one transaction with timestamp.
|
89
|
-
# client.report({:
|
89
|
+
# client.report({:app_id => 'foo',
|
90
90
|
# :timestamp => Time.local(2010, 4, 27, 15, 14),
|
91
91
|
# :usage => {'hits' => 1})
|
92
92
|
#
|
@@ -97,34 +97,42 @@ module ThreeScale
|
|
97
97
|
payload['provider_key'] = CGI.escape(provider_key)
|
98
98
|
|
99
99
|
uri = URI.parse("http://#{host}/transactions.xml")
|
100
|
-
|
101
|
-
|
102
|
-
|
100
|
+
http_response = Net::HTTP.post_form(uri, payload)
|
101
|
+
|
102
|
+
case http_response
|
103
|
+
when Net::HTTPSuccess
|
104
|
+
build_report_response
|
105
|
+
when Net::HTTPClientError
|
106
|
+
build_error_response(http_response.body)
|
107
|
+
else
|
108
|
+
raise ServerError.new(http_response)
|
103
109
|
end
|
104
110
|
end
|
105
111
|
|
106
|
-
# Authorize
|
112
|
+
# Authorize an application.
|
107
113
|
#
|
108
114
|
# == Parameters
|
109
115
|
#
|
110
116
|
# Hash with options:
|
111
117
|
#
|
112
|
-
#
|
118
|
+
# app_id:: id of the application to authorize. This is required.
|
119
|
+
# app_key:: secret key assigned to the application. Required only if application has
|
120
|
+
# a key defined.
|
113
121
|
#
|
114
122
|
# == Return
|
115
123
|
#
|
116
124
|
# An ThreeScale::AuthorizeResponse object. It's +success?+ method returns true if
|
117
|
-
# the authorization is successful
|
118
|
-
# about the status of the
|
119
|
-
# In case of error, the +
|
120
|
-
#
|
125
|
+
# the authorization is successful, false otherwise. It contains additional information
|
126
|
+
# about the status of the usage. See the ThreeScale::AuthorizeResponse for more information.
|
127
|
+
# In case of error, the +error_code+ returns code of the error and +error_message+
|
128
|
+
# human readable error description.
|
121
129
|
#
|
122
130
|
# In case of unexpected internal server error, this method raises a ThreeScale::ServerError
|
123
131
|
# exception.
|
124
132
|
#
|
125
133
|
# == Examples
|
126
134
|
#
|
127
|
-
# response = client.authorize(:
|
135
|
+
# response = client.authorize(:app_id => '1234')
|
128
136
|
#
|
129
137
|
# if response.success?
|
130
138
|
# # All good. Proceed...
|
@@ -133,21 +141,15 @@ module ThreeScale
|
|
133
141
|
def authorize(options)
|
134
142
|
path = "/transactions/authorize.xml" +
|
135
143
|
"?provider_key=#{CGI.escape(provider_key)}" +
|
136
|
-
"&
|
144
|
+
"&app_id=#{CGI.escape(options[:app_id].to_s)}"
|
145
|
+
path += "&app_key=#{CGI.escape(options[:app_key])}" if options[:app_key]
|
137
146
|
|
138
147
|
uri = URI.parse("http://#{host}#{path}")
|
148
|
+
http_response = Net::HTTP.get_response(uri)
|
139
149
|
|
140
|
-
process_response(Net::HTTP.get_response(uri)) do |http_response|
|
141
|
-
build_authorize_response(http_response.body)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
private
|
146
|
-
|
147
|
-
def process_response(http_response)
|
148
150
|
case http_response
|
149
151
|
when Net::HTTPSuccess
|
150
|
-
|
152
|
+
build_authorize_response(http_response.body)
|
151
153
|
when Net::HTTPClientError
|
152
154
|
build_error_response(http_response.body)
|
153
155
|
else
|
@@ -155,11 +157,13 @@ module ThreeScale
|
|
155
157
|
end
|
156
158
|
end
|
157
159
|
|
160
|
+
private
|
161
|
+
|
158
162
|
def encode_transactions(transactions)
|
159
163
|
result = {}
|
160
164
|
|
161
165
|
transactions.each_with_index do |transaction, index|
|
162
|
-
append_encoded_value(result, index, [:
|
166
|
+
append_encoded_value(result, index, [:app_id], transaction[:app_id])
|
163
167
|
append_encoded_value(result, index, [:timestamp], transaction[:timestamp])
|
164
168
|
append_encoded_value(result, index, [:client_ip], transaction[:client_ip])
|
165
169
|
|
@@ -175,38 +179,42 @@ module ThreeScale
|
|
175
179
|
result["transactions[#{index}][#{names.join('][')}]"] = CGI.escape(value.to_s) if value
|
176
180
|
end
|
177
181
|
|
182
|
+
def build_report_response
|
183
|
+
response = Response.new
|
184
|
+
response.success!
|
185
|
+
response
|
186
|
+
end
|
187
|
+
|
178
188
|
def build_authorize_response(body)
|
179
189
|
response = AuthorizeResponse.new
|
180
190
|
doc = Nokogiri::XML(body)
|
181
191
|
|
192
|
+
if doc.at_css('authorized').content == 'true'
|
193
|
+
response.success!
|
194
|
+
else
|
195
|
+
response.error!(doc.at_css('reason').content)
|
196
|
+
end
|
197
|
+
|
182
198
|
response.plan = doc.at_css('plan').content.to_s.strip
|
183
199
|
|
184
|
-
doc.css('
|
185
|
-
response.
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
200
|
+
doc.css('usage_reports usage_report').each do |node|
|
201
|
+
response.add_usage_report(:metric => node['metric'].to_s.strip,
|
202
|
+
:period => node['period'].to_s.strip.to_sym,
|
203
|
+
:period_start => node.at('period_start').content,
|
204
|
+
:period_end => node.at('period_end').content,
|
205
|
+
:current_value => node.at('current_value').content.to_i,
|
206
|
+
:max_value => node.at('max_value').content.to_i)
|
191
207
|
end
|
192
208
|
|
193
209
|
response
|
194
210
|
end
|
195
211
|
|
196
212
|
def build_error_response(body)
|
197
|
-
response = Response.new(:success => false)
|
198
213
|
doc = Nokogiri::XML(body)
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
# Backwards compatibility: error code is sometimes in
|
204
|
-
# the "id" attribute.
|
205
|
-
node['code'] || node['id'],
|
206
|
-
|
207
|
-
node.content.to_s.strip)
|
208
|
-
end
|
209
|
-
|
214
|
+
node = doc.at_css('error')
|
215
|
+
|
216
|
+
response = Response.new
|
217
|
+
response.error!(node.content.to_s.strip, node['code'].to_s.strip)
|
210
218
|
response
|
211
219
|
end
|
212
220
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ThreeScale
|
2
|
+
class Response
|
3
|
+
def success!
|
4
|
+
@error_code = nil
|
5
|
+
@error_message = nil
|
6
|
+
end
|
7
|
+
|
8
|
+
def error!(message, code = nil)
|
9
|
+
@error_code = code
|
10
|
+
@error_message = message
|
11
|
+
end
|
12
|
+
|
13
|
+
def success?
|
14
|
+
@error_code.nil? && @error_message.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
# System error code.
|
18
|
+
attr_reader :error_code
|
19
|
+
|
20
|
+
# Human readable error message.
|
21
|
+
attr_reader :error_message
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
data/test/client_test.rb
CHANGED
@@ -2,7 +2,7 @@ require 'test/unit'
|
|
2
2
|
require 'fakeweb'
|
3
3
|
require 'mocha'
|
4
4
|
|
5
|
-
require '
|
5
|
+
require '3scale/client'
|
6
6
|
|
7
7
|
class ThreeScale::ClientTest < Test::Unit::TestCase
|
8
8
|
def setup
|
@@ -10,6 +10,7 @@ class ThreeScale::ClientTest < Test::Unit::TestCase
|
|
10
10
|
FakeWeb.allow_net_connect = false
|
11
11
|
|
12
12
|
@client = ThreeScale::Client.new(:provider_key => '1234abcd')
|
13
|
+
@host = ThreeScale::Client::DEFAULT_HOST
|
13
14
|
end
|
14
15
|
|
15
16
|
def test_raises_exception_if_provider_key_is_missing
|
@@ -21,69 +22,114 @@ class ThreeScale::ClientTest < Test::Unit::TestCase
|
|
21
22
|
def test_default_host
|
22
23
|
client = ThreeScale::Client.new(:provider_key => '1234abcd')
|
23
24
|
|
24
|
-
assert_equal '
|
25
|
+
assert_equal 'su1.3scale.net', client.host
|
25
26
|
end
|
26
27
|
|
27
28
|
def test_successful_authorize
|
28
29
|
body = '<status>
|
30
|
+
<authorized>true</authorized>
|
29
31
|
<plan>Ultimate</plan>
|
30
|
-
|
31
|
-
<
|
32
|
-
<
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
<
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
32
|
+
|
33
|
+
<usage_reports>
|
34
|
+
<usage_report metric="hits" period="day">
|
35
|
+
<period_start>2010-04-26 00:00:00 +0000</period_start>
|
36
|
+
<period_end>2010-04-27 00:00:00 +0000</period_end>
|
37
|
+
<current_value>10023</current_value>
|
38
|
+
<max_value>50000</max_value>
|
39
|
+
</usage_report>
|
40
|
+
|
41
|
+
<usage_report metric="hits" period="month">
|
42
|
+
<period_start>2010-04-01 00:00:00 +0000</period_start>
|
43
|
+
<period_end>2010-05-01 00:00:00 +0000</period_end>
|
44
|
+
<current_value>999872</current_value>
|
45
|
+
<max_value>150000</max_value>
|
46
|
+
</usage_report>
|
47
|
+
</usage_reports>
|
44
48
|
</status>'
|
45
49
|
|
46
|
-
FakeWeb.register_uri(:get,
|
50
|
+
FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['200', 'OK'], :body => body)
|
47
51
|
|
48
|
-
response = @client.authorize(:
|
52
|
+
response = @client.authorize(:app_id => 'foo')
|
49
53
|
|
50
54
|
assert response.success?
|
51
55
|
assert_equal 'Ultimate', response.plan
|
52
|
-
assert_equal 2, response.
|
56
|
+
assert_equal 2, response.usage_reports.size
|
53
57
|
|
54
|
-
assert_equal :day, response.
|
55
|
-
assert_equal Time.
|
56
|
-
assert_equal Time.
|
57
|
-
assert_equal 10023, response.
|
58
|
-
assert_equal 50000, response.
|
59
|
-
|
60
|
-
assert_equal :month, response.
|
61
|
-
assert_equal Time.
|
62
|
-
assert_equal Time.
|
63
|
-
assert_equal 999872, response.
|
64
|
-
assert_equal 150000, response.
|
58
|
+
assert_equal :day, response.usage_reports[0].period
|
59
|
+
assert_equal Time.utc(2010, 4, 26), response.usage_reports[0].period_start
|
60
|
+
assert_equal Time.utc(2010, 4, 27), response.usage_reports[0].period_end
|
61
|
+
assert_equal 10023, response.usage_reports[0].current_value
|
62
|
+
assert_equal 50000, response.usage_reports[0].max_value
|
63
|
+
|
64
|
+
assert_equal :month, response.usage_reports[1].period
|
65
|
+
assert_equal Time.utc(2010, 4, 1), response.usage_reports[1].period_start
|
66
|
+
assert_equal Time.utc(2010, 5, 1), response.usage_reports[1].period_end
|
67
|
+
assert_equal 999872, response.usage_reports[1].current_value
|
68
|
+
assert_equal 150000, response.usage_reports[1].max_value
|
65
69
|
end
|
70
|
+
|
71
|
+
def test_successful_authorize_with_app_keys
|
72
|
+
body = '<status>
|
73
|
+
<authorized>true</authorized>
|
74
|
+
<plan>Ultimate</plan>
|
75
|
+
</status>'
|
76
|
+
|
77
|
+
FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo&app_key=toosecret", :status => ['200', 'OK'], :body => body)
|
66
78
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
79
|
+
response = @client.authorize(:app_id => 'foo', :app_key => 'toosecret')
|
80
|
+
assert response.success?
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_authorize_with_exceeded_usage_limits
|
84
|
+
body = '<status>
|
85
|
+
<authorized>false</authorized>
|
86
|
+
<reason>usage limits are exceeded</reason>
|
87
|
+
|
88
|
+
<plan>Ultimate</plan>
|
89
|
+
|
90
|
+
<usage_reports>
|
91
|
+
<usage_report metric="hits" period="day" exceeded="true">
|
92
|
+
<period_start>2010-04-26 00:00:00 +0000</period_start>
|
93
|
+
<period_end>2010-04-27 00:00:00 +0000</period_end>
|
94
|
+
<current_value>50002</current_value>
|
95
|
+
<max_value>50000</max_value>
|
96
|
+
</usage_report>
|
97
|
+
|
98
|
+
<usage_report metric="hits" period="month">
|
99
|
+
<period_start>2010-04-01 00:00:00 +0000</period_start>
|
100
|
+
<period_end>2010-05-01 00:00:00 +0000</period_end>
|
101
|
+
<current_value>999872</current_value>
|
102
|
+
<max_value>150000</max_value>
|
103
|
+
</usage_report>
|
104
|
+
</usage_reports>
|
105
|
+
</status>'
|
106
|
+
|
107
|
+
FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['200', 'OK'], :body => body)
|
71
108
|
|
72
|
-
|
109
|
+
response = @client.authorize(:app_id => 'foo')
|
110
|
+
|
111
|
+
assert !response.success?
|
112
|
+
assert_equal 'usage limits are exceeded', response.error_message
|
113
|
+
assert response.usage_reports[0].exceeded?
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_authorize_with_invalid_app_id
|
117
|
+
body = '<error code="application_not_found">application with id="foo" was not found</error>'
|
73
118
|
|
74
|
-
|
119
|
+
FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['403', 'Forbidden'], :body => body)
|
120
|
+
|
121
|
+
response = @client.authorize(:app_id => 'foo')
|
75
122
|
|
76
123
|
assert !response.success?
|
77
|
-
assert_equal
|
78
|
-
assert_equal '
|
79
|
-
assert_equal 'usage limits are exceeded', response.errors[0].message
|
124
|
+
assert_equal 'application_not_found', response.error_code
|
125
|
+
assert_equal 'application with id="foo" was not found', response.error_message
|
80
126
|
end
|
81
127
|
|
82
128
|
def test_authorize_with_server_error
|
83
|
-
FakeWeb.register_uri(:get,
|
129
|
+
FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['500', 'Internal Server Error'], :body => 'OMG! WTF!')
|
84
130
|
|
85
131
|
assert_raise ThreeScale::ServerError do
|
86
|
-
@client.authorize(:
|
132
|
+
@client.authorize(:app_id => 'foo')
|
87
133
|
end
|
88
134
|
end
|
89
135
|
|
@@ -94,10 +140,10 @@ class ThreeScale::ClientTest < Test::Unit::TestCase
|
|
94
140
|
end
|
95
141
|
|
96
142
|
def test_successful_report
|
97
|
-
FakeWeb.register_uri(:post,
|
143
|
+
FakeWeb.register_uri(:post, "http://#{@host}/transactions.xml",
|
98
144
|
:status => ['200', 'OK'])
|
99
145
|
|
100
|
-
response = @client.report({:
|
146
|
+
response = @client.report({:app_id => 'foo',
|
101
147
|
:timestamp => Time.local(2010, 4, 27, 15, 00),
|
102
148
|
:usage => {'hits' => 1}})
|
103
149
|
|
@@ -111,59 +157,45 @@ class ThreeScale::ClientTest < Test::Unit::TestCase
|
|
111
157
|
Net::HTTP.expects(:post_form).
|
112
158
|
with(anything,
|
113
159
|
'provider_key' => '1234abcd',
|
114
|
-
'transactions[0][
|
160
|
+
'transactions[0][app_id]' => 'foo',
|
115
161
|
'transactions[0][usage][hits]' => '1',
|
116
162
|
'transactions[0][timestamp]' => CGI.escape('2010-04-27 15:42:17 0200'),
|
117
|
-
'transactions[1][
|
163
|
+
'transactions[1][app_id]' => 'bar',
|
118
164
|
'transactions[1][usage][hits]' => '1',
|
119
165
|
'transactions[1][timestamp]' => CGI.escape('2010-04-27 15:55:12 0200')).
|
120
166
|
returns(http_response)
|
121
167
|
|
122
|
-
@client.report({:
|
168
|
+
@client.report({:app_id => 'foo',
|
123
169
|
:usage => {'hits' => 1},
|
124
170
|
:timestamp => '2010-04-27 15:42:17 0200'},
|
125
171
|
|
126
|
-
{:
|
172
|
+
{:app_id => 'bar',
|
127
173
|
:usage => {'hits' => 1},
|
128
174
|
:timestamp => '2010-04-27 15:55:12 0200'})
|
129
175
|
end
|
130
176
|
|
131
177
|
def test_failed_report
|
132
|
-
error_body = '<
|
133
|
-
|
134
|
-
|
135
|
-
</error>
|
136
|
-
<error code="provider.invalid_metric" index="1">
|
137
|
-
metric does not exist
|
138
|
-
</error>
|
139
|
-
</errors>'
|
140
|
-
|
141
|
-
FakeWeb.register_uri(:post, 'http://server.3scale.net/transactions.xml',
|
178
|
+
error_body = '<error code="provider_key_invalid">provider key "foo" is invalid</error>'
|
179
|
+
|
180
|
+
FakeWeb.register_uri(:post, "http://#{@host}/transactions.xml",
|
142
181
|
:status => ['403', 'Forbidden'],
|
143
182
|
:body => error_body)
|
144
183
|
|
145
|
-
|
146
|
-
|
184
|
+
client = ThreeScale::Client.new(:provider_key => 'foo')
|
185
|
+
response = client.report({:app_id => 'abc', :usage => {'hits' => 1}})
|
147
186
|
|
148
187
|
assert !response.success?
|
149
|
-
assert_equal
|
150
|
-
|
151
|
-
assert_equal 0, response.errors[0].index
|
152
|
-
assert_equal 'user.invalid_key', response.errors[0].code
|
153
|
-
assert_equal 'user key is invalid', response.errors[0].message
|
154
|
-
|
155
|
-
assert_equal 1, response.errors[1].index
|
156
|
-
assert_equal 'provider.invalid_metric', response.errors[1].code
|
157
|
-
assert_equal 'metric does not exist', response.errors[1].message
|
188
|
+
assert_equal 'provider_key_invalid', response.error_code
|
189
|
+
assert_equal 'provider key "foo" is invalid', response.error_message
|
158
190
|
end
|
159
191
|
|
160
192
|
def test_report_with_server_error
|
161
|
-
FakeWeb.register_uri(:post,
|
193
|
+
FakeWeb.register_uri(:post, "http://#{@host}/transactions.xml",
|
162
194
|
:status => ['500', 'Internal Server Error'],
|
163
195
|
:body => 'OMG! WTF!')
|
164
196
|
|
165
197
|
assert_raise ThreeScale::ServerError do
|
166
|
-
@client.report({:
|
198
|
+
@client.report({:app_id => 'foo', :usage => {'hits' => 1}})
|
167
199
|
end
|
168
200
|
end
|
169
201
|
end
|
data/test/remote_test.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
require 'test/unit'
|
2
|
-
require '
|
2
|
+
require '3scale/client'
|
3
3
|
|
4
|
-
if ENV['TEST_3SCALE_PROVIDER_KEY'] &&
|
4
|
+
if ENV['TEST_3SCALE_PROVIDER_KEY'] &&
|
5
|
+
ENV['TEST_3SCALE_APP_IDS'] &&
|
6
|
+
ENV['TEST_3SCALE_APP_KEYS']
|
5
7
|
class ThreeScale::RemoteTest < Test::Unit::TestCase
|
6
8
|
def setup
|
7
9
|
@provider_key = ENV['TEST_3SCALE_PROVIDER_KEY']
|
8
|
-
|
10
|
+
|
11
|
+
stripper = lambda { |string| string.strip }
|
12
|
+
|
13
|
+
@app_ids = ENV['TEST_3SCALE_APP_IDS'].split(',').map(&stripper)
|
14
|
+
@app_keys = ENV['TEST_3SCALE_APP_KEYS'].split(',').map(&stripper)
|
9
15
|
|
10
16
|
@client = ThreeScale::Client.new(:provider_key => @provider_key)
|
11
17
|
|
@@ -16,26 +22,44 @@ if ENV['TEST_3SCALE_PROVIDER_KEY'] && ENV['TEST_3SCALE_USER_KEYS']
|
|
16
22
|
end
|
17
23
|
|
18
24
|
def test_successful_authorize
|
19
|
-
|
20
|
-
|
25
|
+
@app_keys.each do |app_key|
|
26
|
+
response = @client.authorize(:app_id => @app_ids[0], :app_key => app_key)
|
27
|
+
assert response.success?, "Authorize should succeed for app_id=#{@app_ids[0]} and app_key=#{app_key}, but it didn't"
|
28
|
+
end
|
21
29
|
end
|
22
30
|
|
23
31
|
def test_failed_authorize
|
24
|
-
response = @client.authorize(:
|
32
|
+
response = @client.authorize(:app_id => 'invalid-id')
|
25
33
|
assert !response.success?
|
26
|
-
assert_equal '
|
34
|
+
assert_equal 'application_not_found', response.error_code
|
35
|
+
assert_equal 'application with id="invalid-id" was not found', response.error_message
|
27
36
|
end
|
28
37
|
|
29
38
|
def test_successful_report
|
30
|
-
transactions = @
|
31
|
-
{:
|
39
|
+
transactions = @app_ids.map do |app_id|
|
40
|
+
{:app_id => app_id, :usage => {'hits' => 1}}
|
32
41
|
end
|
33
42
|
|
34
43
|
response = @client.report(*transactions)
|
35
44
|
assert response.success?
|
36
45
|
end
|
46
|
+
|
47
|
+
def test_failed_report
|
48
|
+
transactions = @app_ids.map do |app_id|
|
49
|
+
{:app_id => app_id, :usage => {'hits' => 1}}
|
50
|
+
end
|
51
|
+
|
52
|
+
client = ThreeScale::Client.new(:provider_key => 'invalid-key')
|
53
|
+
response = client.report(*transactions)
|
54
|
+
assert !response.success?
|
55
|
+
assert_equal 'provider_key_invalid', response.error_code
|
56
|
+
assert_equal 'provider key "invalid-key" is invalid', response.error_message
|
57
|
+
end
|
37
58
|
end
|
38
59
|
|
39
60
|
else
|
40
|
-
puts "
|
61
|
+
puts "This test executes real requests against 3scale backend server. It needs to know provider key, application ids and application keys to use in the requests. You have to set these environment variables:"
|
62
|
+
puts " * TEST_3SCALE_PROVIDER_KEY - a provider key."
|
63
|
+
puts " * TEST_3SCALE_APP_IDS - list of application ids, separated by commas."
|
64
|
+
puts " * TEST_3SCALE_APP_KEYS - list of application keys corresponding to the FIRST id in the TEST_3SCALE_APP_IDS list. Also separated by commas."
|
41
65
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 2
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 2.
|
7
|
+
- 2
|
8
|
+
- 4
|
9
|
+
version: 2.2.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- "Adam Cig\xC3\xA1nek"
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-09-15 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -46,9 +46,9 @@ files:
|
|
46
46
|
- README.rdoc
|
47
47
|
- Rakefile
|
48
48
|
- VERSION
|
49
|
-
- lib/
|
50
|
-
- lib/
|
51
|
-
- lib/
|
49
|
+
- lib/3scale/authorize_response.rb
|
50
|
+
- lib/3scale/client.rb
|
51
|
+
- lib/3scale/response.rb
|
52
52
|
- test/client_test.rb
|
53
53
|
- test/remote_test.rb
|
54
54
|
has_rdoc: true
|
data/lib/three_scale/response.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module ThreeScale
|
2
|
-
class Response
|
3
|
-
def initialize(options)
|
4
|
-
@success = options[:success]
|
5
|
-
@errors = options[:errors] || []
|
6
|
-
end
|
7
|
-
|
8
|
-
def success?
|
9
|
-
@success
|
10
|
-
end
|
11
|
-
|
12
|
-
Error = Struct.new(:index, :code, :message)
|
13
|
-
|
14
|
-
attr_reader :errors
|
15
|
-
|
16
|
-
def add_error(*args)
|
17
|
-
@errors << Error.new(*args)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|