sailthru-client 1.01 → 1.02

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README.md +2 -2
  2. data/lib/sailthru.rb +401 -346
  3. metadata +18 -4
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
1
  # A simple client library to remotely access the Sailthru REST API.
2
2
 
3
- ## Installing (Tested with Ruby 1.8.7)
4
- $ gem install sailthru
3
+ ## Installing from rubygems.org (Tested with Ruby 1.8.7)
4
+ $ gem install sailthru-client
data/lib/sailthru.rb CHANGED
@@ -1,38 +1,3 @@
1
- ################################################################################
2
- #
3
- # A simple client library to remotely access the Sailthru REST API.
4
- #
5
- ################################################################################
6
- #
7
- # Copyright (c) 2007 Sailthru, Inc.
8
- # All rights reserved.
9
- #
10
- # Special thanks to the iminlikewithyou.com team for the development
11
- # of this library.
12
- #
13
- # Redistribution and use in source and binary forms, with or without
14
- # modification, are permitted provided that the following conditions
15
- # are met:
16
- #
17
- # 1. Redistributions of source code must retain the above copyright
18
- # notice, this list of conditions and the following disclaimer.
19
- # 2. Redistributions in binary form must reproduce the above copyright
20
- # notice, this list of conditions and the following disclaimer in the
21
- # documentation and/or other materials provided with the distribution.
22
- #
23
- # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24
- # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25
- # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26
- # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27
- # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28
- # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
- # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30
- # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
- # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32
- # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
- #
34
- ################################################################################
35
-
36
1
  require 'net/http'
37
2
  require 'uri'
38
3
  require 'cgi'
@@ -40,335 +5,425 @@ require 'rubygems'
40
5
  require 'json'
41
6
  require 'md5'
42
7
 
43
- class SailthruClientException < Exception
44
- end
45
-
46
- class SailthruClient
47
- attr_accessor :api_uri, :api_key, :secret, :version, :last_request
48
-
49
- VERSION = '1.01'
50
-
51
- # params:
52
- # api_key, String
53
- # secret, String
54
- # api_uri, String
55
- #
56
- # Instantiate a new client; constructor optionally takes overrides for key/secret/uri.
57
- def initialize(api_key, secret, api_uri)
58
- @api_key = api_key
59
- @secret = secret
60
- @api_uri = api_uri
8
+ module Sailthru
9
+
10
+ Version = VERSION = '1.02'
11
+
12
+ class SailthruClientException < Exception
61
13
  end
62
-
63
- # params:
64
- # template_name, String
65
- # email, String
66
- # replacements, Hash
67
- # options, Hash
68
- # replyto: override Reply-To header
69
- # test: send as test email (subject line will be marked, will not count towards stats)
70
- # returns:
71
- # Hash, response data from server
72
- def send(template_name, email, vars, options = {}, schedule_time = nil)
73
- post = {}
74
- post[:template] = template_name
75
- post[:email] = email
76
- post[:vars] = vars
77
- post[:options] = options
78
- if schedule_time != nil
79
- post[:schedule_time] = schedule_time
14
+
15
+ module Helpers
16
+ # params:
17
+ # params, Hash
18
+ # returns:
19
+ # Array, values of each item in the Hash (and nested hashes)
20
+ #
21
+ # Extracts the values of a set of parameters, recursing into nested assoc arrays.
22
+ def extract_param_values(params)
23
+ values = []
24
+ params.each do |k, v|
25
+ if v.class == Hash
26
+ values.concat extract_param_values(v)
27
+ elsif v.class == Array
28
+ temp_hash = Hash.new()
29
+ v.each_with_index do |v_,i_|
30
+ temp_hash[i_.to_s] = v_
31
+ end
32
+ values.concat extract_param_values(temp_hash)
33
+ else
34
+ values.push v.to_s
35
+ end
36
+ end
37
+ return values
80
38
  end
81
- return self.api_post(:send, post)
82
- end
83
39
 
