sailthru-client 4.0.7 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 067482a879f7af281db3f53988a0595665dea658
4
- data.tar.gz: 1bf7045b497d4b74ee60b85f14c8139dbc8734de
3
+ metadata.gz: 861a575aa56944d027c0cc7e3fbd52a9c266abc0
4
+ data.tar.gz: 55d80097eb3dc65651a27c90e27d2a481f113019
5
5
  SHA512:
6
- metadata.gz: 8928a8a8858455f45358303db337749c9d4a32c865ffa84d72a809729bcac1194c783a720ff39d6dc82ee095a9bec92c6896b129745f35b59cc0ad59a25bdbc0
7
- data.tar.gz: 40776ddd4d7a5f738d0cf57e04eda271d2748799ea8dc2fe54dcf884a7a2b27ac69bcd22d7d931117c670e63034c6d9ae5b0dea1cb3df52d2dbb46f2a58e5a2e
6
+ metadata.gz: a4d39c922e39970f6bcf10063efdf015b513da719fef606092e69e594603d3a3e83f2631a2b491b7bcd463bd50867b23200c9f87b7ded646b1dc8b969f832f90
7
+ data.tar.gz: 7b30e7fc8563837c3176de48bc6edc2674d21b240085a6314510a3138811dab377e6e8a0fa6b7b135239a78a3f53a6281f652604c81b9ecda7f8f04cebdf627c
@@ -1,3 +1,6 @@
1
+ ## 4.1.0
2
+ - added get_last_rate_limit_info method call
3
+
1
4
  ## 4.0.3
2
5
  - Explicitly enable TLS (version 1.0)
3
6
 
data/README.md CHANGED
@@ -24,6 +24,28 @@ sailthru = Sailthru::Client.new("api-key", "api-secret", "https://api.sailthru.c
24
24
  {:http_read_timeout => 30, :http_ssl_timeout => 30, :http_open_timeout => 30})
