rets 0.1.1 → 0.1.2

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.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ### 0.1.2 / 2012-02-17
2
+
3
+ * bugfix - check ReplyCode in login, retry on errors
4
+
1
5
  ### 0.1.1 / 2012-01-11
2
6
 
3
7
  * bugfix - prevent infinite loop in login
data/lib/rets.rb CHANGED
@@ -8,7 +8,7 @@ require 'net/http/persistent'
8
8
  require 'nokogiri'
9
9
 
10
10
  module Rets
11
- VERSION = '0.1.1'
11
+ VERSION = '0.1.2'
12
12
 
13
13
  AuthorizationFailure = Class.new(ArgumentError)
14
14
  InvalidRequest = Class.new(ArgumentError)
data/lib/rets/client.rb CHANGED
@@ -10,22 +10,32 @@ module Rets
10
10
  attr_writer :capabilities, :metadata
11
11
 
12
12
  def initialize(options)
13
+ @options = options
14
+ clean_setup
15
+ end
16
+
17
+ def clean_setup
18
+
13
19
  @capabilities = nil
14
20
  @cookies = nil
15
21
  @metadata = nil
22
+ @cached_metadata = nil
23
+
24
+ self.authorization = nil
25
+ self.capabilities = nil
16
26
 
17
- uri = URI.parse(options[:login_url])
27
+ uri = URI.parse(@options[:login_url])
18
28
 
19
- uri.user = options.key?(:username) ? CGI.escape(options[:username]) : nil
20
- uri.password = options.key?(:password) ? CGI.escape(options[:password]) : nil
29
+ uri.user = @options.key?(:username) ? CGI.escape(@options[:username]) : nil
30
+ uri.password = @options.key?(:password) ? CGI.escape(@options[:password]) : nil
21
31
 
22
- self.options = DEFAULT_OPTIONS.merge(options)
32
+ self.options = DEFAULT_OPTIONS.merge(@options)
23
33
  self.uri = uri
24
34
 
25
- self.logger = options[:logger] || FakeLogger.new
35
+ self.logger = @options[:logger] || FakeLogger.new
26
36
 
27
- self.session = options[:session] if options[:session]
28
- @cached_metadata = options[:metadata] || nil
37
+ self.session = @options[:session] if @options[:session]
38
+ @cached_metadata = @options[:metadata] || nil
29
39
  end
30
40
 
31
41
 
@@ -59,14 +69,29 @@ module Rets
59
69
  #
60
70
  def find(quantity, opts = {})
61
71
  case quantity
62
- when :first then find_every(opts.merge(:limit => 1)).first
63
- when :all then find_every(opts)
72
+ when :first then find_with_retries(opts.merge(:limit => 1)).first
73
+ when :all then find_with_retries(opts)
64
74
  else raise ArgumentError, "First argument must be :first or :all"
65
75
  end
66
76
  end
67
77
 
68
78
  alias search find
69
79
 
80
+ def find_with_retries(opts = {})
81
+ retries = 0
82
+ begin
83
+ find_every(opts)
84
+ rescue AuthorizationFailure, InvalidRequest => e
85
+ if retries < 3
86
+ retries += 1
87
+ self.logger.warn "Failed with message: #{e.message}"
88
+ self.logger.info "Retry #{retries}/3"
89
+ clean_setup
90
+ retry
91
+ end
92
+ end
93
+ end
94
+
70
95
  def find_every(opts = {})
71
96
  search_uri = capability_url("Search")
72
97
 
@@ -275,6 +300,7 @@ module Rets
275
300
  if Net::HTTPUnauthorized === response
276
301
  raise AuthorizationFailure, "Authorization failed, check credentials?"
277
302
  else
303
+ check_errors(response)
278
304
  self.capabilities = extract_capabilities(Nokogiri.parse(response.body))
279
305
  end
280
306
  end
@@ -285,31 +311,32 @@ module Rets
285
311
  handle_unauthorized_response(response)
286
312
 
287
313
  elsif Net::HTTPSuccess === response # 2xx
