sailthru-client 4.0.7 → 4.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
  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