25
25
  ```
26
26
 
27
+ ## Rate Limit Information
28
+
29
+ The library allows inspection of the 'X-Rate-Limit-*' headers returned by the Sailthru API. The `get_last_rate_limit_info(endpoint, method)` function allows you to retrieve the last known rate limit information for the given endpoint / method combination. It must follow an API call. For example, if you do a `/send POST`, you can follow up with a call to `get_last_rate_limit_info(:send, :post)` as shown below:
30
+
31
+ ``` ruby
32
+ # make API call as normal
33
+ response = sailthru.send_email template_name, email, {foo: "bar"}
34
+
35
+ # check rate limit information
36
+ rate_limit_info = sailthru.get_last_rate_limit_info :send, :post
37
+ ```
38
+
39
+ The return type will be `nil` if there is no rate limit information for the given endpoint / method combination (e.g. if you have not yet made a request to that endpoint). Otherwise, it will be a hash in the following format:
40
+
41
+ ``` ruby
42
+ {
43
+ limit: 1234, # <Number representing the limit of requests/minute for this action / method combination>
44
+ remaining: 1230, # <Number representing how many requests remain in the current minute>
45
+ reset: 1459381680 # <Number representing the UNIX epoch timestamp of when the next minute starts, and when the rate limit resets>
46
+ }
47
+ ```
48
+
27
49
  ## License
28
50
 
29
51
  Please see MIT-LICENSE for license.
@@ -29,6 +29,7 @@ module Sailthru
29
29
  @proxy_port = proxy_port
30
30
  @verify_ssl = true
31
31
  @opts = opts
32
+ @last_rate_limit_info = {}
32
33
  end
33
34
 
34
35
  # params:
@@ -746,6 +747,21 @@ module Sailthru
746
747
  api_request(action, data, 'DELETE')
747
748
  end
748
749
 
750
+ # params
751
+ # endpoint, String a e.g. "user" or "send"
752
+ # method, String "GET" or "POST"
753
+ # returns
754
+ # Hash rate info
755
+ # Get rate info for a particular endpoint/method, as of the last time a request was sent to the given endpoint/method
756
+ # Includes the following keys:
757
+ # limit: the per-minute limit for the given endpoint/method
758
+ # remaining: the number of allotted requests remaining in the current minute for the given endpoint/method
759
+ # reset: unix timestamp of the top of the next minute, when the rate limit will reset
760
+ def get_last_rate_limit_info(endpoint, method)
761
+ rate_info_key = get_rate_limit_info_key(endpoint, method)
762
+ @last_rate_limit_info[rate_info_key]
763
+ end
764
+
749
765
  protected
750
766
 
751
767
  # params:
@@ -774,7 +790,7 @@ module Sailthru
774
790
  if !binary_key.nil?
775
791
  data[binary_key] = binary_key_data
776
792
  end
777
- _result = http_request("#{@api_uri}/#{action}", data, request_type, binary_key)
793
+ _result = http_request(action, data, request_type, binary_key)
778
794
 
779
795
  # NOTE: don't do the unserialize here
780
796
  if data[:format] == 'json'
@@ -817,9 +833,10 @@ module Sailthru
817
833
  # method, String "GET" or "POST"
818
834
  # returns:
819
835
  # String, body of response
820
- def http_request(uri, data, method = 'POST', binary_key = nil)
836
+ def http_request(action, data, method = 'POST', binary_key = nil)
821
837
  data = flatten_nested_hash(data, false)
822
838
 
839
+ uri = "#{@api_uri}/#{action}"
823
840
  if method != 'POST'
824
841
  uri += "?" + data.map{ |key, value| "#{CGI::escape(key.to_s)}=#{CGI::escape(value.to_s)}" }.join("&")
825
842
  end
@@ -866,6 +883,8 @@ module Sailthru
866
883
  raise ClientError, "Unable to open stream to #{_uri}: #{e.message}"
867
884
  end
868
885
 
886
+ save_rate_limit_info(action, method, response)
887
+
869
888
  response.body || raise(ClientError, "No response received from stream: #{_uri}")
870
889
  end
871
890
 
@@ -883,5 +902,26 @@ module Sailthru
883
902
  payload[:sig] = get_signature_hash(payload, @secret)
884
903
  payload
885
904
  end
905
+
906
+ def save_rate_limit_info(action, method, response)
907
+ limit = response['x-rate-limit-limit'].to_i
908
+ remaining = response['x-rate-limit-remaining'].to_i
909
+ reset = response['x-rate-limit-reset'].to_i
910
+
911
+ if limit.nil? or remaining.nil? or reset.nil?
912
+ return
913
+ end
914
+
915
+ rate_info_key = get_rate_limit_info_key(action, method)
916
+ @last_rate_limit_info[rate_info_key] = {
917
+ limit: limit,
918
+ remaining: remaining,
919
+ reset: reset
920
+ }
921
+ end
922
+
923
+ def get_rate_limit_info_key(endpoint, method)
924
+ :"#{endpoint}_#{method.downcase}"
925
+ end
886
926
  end
887
927
  end
@@ -1,3 +1,3 @@
1
1
  module Sailthru
2
- VERSION = '4.0.7'
2
+ VERSION = '4.1.0'
3
3
  end
@@ -0,0 +1 @@
1
+ {"templates":[{"template_id": 23},{"template_id": 24}]}
@@ -3,7 +3,7 @@ require 'mocha/setup'
3
3
 
4
4
  class FileUploadTest < Minitest::Test
5
5
 
6
- describe "API Call: blast" do
6
+ describe "File Upload Functionality" do
7
7
 
8
8
  before do
9
9
  @secret = 'my_secret'
@@ -26,7 +26,8 @@ class FileUploadTest < Minitest::Test
26
26
  Net::HTTP.stubs(:Proxy).returns(Net::HTTP)
27
27
  Net::HTTP.any_instance.stubs(
28
28
  :request => stub(
29
- "body" => JSON.unparse({"job_id" => "123"})
29
+ "body" => JSON.unparse({"job_id" => "123"}),
30
+ "[]" => nil
30
31
  )
31
32
  )
32
33
 
@@ -50,7 +51,8 @@ class FileUploadTest < Minitest::Test
50
51
  Net::HTTP.stubs(:Proxy).returns(Net::HTTP)
51
52
  Net::HTTP.any_instance.stubs(
52
53
  :request => stub(
53
- "body" => JSON.unparse({"job_id" => "123"})
54
+ "body" => JSON.unparse({"job_id" => "123"}),
55
+ "[]" => nil
54
56
  )
55
57
  )
56
58
 
@@ -0,0 +1,94 @@
1
+ require 'test_helper'
2
+
3
+ class RateInfoTest < Minitest::Test
4
+ describe "get_last_rate_limit_info() (All API Calls)" do
5
+ before do
6
+ @api_url = 'http://api.sailthru.com'
7
+ @secret = 'my_secret'
8
+ @api_key = 'my_api_key'
9
+ @sailthru_client = Sailthru::Client.new(@api_key, @secret, @api_url)
10
+ end
11
+
12
+ it "returns rate limit info for a given endpoint and method" do
13
+ # perform a /send GET request
14
+ api_call_url = sailthru_api_call_url(@api_url, 'send')
15
+ valid_send_id = "TT1ClGdj2bRHAAP6"
16
+ params = {
17
+ 'send_id' => valid_send_id
18
+ }
19
+ query_string = create_json_payload(@api_key, @secret, params)
20
+ rate_headers = get_rate_info_headers(3, 2, Time.now.to_i)
21
+ stub_get(api_call_url + '?' + query_string , 'send_get_valid.json', rate_headers)
22
+ response = @sailthru_client.get_send(valid_send_id)
23
+ assert_equal valid_send_id, response['send_id']
24
+
25
+ # verify the subsequent rate info for /send GET
26
+ rate_info = @sailthru_client.get_last_rate_limit_info(:send, :get)
27
+ assert_equal rate_headers[:x_rate_limit_limit], rate_info[:limit]
28
+ assert_equal rate_headers[:x_rate_limit_remaining], rate_info[:remaining]
29
+ assert_equal rate_headers[:x_rate_limit_reset], rate_info[:reset]
30
+ end
31
+
32
+ it "can return distinct rate limit info for different endpoints" do
33
+ # perform a /send GET request
34
+ send_api_call_url = sailthru_api_call_url(@api_url, 'send')
35
+ valid_send_id = "TT1ClGdj2bRHAAP6"
36
+ send_query_string = create_json_payload(@api_key, @secret, { 'send_id' => valid_send_id })
37
+ send_rate_headers = get_rate_info_headers(3, 2, Time.now.to_i + 10)
38
+ stub_get(send_api_call_url + '?' + send_query_string , 'send_get_valid.json', send_rate_headers)
39
+ response = @sailthru_client.get_send(valid_send_id)
40
+ assert_equal valid_send_id, response['send_id']
41
+
42
+ # perform a /list GET request -- and have this endpoint return different rate info
43
+ list_api_call_url = sailthru_api_call_url(@api_url, 'list')
44
+ list = 'list1'
45
+ list_query_string = create_json_payload(@api_key, @secret, {'list' => list})
46
+ list_rate_headers = get_rate_info_headers(5, 4, Time.now.to_i + 8)
47
+ stub_get(list_api_call_url + '?' + list_query_string, 'list_get_valid.json', list_rate_headers)
48
+ response = @sailthru_client.get_list(list)
49
+ assert_equal(response['list'], list)
50
+
51
+ # verify the rate info for each call
52
+ send_rate_info = @sailthru_client.get_last_rate_limit_info(:send, :get)
53
+ assert_equal send_rate_headers[:x_rate_limit_limit], send_rate_info[:limit]
54
+ assert_equal send_rate_headers[:x_rate_limit_remaining], send_rate_info[:remaining]
55
+ assert_equal send_rate_headers[:x_rate_limit_reset], send_rate_info[:reset]
56
+
57
+ list_rate_info = @sailthru_client.get_last_rate_limit_info(:list, :get)
58
+ assert_equal list_rate_headers[:x_rate_limit_limit], list_rate_info[:limit]
59
+ assert_equal list_rate_headers[:x_rate_limit_remaining], list_rate_info[:remaining]
60
+ assert_equal list_rate_headers[:x_rate_limit_reset], list_rate_info[:reset]
61
+ end
62
+
63
+ it "can return distinct rate limit info for different methods" do
64
+ api_call_url = sailthru_api_call_url(@api_url, 'send')
65
+
66
+ # perform a /send GET request
67
+ valid_send_id = "TT1ClGdj2bRHAAP6"
68
+ get_query_string = create_json_payload(@api_key, @secret, { 'send_id' => valid_send_id })
69
+ get_rate_headers = get_rate_info_headers(3, 2, Time.now.to_i + 10)
70
+ stub_get(api_call_url + '?' + get_query_string , 'send_get_valid.json', get_rate_headers)
71
+ response = @sailthru_client.get_send(valid_send_id)
72
+ assert_equal valid_send_id, response['send_id']
73
+
74
+ # perform a /send POST request -- and have this method return different rate info
75
+ template_name = 'default'
76
+ email = 'example@example.com'
77
+ post_rate_headers = get_rate_info_headers(5, 4, Time.now.to_i + 8)
78
+ stub_post(api_call_url, 'send_get_valid.json', post_rate_headers)
79
+ response = @sailthru_client.send_email template_name, email, {"name" => "Unix", "myvar" => [1111,2,3], "mycomplexvar" => {"tags" => ["obama", "aaa", "c"]}}
80
+ assert_equal template_name, response['template']
81
+
82
+ # verify the rate info for each call
83
+ get_rate_info = @sailthru_client.get_last_rate_limit_info(:send, :get)
84
+ assert_equal get_rate_headers[:x_rate_limit_limit], get_rate_info[:limit]
85
+ assert_equal get_rate_headers[:x_rate_limit_remaining], get_rate_info[:remaining]
86
+ assert_equal get_rate_headers[:x_rate_limit_reset], get_rate_info[:reset]
87
+
88
+ post_rate_info = @sailthru_client.get_last_rate_limit_info(:send, :post)
89
+ assert_equal post_rate_headers[:x_rate_limit_limit], post_rate_info[:limit]
90
+ assert_equal post_rate_headers[:x_rate_limit_remaining], post_rate_info[:remaining]
91
+ assert_equal post_rate_headers[:x_rate_limit_reset], post_rate_info[:reset]
92
+ end
93
+ end
94
+ end
@@ -28,6 +28,14 @@ class TemplateTest < Minitest::Test
28
28
  assert_equal 14, response['error']
29
29
  end
30
30
 
31
+ it "can get a list of all existing templates" do
32
+ query_string = create_json_payload(@api_key, @secret, {})
33
+ stub_get(@api_call_url + '?' + query_string, 'templates_get.json')
34
+ response = @sailthru_client.get_templates
35
+ assert response['templates'][0].has_key?('template_id')
36
+ refute_nil response['templates'][0]['template_id']
37
+ end
38
+
31
39
  it "can save template with given template name" do
32
40
  valid_template_name = 'my-template-new'
33
41
  from_email = 'praj@sailthru.com'
@@ -34,18 +34,22 @@ class Minitest::Test
34
34
  sailthru_api_base_url(url + action)
35
35
  end
36
36
 
37
- def stub_get(url, filename)
37
+ def stub_get(url, filename, headers={})
38
38
  options = { :body => fixture_file(filename), :content_type => 'application/json' }
39
+ options.merge!(headers)
39
40
  FakeWeb.register_uri(:get, URI.parse(url), options)
40
41
  end
41
42
 
42
- def stub_delete(url, filename)
43
+ def stub_delete(url, filename, headers={})
43
44
  options = { :body => fixture_file(filename), :content_type => 'application/json' }
45
+ options.merge!(headers)
44
46
  FakeWeb.register_uri(:delete, URI.parse(url), options)
45
47
  end
46
48
 
47
- def stub_post(url, filename)
48
- FakeWeb.register_uri(:post, URI.parse(url), :body => fixture_file(filename), :content_type => 'application/json')
49
+ def stub_post(url, filename, headers={})
50
+ options = { :body => fixture_file(filename), :content_type => 'application/json' }
51
+ options.merge!(headers)
52
+ FakeWeb.register_uri(:post, URI.parse(url), options)
49
53
  end
50
54
 
51
55
  def stub_exception(url, filename)
@@ -65,4 +69,13 @@ class Minitest::Test
65
69
  data['sig'] = get_signature_hash(data, secret)
66
70
  data.map{ |key, value| "#{CGI::escape(key.to_s)}=#{CGI::escape(value.to_s)}" }.join("&")
67
71
  end
72
+
73
+ def get_rate_info_headers(limit, remaining, reset)
74
+ {
75
+ :x_rate_limit_limit => limit,
76
+ :x_rate_limit_remaining => remaining,
77
+ :x_rate_limit_reset => reset
78
+ }
79
+ end
80
+
68
81
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sailthru-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.7
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Prajwal Tuladhar
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-02-23 00:00:00.000000000 Z
13
+ date: 2016-05-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -153,6 +153,7 @@ files:
153
153
  - test/fixtures/template_save.json
154
154
  - test/fixtures/template_save_test_vars.json
155
155
  - test/fixtures/template_valid_get.json
156
+ - test/fixtures/templates_get.json
156
157
  - test/fixtures/user_update_post_valid.json
157
158
  - test/fixtures/user_update_valid.json
158
159
  - test/sailthru/blast_test.rb
@@ -163,6 +164,7 @@ files:
163
164
  - test/sailthru/helpers_test.rb
164
165
  - test/sailthru/list_test.rb
165
166
  - test/sailthru/purchase_test.rb
167
+ - test/sailthru/rate_info_test.rb
166
168
  - test/sailthru/receive_post_callback_test.rb
167
169
  - test/sailthru/send_test.rb
168
170
  - test/sailthru/stats_test.rb
@@ -233,6 +235,7 @@ test_files:
233
235
  - test/fixtures/template_save.json
234
236
  - test/fixtures/template_save_test_vars.json
235
237
  - test/fixtures/template_valid_get.json
238
+ - test/fixtures/templates_get.json
236
239
  - test/fixtures/user_update_post_valid.json
237
240
  - test/fixtures/user_update_valid.json
238
241
  - test/sailthru/blast_test.rb
@@ -243,6 +246,7 @@ test_files:
243
246
  - test/sailthru/helpers_test.rb
244
247
  - test/sailthru/list_test.rb
245
248
  - test/sailthru/purchase_test.rb
249
+ - test/sailthru/rate_info_test.rb
246
250
  - test/sailthru/receive_post_callback_test.rb
247
251
  - test/sailthru/send_test.rb
248
252
  - test/sailthru/stats_test.rb