84
-
85
- # params:
86
- # send_id, Fixnum
87
- # returns:
88
- # Hash, response data from server
89
- #
90
- # Get the status of a send.
91
- def get_send(send_id)
92
- self.api_get(:send, {:send_id => send_id.to_s})
93
- end
94
-
95
- # params:
96
- # name, String
97
- # list, String
98
- # schedule_time, String
99
- # from_name, String
100
- # from_email, String
101
- # subject, String
102
- # content_html, String
103
- # content_text, String
104
- # options, Hash
105
- # returns:
106
- # Hash, response data from server
107
- #
108
- # Schedule a mass mail blast
109
- def schedule_blast(name, list, schedule_time, from_name, from_email, subject, content_html, content_text, options)
110
- post = options ? options : {}
111
- post[:name] = name
112
- post[:list] = list
113
- post[:schedule_time] = schedule_time
114
- post[:from_name] = from_name
115
- post[:from_email] = from_email
116
- post[:subject] = subject
117
- post[:content_html] = content_html
118
- post[:content_text] = content_text
119
- self.api_post(:blast, post)
120
- end
121
-
122
-
123
- # params:
124
- # blast_id, Fixnum
125
- # returns:
126
- # Hash, response data from server
127
- #
128
- # Get information on a previously scheduled email blast
129
- def get_blast(blast_id)
130
- self.api_get(:blast, {:blast_id => blast_id.to_s})
131
- end
132
-
133
- # params:
134
- # email, String
135
- # returns:
136
- # Hash, response data from server
137
- #
138
- # Return information about an email address, including replacement vars and lists.
139
- def get_email(email)
140
- self.api_get(:email, {:email => email})
141
- end
142
-
143
- # params:
144
- # email, String
145
- # vars, Hash
146
- # lists, Hash mapping list name => 1 for subscribed, 0 for unsubscribed
147
- # returns:
148
- # Hash, response data from server
149
- #
150
- # Set replacement vars and/or list subscriptions for an email address.
151
- def set_email(email, vars = {}, lists = {}, templates = {})
152
- data = {:email => email}
153
- data[:vars] = vars unless vars.empty?
154
- data[:lists] = lists unless lists.empty?
155
- data[:templates] = templates unless templates.empty?
156
- self.api_post(:email, data)
157
- end
158
-
159
- # params:
160
- # email, String
161
- # password, String
162
- # with_names, Boolean
163
- # returns:
164
- # Hash, response data from server
165
- #
166
- # Fetch email contacts from an address book at one of the major email providers (aol/gmail/hotmail/yahoo)
167
- # Use the with_names parameter if you want to fetch the contact names as well as emails
168
- def import_contacts(email, password, with_names = false)
169
- data = { :email => email, :password => password }
170
- data[:names] = 1 if with_names
171
- self.api_post(:contacts, data)
172
- end
173
-
174
-
175
- # params:
176
- # template_name, String
177
- # returns:
178
- # Hash of response data.
179
- #
180
- # Get a template.
181
- def get_template(template_name)
182
- self.api_get(:template, {:template => template_name})
183
- end
184
-
185
-
186
- # params:
187
- # template_name, String
188
- # template_fields, Hash
189
- # returns:
190
- # Hash containg response from the server.
191
- #
192
- # Save a template.
193
- def save_template(template_name, template_fields)
194
- data = template_fields
195
- data[:template] = template_name
196
- self.api_post(:template, data)
197
- end
198
-
199
-
200
- # params:
201
- # params, Hash
202
- # request, String
203
- # returns:
204
- # TrueClass or FalseClass, Returns true if the incoming request is an authenticated verify post.
205
- def receive_verify_post(params, request)
206
- if request.post?
207
- [:action, :email, :send_id, :sig].each { |key| return false unless params.has_key?(key) }
208
-
209
- return false unless params[:action] == :verify
210
-
211
- sig = params[:sig]
212
- params.delete(:sig)
213
- return false unless sig == SailthruClient.get_signature_hash(params, @secret)
214
-
215
- _send = self.get_send(params[:send_id])
216
- return false unless _send.has_key?(:email)
217
-
218
- return false unless _send[:email] == params[:email]
219
-
220
- return true
221
- else
40
+ # params:
41
+ # params, Hash
42
+ # secret, String
43
+ # returns:
44
+ # String
45
+ #
46
+ # Returns the unhashed signature string (secret + sorted list of param values) for an API call.
47
+ def get_signature_string(params, secret)
48
+ return secret + extract_param_values(params).sort.join("")
49
+ end
50
+
51
+
52
+ # params:
53
+ # params, Hash
54
+ # secret, String
55
+ # returns:
56
+ # String
57
+ #
58
+ # Returns an MD5 hash of the signature string for an API call.
59
+ def get_signature_hash(params, secret)
60
+ MD5.md5(get_signature_string(params, secret)).to_s # debuggin
61
+ end
62
+
63
+
64
+ # Flatten nested hash for GET / POST request.
65
+ def flatten_nested_hash(hash, brackets = true)
66
+ f = {}
67
+ hash.each do |key, value|
68
+ _key = brackets ? "[#{key}]" : key.to_s
69
+ if value.class == Hash
70
+ flatten_nested_hash(value).each do |k, v|
71
+ f["#{_key}#{k}"] = v
72
+ end
73
+ elsif value.class == Array
74
+ temp_hash = Hash.new()
75
+ value.each_with_index do |v, i|
76
+ temp_hash[i.to_s] = v
77
+ end
78
+ flatten_nested_hash(temp_hash).each do |k, v|
79
+ f["#{_key}#{k}"] = v
80
+ end
81
+
82
+ else
83
+ f[_key] = value
84
+ end
85
+ end
86
+ return f
87
+ end
88
+
89
+ def verify_purchase_items (items)
90
+ if items.class == Array and !items.empty?
91
+ required_item_fields = ['qty', 'title', 'price', 'id', 'url'].sort
92
+ items.each do |v|
93
+ keys = v.keys.sort
94
+ return false if keys != required_item_fields
95
+ end
96
+ return true
97
+ end
222
98
  return false
