rets 0.3.0.rc.1 → 0.3.0.rc.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 +4 -0
- data/Rakefile +1 -0
- data/lib/rets/client.rb +48 -46
- data/test/test_client.rb +4 -51
- metadata +16 -16
data/CHANGELOG.md
CHANGED
data/Rakefile
CHANGED
data/lib/rets/client.rb
CHANGED
@@ -44,7 +44,8 @@ module Rets
|
|
44
44
|
# provided in initialize. Returns the capabilities that the
|
45
45
|
# RETS server provides, per http://retsdoc.onconfluence.com/display/rets172/4.10+Capability+URL+List.
|
46
46
|
def login
|
47
|
-
request(uri.path)
|
47
|
+
response = request(uri.path)
|
48
|
+
self.capabilities = extract_capabilities(Nokogiri.parse(response.body))
|
48
49
|
raise UnknownResponse, "Cannot read rets server capabilities." unless @capabilities
|
49
50
|
@capabilities
|
50
51
|
end
|
@@ -94,7 +95,7 @@ module Rets
|
|
94
95
|
end
|
95
96
|
end
|
96
97
|
end
|
97
|
-
|
98
|
+
|
98
99
|
def find_every(opts = {})
|
99
100
|
search_uri = capability_url("Search")
|
100
101
|
|
@@ -235,9 +236,12 @@ module Rets
|
|
235
236
|
def metadata
|
236
237
|
return @metadata if @metadata
|
237
238
|
|
238
|
-
if @cached_metadata && @
|
239
|
+
if @cached_metadata && (@options[:skip_metadata_uptodate_check] ||
|
240
|
+
@cached_metadata.current?(capabilities["MetadataTimestamp"], capabilities["MetadataVersion"]))
|
241
|
+
logger.info "Use cached metadata"
|
239
242
|
self.metadata = @cached_metadata
|
240
243
|
else
|
244
|
+
logger.info @cached_metadata ? "Cached metadata out of date" : "Cached metadata unavailable"
|
241
245
|
metadata_fetcher = lambda { |type| retrieve_metadata_type(type) }
|
242
246
|
self.metadata = Metadata::Root.new(&metadata_fetcher)
|
243
247
|
end
|
@@ -263,15 +267,18 @@ module Rets
|
|
263
267
|
end
|
264
268
|
|
265
269
|
def raw_request(path, body = nil, extra_headers = {}, &reader)
|
266
|
-
logger.info "posting to #{path}"
|
267
270
|
headers = build_headers.merge(extra_headers)
|
268
271
|
|
269
272
|
post = Net::HTTP::Post.new(path, headers)
|
270
273
|
post.body = body.to_s
|
271
274
|
|
272
|
-
logger.debug
|
273
|
-
|
274
|
-
|
275
|
+
logger.debug <<EOF
|
276
|
+
>>>> Request
|
277
|
+
POST #{path}
|
278
|
+
#{format_headers(headers)}
|
279
|
+
|
280
|
+
#{binary?(body.to_s) ? '<<< BINARY BODY >>>' : body.to_s}
|
281
|
+
EOF
|
275
282
|
|
276
283
|
connection_args = [Net::HTTP::Persistent === connection ? uri : nil, post].compact
|
277
284
|
|
@@ -279,27 +286,39 @@ module Rets
|
|
279
286
|
res.read_body(&reader)
|
280
287
|
end
|
281
288
|
|
282
|
-
|
289
|
+
logger.debug <<EOF
|
290
|
+
<<<< Response
|
291
|
+
#{response.code} #{response.message}
|
292
|
+
#{format_headers(response.to_hash)}
|
283
293
|
|
284
|
-
|
285
|
-
|
286
|
-
logger.debug format_headers(response.to_hash)
|
287
|
-
logger.debug ""
|
288
|
-
logger.debug "Body:"
|
289
|
-
logger.debug response.body
|
294
|
+
#{binary?(response.body.to_s) ? '<<< BINARY BODY >>>' : response.body.to_s}
|
295
|
+
EOF
|
290
296
|
|
297
|
+
handle_cookies(response)
|
291
298
|
return response
|
292
299
|
end
|
293
300
|
|
294
|
-
def
|
295
|
-
response =
|
301
|
+
def digest_auth_request(path, body = nil, extra_headers = {}, &reader)
|
302
|
+
response = raw_request(path, body, extra_headers, &reader)
|
296
303
|
if Net::HTTPUnauthorized === response
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
304
|
+
challenge = extract_digest_header(response)
|
305
|
+
if challenge
|
306
|
+
uri2 = URI.parse(uri.to_s)
|
307
|
+
uri2.user = uri.user
|
308
|
+
uri2.password = uri.password
|
309
|
+
uri2.path = path
|
310
|
+
self.authorization = build_auth(challenge, uri2, tries)
|
311
|
+
response = raw_request(path, body, extra_headers, &reader)
|
312
|
+
if Net::HTTPUnauthorized === response
|
313
|
+
raise AuthorizationFailure, "Authorization failed, check credentials?"
|
314
|
+
end
|
315
|
+
end
|
302
316
|
end
|
317
|
+
response
|
318
|
+
end
|
319
|
+
|
320
|
+
def request(*args, &block)
|
321
|
+
handle_response(digest_auth_request(*args, &block))
|
303
322
|
end
|
304
323
|
|
305
324
|
def request_with_compact_response(path, body, headers)
|
@@ -310,38 +329,20 @@ module Rets
|
|
310
329
|
|
311
330
|
def extract_digest_header(response)
|
312
331
|
authenticate_headers = response.get_fields("www-authenticate")
|
313
|
-
authenticate_headers
|
314
|
-
|
315
|
-
|
316
|
-
def handle_unauthorized_response(response)
|
317
|
-
if self.authorization.nil?
|
318
|
-
self.authorization = build_auth(extract_digest_header(response), uri, tries)
|
319
|
-
response = raw_request(uri.path)
|
320
|
-
|
321
|
-
if Net::HTTPUnauthorized === response
|
322
|
-
raise AuthorizationFailure, "Authorization failed, check credentials?"
|
323
|
-
else
|
324
|
-
ErrorChecker.check(response)
|
325
|
-
self.capabilities = extract_capabilities(Nokogiri.parse(response.body))
|
326
|
-
end
|
332
|
+
if authenticate_headers
|
333
|
+
authenticate_headers.detect {|h| h =~ /Digest/}
|
327
334
|
else
|
328
|
-
|
329
|
-
login
|
335
|
+
nil
|
330
336
|
end
|
331
337
|
end
|
332
338
|
|
333
339
|
def handle_response(response)
|
334
|
-
|
335
|
-
if Net::HTTPUnauthorized === response # 401
|
336
|
-
handle_unauthorized_response(response)
|
337
|
-
|
338
|
-
elsif Net::HTTPSuccess === response # 2xx
|
340
|
+
if Net::HTTPSuccess === response
|
339
341
|
ErrorChecker.check(response)
|
340
342
|
else
|
341
343
|
raise UnknownResponse, "Unable to handle response #{response.class}"
|
342
344
|
end
|
343
|
-
|
344
|
-
return response
|
345
|
+
response
|
345
346
|
end
|
346
347
|
|
347
348
|
def handle_cookies(response)
|
@@ -379,7 +380,6 @@ module Rets
|
|
379
380
|
@cookies[name]
|
380
381
|
end
|
381
382
|
|
382
|
-
|
383
383
|
def session=(session)
|
384
384
|
self.authorization = session.authorization
|
385
385
|
self.capabilities = session.capabilities
|
@@ -478,7 +478,9 @@ module Rets
|
|
478
478
|
data.map{|k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join("&")
|
479
479
|
end
|
480
480
|
|
481
|
-
|
481
|
+
def binary?(data)
|
482
|
+
data.slice(0, 1024).any? {|b| b >= "\x0" && b < " " && b != '-' && b != '~' && b != "\t" && b != "\r" && b != "\n"}
|
483
|
+
end
|
482
484
|
|
483
485
|
def tries
|
484
486
|
@tries ||= 1
|
data/test/test_client.rb
CHANGED
@@ -98,15 +98,6 @@ class TestClient < Test::Unit::TestCase
|
|
98
98
|
client.request("/foo")
|
99
99
|
end
|
100
100
|
|
101
|
-
|
102
|
-
def test_handle_response_instigates_login_process
|
103
|
-
response = Net::HTTPUnauthorized.new("","","")
|
104
|
-
|
105
|
-
@client.expects(:handle_unauthorized_response)
|
106
|
-
|
107
|
-
assert_equal response, @client.handle_response(response)
|
108
|
-
end
|
109
|
-
|
110
101
|
def test_handle_response_handles_rets_errors
|
111
102
|
response = Net::HTTPSuccess.new("", "", "")
|
112
103
|
response.stubs(:body => RETS_ERROR)
|
@@ -116,18 +107,6 @@ class TestClient < Test::Unit::TestCase
|
|
116
107
|
end
|
117
108
|
end
|
118
109
|
|
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
|
-
|
131
110
|
def test_handle_response_handles_rets_valid_response
|
132
111
|
response = Net::HTTPSuccess.new("", "", "")
|
133
112
|
response.stubs(:body => RETS_REPLY)
|
@@ -157,35 +136,6 @@ class TestClient < Test::Unit::TestCase
|
|
157
136
|
end
|
158
137
|
end
|
159
138
|
|
160
|
-
|
161
|
-
def test_handle_unauthorized_response_sets_capabilities_on_success
|
162
|
-
response = Net::HTTPSuccess.new("","","")
|
163
|
-
response.stubs(:body => CAPABILITIES, :get_fields => ["xxx"])
|
164
|
-
|
165
|
-
@client.stubs(:build_auth)
|
166
|
-
@client.expects(:raw_request).with("/login").returns(response)
|
167
|
-
|
168
|
-
@client.handle_unauthorized_response(response)
|
169
|
-
|
170
|
-
capabilities = {"abc" => "123", "def" => "ghi=jk"}
|
171
|
-
|
172
|
-
assert_equal capabilities, @client.capabilities
|
173
|
-
end
|
174
|
-
|
175
|
-
def test_handle_unauthorized_response_raises_on_auth_failure
|
176
|
-
response = Net::HTTPUnauthorized.new("","","")
|
177
|
-
response.stubs(:body => "", :get_fields => ["xxx"])
|
178
|
-
|
179
|
-
@client.stubs(:build_auth)
|
180
|
-
@client.expects(:raw_request).with("/login").returns(response)
|
181
|
-
|
182
|
-
assert_raise Rets::AuthorizationFailure do
|
183
|
-
@client.handle_unauthorized_response(response)
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
|
188
|
-
|
189
139
|
def test_extract_capabilities
|
190
140
|
assert_equal(
|
191
141
|
{"abc" => "123", "def" => "ghi=jk"},
|
@@ -220,7 +170,10 @@ class TestClient < Test::Unit::TestCase
|
|
220
170
|
end
|
221
171
|
|
222
172
|
def test_login_fails_if_cannot_read_capabilities
|
223
|
-
|
173
|
+
response = Net::HTTPSuccess.new("", "", "")
|
174
|
+
response.stubs(:body => RETS_REPLY)
|
175
|
+
@client.stubs(:request).returns(response)
|
176
|
+
@client.stubs(:extract_capabilities)
|
224
177
|
assert_raise Rets::UnknownResponse do
|
225
178
|
@client.login
|
226
179
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.0.rc.
|
4
|
+
version: 0.3.0.rc.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: net-http-persistent
|
16
|
-
requirement: &
|
16
|
+
requirement: &70154418461060 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '1.7'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70154418461060
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: nokogiri
|
27
|
-
requirement: &
|
27
|
+
requirement: &70154418460640 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.5.2
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70154418460640
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: mocha
|
38
|
-
requirement: &
|
38
|
+
requirement: &70154418460220 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 0.11.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70154418460220
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: vcr
|
49
|
-
requirement: &
|
49
|
+
requirement: &70154418459800 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 2.2.2
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70154418459800
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: webmock
|
60
|
-
requirement: &
|
60
|
+
requirement: &70154418459380 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.8.0
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70154418459380
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rdoc
|
71
|
-
requirement: &
|
71
|
+
requirement: &70154418458960 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '3.10'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70154418458960
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: hoe
|
82
|
-
requirement: &
|
82
|
+
requirement: &70154418458540 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ~>
|
@@ -87,7 +87,7 @@ dependencies:
|
|
87
87
|
version: '2.13'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70154418458540
|
91
91
|
description: ! '[](http://travis-ci.org/estately/rets)
|
92
92
|
|
93
93
|
A pure-ruby library for fetching data from [RETS] servers.
|