288
- begin
289
- if !response.body.empty?
290
- xml = Nokogiri::XML.parse(response.body, nil, nil, Nokogiri::XML::ParseOptions::STRICT)
314
+ check_errors(response)
315
+ else
316
+ raise UnknownResponse, "Unable to handle response #{response.class}"
317
+ end
291
318
 
292
- reply_text = xml.xpath("/RETS").attr("ReplyText").value
293
- reply_code = xml.xpath("/RETS").attr("ReplyCode").value.to_i
319
+ return response
320
+ end
294
321
 
295
- if reply_code.nonzero?
296
- raise InvalidRequest, "Got error code #{reply_code} (#{reply_text})."
297
- end
298
- end
322
+ def check_errors(response)
323
+ begin
324
+ if !response.body.empty?
325
+ xml = Nokogiri::XML.parse(response.body, nil, nil, Nokogiri::XML::ParseOptions::STRICT)
299
326
 
300
- rescue Nokogiri::XML::SyntaxError => e
301
- logger.debug "Not xml"
327
+ reply_text = xml.xpath("/RETS").attr("ReplyText").value
328
+ reply_code = xml.xpath("/RETS").attr("ReplyCode").value.to_i
302
329
 
330
+ if reply_code.nonzero?
331
+ raise InvalidRequest, "Got error code #{reply_code} (#{reply_text})."
332
+ end
303
333
  end
304
334
 
305
- else
306
- raise UnknownResponse, "Unable to handle response #{response.class}"
335
+ rescue Nokogiri::XML::SyntaxError => e
336
+ logger.debug "Not xml"
307
337
  end
308
-
309
- return response
310
338
  end
311
339
 
312
-
313
340
  def handle_cookies(response)
314
341
  if cookies?(response)
315
342
  self.cookies = response.get_fields('set-cookie')
data/test/test_client.rb CHANGED
@@ -116,6 +116,18 @@ class TestClient < Test::Unit::TestCase
116
116
  end
117
117
  end
118
118
 
119
+ def test_handle_unauthorize_response_handles_rets_errors
120
+ response = Net::HTTPSuccess.new("", "", "")
121
+ response.stubs(:body => RETS_ERROR)
122
+ @client.stubs(:build_auth)
123
+ @client.stubs(:extract_digest_header)
124
+ @client.stubs(:raw_request).returns(response)
125
+
126
+ assert_raise Rets::InvalidRequest do
127
+ @client.handle_unauthorized_response(response)
128
+ end
129
+ end
130
+
119
131
  def test_handle_response_handles_rets_valid_response
120
132
  response = Net::HTTPSuccess.new("", "", "")
121
133
  response.stubs(:body => RETS_REPLY)
@@ -420,6 +432,11 @@ DIGEST
420
432
  end
421
433
  end
422
434
 
435
+ def test_find_retries_on_errors
436
+ @client.stubs(:find_every).raises(Rets::AuthorizationFailure).then.raises(Rets::InvalidRequest).then.returns([])
437
+ @client.find(:all, :foo => :bar)
438
+ end
439
+
423
440
  def test_find_provides_default_values
424
441
  @client.expects(:build_key_values).
425
442
  with("QueryType" => "DMQL2", "Format" => "COMPACT", "Query" => "x", "Foo" => "bar").
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rets
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Estately, Inc. Open Source
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2012-01-11 00:00:00 Z
19
+ date: 2012-02-17 00:00:00 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: net-http-persistent
@@ -88,11 +88,11 @@ dependencies:
88
88
  requirements:
89
89
  - - ~>
90
90
  - !ruby/object:Gem::Version
91
- hash: 27
91
+ hash: 25
92
92
  segments:
93
93
  - 2
94
- - 12
95
- version: "2.12"
94
+ - 13
95
+ version: "2.13"
96
96
  type: :development
97
97
  version_requirements: *id005
98
98
  description: |-
@@ -163,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
163
163
  requirements: []
164
164
 
165
165
  rubyforge_project: rets
166
- rubygems_version: 1.8.10
166
+ rubygems_version: 1.8.15
167
167
  signing_key:
168
168
  specification_version: 3
169
169
  summary: A pure-ruby library for fetching data from [RETS] servers