223
99
  end
224
100
  end
225
-
226
-
227
- # Perform API GET request
228
- def api_get(action, data)
229
- api_request(action, data, 'GET')
230
- end
231
-
232
- # Perform API POST request
233
- def api_post(action, data)
234
- api_request(action, data, 'POST')
235
- end
236
-
237
- # params:
238
- # action, String
239
- # data, Hash
240
- # request, String "GET" or "POST"
241
- # returns:
242
- # Hash
243
- #
244
- # Perform an API request, using the shared-secret auth hash.
245
- #
246
- def api_request(action, data, request_type)
247
- data[:api_key] = @api_key
248
- data[:format] ||= 'json'
249
- data[:sig] = SailthruClient.get_signature_hash(data, @secret)
250
- _result = self.http_request("#{@api_uri}/#{action}", data, request_type)
251
-
252
101
 
253
- # NOTE: don't do the unserialize here
254
- unserialized = JSON.parse(_result)
255
- return unserialized ? unserialized : _result
256
- end
257
-
258
-
259
- # params:
260
- # uri, String
261
- # data, Hash
262
- # method, String "GET" or "POST"
263
- # returns:
264
- # String, body of response
265
- def http_request(uri, data, method = 'POST')
266
- data = flatten_nested_hash(data, false)
267
- # puts data.inspect
268
- if method == 'POST'
269
- post_data = data
270
- else
271
- uri += "?" + data.map{ |key, value| "#{CGI::escape(key)}=#{CGI::escape(value)}" }.join("&")
102
+ class SailthruClient
103
+
104
+ include Helpers
105
+
106
+ # params:
107
+ # api_key, String
108
+ # secret, String
109
+ # api_uri, String
110
+ #
111
+ # Instantiate a new client; constructor optionally takes overrides for key/secret/uri.
112
+ def initialize(api_key, secret, api_uri)
113
+ @api_key = api_key
114
+ @secret = secret
115
+ @api_uri = api_uri
272
116
  end
273
- req = nil
274
- headers = {"User-Agent" => "Sailthru API Ruby Client #{VERSION}"}
275
-
276
- _uri = URI.parse(uri)
277
- if method == 'POST'
278
- req = Net::HTTP::Post.new(_uri.path, headers)
279
- req.set_form_data(data)
280
- else
281
- req = Net::HTTP::Get.new("#{_uri.path}?#{_uri.query}", headers)
117
+
118
+ # params:
119
+ # template_name, String
120
+ # email, String
121
+ # replacements, Hash
122
+ # options, Hash
123
+ # replyto: override Reply-To header
124
+ # test: send as test email (subject line will be marked, will not count towards stats)
125
+ # returns:
126
+ # Hash, response data from server
127
+ def send(template_name, email, vars={}, options = {}, schedule_time = nil)
128
+ post = {}
129
+ post[:template] = template_name
130
+ post[:email] = email
131
+ post[:options] = options
132
+
133
+ if vars.length > 0
134
+ post[:vars] = vars
135
+ end
136
+
137
+ if schedule_time != nil
138
+ post[:schedule_time] = schedule_time
139
+ end
140
+ return self.api_post(:send, post)
282
141
  end
283
-
284
- @last_request = req
285
- begin
286
- response = Net::HTTP.start(_uri.host, _uri.port) {|http|
287
- http.request(req)
288
- }
289
- rescue Exception => e
290
- raise SailthruClientException.new("Unable to open stream: #{_uri.to_s}");
142
+
143
+
144
+ def multi_send(template_name, emails, vars={}, options = {}, schedule_time = nil)
145
+ post = {}
146
+ post[:template] = template_name
147
+ post[:email] = emails
148
+ post[:options] = options
149
+
150
+ if schedule_time != nil
151
+ post[:schedule_time] = schedule_time
152
+ end
153
+
154
+ if vars.length > 0
155
+ post[:vars] = vars
156
+ end
157
+
158
+ return self.api_post(:send, post)
291
159
  end
292
-
293
- if response.body
294
- return response.body
295
- else
296
- raise SailthruClientException.new("No response received from stream: #{_uri.to_s}")
160
+
161
+
162
+ # params:
163
+ # send_id, Fixnum
164
+ # returns:
165
+ # Hash, response data from server
166
+ #
167
+ # Get the status of a send.
168
+ def get_send(send_id)
169
+ self.api_get(:send, {:send_id => send_id.to_s})
297
170
  end
171
+
298
172
 
299
- end
300
-
301
- # Flatten nested hash for GET / POST request.
302
- def flatten_nested_hash(hash, brackets = true)
303
- f = {}
304
- hash.each do |key, value|
305
- _key = brackets ? "[#{key}]" : key.to_s
306
- if value.class == Hash
307
- flatten_nested_hash(value).each do |k, v|
308
- f["#{_key}#{k}"] = v
309
- end
310
- elsif value.class == Array
311
- temp_hash = Hash.new()
312
- value.each_with_index do |v, i|
313
- temp_hash[i.to_s] = v
314
- end
315
- flatten_nested_hash(temp_hash).each do |k, v|
316
- f["#{_key}#{k}"] = v
317
- end
173
+ def cancel_send(send_id)
174
+ self.api_delete(:send, {:send_id => send_id.to_s})
175
+ end
176
+
177
+ # params:
178
+ # name, String
179
+ # list, String
180
+ # schedule_time, String
181
+ # from_name, String
182
+ # from_email, String
183
+ # subject, String
184
+ # content_html, String
185
+ # content_text, String
186
+ # options, Hash
187
+ # returns:
188
+ # Hash, response data from server
189
+ #
190
+ # Schedule a mass mail blast
191
+ def schedule_blast(name, list, schedule_time, from_name, from_email, subject, content_html, content_text, options = {})
192
+ post = options ? options : {}
193
+ post[:name] = name
194
+ post[:list] = list
195
+ post[:schedule_time] = schedule_time
196
+ post[:from_name] = from_name
197
+ post[:from_email] = from_email
198
+ post[:subject] = subject
199
+ post[:content_html] = content_html
200
+ post[:content_text] = content_text
201
+ self.api_post(:blast, post)
202
+ end
203
+
204
+
205
+ # params:
206
+ # blast_id, Fixnum
207
+ # returns:
208
+ # Hash, response data from server
209
+ #
210
+ # Get information on a previously scheduled email blast
211
+ def get_blast(blast_id)
212
+ self.api_get(:blast, {:blast_id => blast_id.to_s})
213
+ end
214
+
215
+ # params:
216
+ # email, String
217
+ # returns:
218
+ # Hash, response data from server
219
+ #
220
+ # Return information about an email address, including replacement vars and lists.
221
+ def get_email(email)
222
+ self.api_get(:email, {:email => email})
223
+ end
224
+
225
+ # params:
226
+ # email, String
227
+ # vars, Hash
228
+ # lists, Hash mapping list name => 1 for subscribed, 0 for unsubscribed
229
+ # returns:
230
+ # Hash, response data from server
231
+ #
232
+ # Set replacement vars and/or list subscriptions for an email address.
233
+ def set_email(email, vars = {}, lists = {}, templates = {})
234
+ data = {:email => email}
235
+ data[:vars] = vars unless vars.empty?
236
+ data[:lists] = lists unless lists.empty?
237
+ data[:templates] = templates unless templates.empty?
238
+ self.api_post(:email, data)
239
+ end
240
+
241
+ # params:
242
+ # email, String
243
+ # password, String
244
+ # with_names, Boolean
245
+ # returns:
246
+ # Hash, response data from server
247
+ #
248
+ # Fetch email contacts from an address book at one of the major email providers (aol/gmail/hotmail/yahoo)
249
+ # Use the with_names parameter if you want to fetch the contact names as well as emails
250
+ def import_contacts(email, password, with_names = false)
251
+ data = { :email => email, :password => password }
252
+ data[:names] = 1 if with_names
253
+ self.api_post(:contacts, data)
254
+ end
255
+
256
+
257
+ # params:
258
+ # template_name, String
259
+ # returns:
260
+ # Hash of response data.
261
+ #
262
+ # Get a template.
263
+ def get_template(template_name)
264
+ self.api_get(:template, {:template => template_name})
265
+ end
318
266
 
267
+
268
+ # params:
269
+ # template_name, String
270
+ # template_fields, Hash
271
+ # returns:
272
+ # Hash containg response from the server.
273
+ #
274
+ # Save a template.
275
+ def save_template(template_name, template_fields)
276
+ data = template_fields
277
+ data[:template] = template_name
278
+ self.api_post(:template, data)
279
+ end
280
+
281
+
282
+ # params:
283
+ # params, Hash
284
+ # request, String
285
+ # returns:
286
+ # TrueClass or FalseClass, Returns true if the incoming request is an authenticated verify post.
287
+ def receive_verify_post(params, request)
288
+ if request.post?
289
+ [:action, :email, :send_id, :sig].each { |key| return false unless params.has_key?(key) }
290
+
291
+ return false unless params[:action] == :verify
292
+
293
+ sig = params[:sig]
294
+ params.delete(:sig)
295
+ return false unless sig == get_signature_hash(params, @secret)
296
+
297
+ _send = self.get_send(params[:send_id])
298
+ return false unless _send.has_key?(:email)
299
+
300
+ return false unless _send[:email] == params[:email]
301
+
302
+ return true
319
303
  else
320
- f[_key] = value
304
+ return false
321
305
  end
322
306
  end
323
- return f
324
- end
325
307
 
326
- # params:
327
- # params, Hash
328
- # returns:
329
- # Array, values of each item in the Hash (and nested hashes)
330
- #
331
- # Extracts the values of a set of parameters, recursing into nested assoc arrays.
332
- def self.extract_param_values(params)
333
- values = []
334
- params.each do |k, v|
335
- # puts "k,v: #{k}, #{v}"
336
- if v.class == Hash
337
- values.concat SailthruClient.extract_param_values(v)
338
- elsif v.class == Array
339
- temp_hash = Hash.new()
340
- v.each_with_index do |v_,i_|
341
- temp_hash[i_.to_s] = v_
342
- end
343
- values.concat self.extract_param_values(temp_hash)
344
- else
345
- values.push v.to_s()
308
+ # params:
309
+ # email, String
310
+ # items, String
311
+ # incomplete, Integer
312
+ # message_id, String
313
+ # returns:
314
+ # hash, response from server
315
+ #
316
+ # Record that a user has made a purchase, or has added items to their purchase total.
317
+ def purchase(email, items, incomplete = nil, message_id = nil)
318
+ data = {}
319
+ data[:email] = email
320
+
321
+ if verify_purchase_items(items)
322
+ data[:items] = items
323
+ end
324
+
325
+ if incomplete != nil
326
+ data[:incomplete] = incomplete.to_i
346
327
  end
328
+
329
+ if message_id != nil
330
+ data[:message_id] = message_id
331
+ end
332
+ api_post(:purchase, data)
347
333
  end
348
- return values
349
- end
350
334
 
351
- # params:
352
- # params, Hash
353
- # secret, String
354
- # returns:
355
- # String
356
- #
357
- # Returns the unhashed signature string (secret + sorted list of param values) for an API call.
358
- def self.get_signature_string(params, secret)
359
- return secret + self.extract_param_values(params).sort.join("")
360
- end
361
-
362
-
363
- # params:
364
- # params, Hash
365
- # secret, String
366
- # returns:
367
- # String
368
- #
369
- # Returns an MD5 hash of the signature string for an API call.
370
- def self.get_signature_hash(params, secret)
371
- return MD5.md5(self.get_signature_string(params, secret)).to_s # debuggin
335
+ # params:
336
+ # stat, String
337
+ #
338
+ # returns:
339
+ # hash, response from server
340
+ # Request various stats from Sailthru.
341
+ def get_stats(stat)
342
+ api_get(:stats, {:stat => stat})
343
+ end
344
+
345
+
346
+ protected
347
+
348
+ # Perform API GET request
349
+ def api_get(action, data)
350
+ api_request(action, data, 'GET')
351
+ end
352
+
353
+ # Perform API POST request
354
+ def api_post(action, data)
355
+ api_request(action, data, 'POST')
356
+ end
357
+
358
+ #Perform API DELETE request
359
+ def api_delete(action, data)
360
+ api_request(action, data, 'DELETE')
361
+ end
362
+
363
+ # params:
364
+ # action, String
365
+ # data, Hash
366
+ # request, String "GET" or "POST"
367
+ # returns:
368
+ # Hash
369
+ #
370
+ # Perform an API request, using the shared-secret auth hash.
371
+ #
372
+ def api_request(action, data, request_type)
373
+ data[:api_key] = @api_key
374
+ data[:format] ||= 'json'
375
+ data[:sig] = get_signature_hash(data, @secret)
376
+ _result = self.http_request("#{@api_uri}/#{action}", data, request_type)
377
+
378
+
379
+ # NOTE: don't do the unserialize here
380
+ unserialized = JSON.parse(_result)
381
+ return unserialized ? unserialized : _result
382
+ end
383
+
384
+
385
+ # params:
386
+ # uri, String
387
+ # data, Hash
388
+ # method, String "GET" or "POST"
389
+ # returns:
390
+ # String, body of response
391
+ def http_request(uri, data, method = 'POST')
392
+ data = flatten_nested_hash(data, false)
393
+ if method == 'POST'
394
+ post_data = data
395
+ else
396
+ uri += "?" + data.map{ |key, value| "#{CGI::escape(key.to_s)}=#{CGI::escape(value.to_s)}" }.join("&")
397
+ end
398
+ req = nil
399
+ headers = {"User-Agent" => "Sailthru API Ruby Client #{VERSION}"}
400
+
401
+ _uri = URI.parse(uri)
402
+ if method == 'POST'
403
+ req = Net::HTTP::Post.new(_uri.path, headers)
404
+ req.set_form_data(data)
405
+ else
406
+ request_uri = "#{_uri.path}?#{_uri.query}"
407
+ if method == 'DELETE'
408
+ req = Net::HTTP::Delete.new(request_uri, headers)
409
+ else
410
+ req = Net::HTTP::Get.new(request_uri, headers)
411
+ end
412
+ end
413
+
414
+ begin
415
+ response = Net::HTTP.start(_uri.host, _uri.port) {|http|
416
+ http.request(req)
417
+ }
418
+ rescue Exception => e
419
+ raise SailthruClientException.new("Unable to open stream: #{_uri.to_s}");
420
+ end
421
+
422
+ if response.body
423
+ return response.body
424
+ else
425
+ raise SailthruClientException.new("No response received from stream: #{_uri.to_s}")
426
+ end
427
+ end
372
428
  end
373
-
374
- end
429
+ end
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sailthru-client
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 11
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
- - 1
9
- version: "1.01"
8
+ - 2
9
+ version: "1.02"
10
10
  platform: ruby
11
11
  authors:
12
12
  - Prajwal Tuladhar
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-19 00:00:00 -05:00
17
+ date: 2011-01-25 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -31,6 +31,20 @@ dependencies:
31
31
  version: "0"
32
32
  type: :runtime
33
33
  version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: fakeweb
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id002
34
48
  description:
35
49
  email: praj@sailthru.com
36
50
  executables: []