rets 0.8.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Manifest.txt +6 -0
- data/Rakefile +2 -1
- data/example/connect.rb +19 -0
- data/example/get-photos.rb +20 -0
- data/example/get-property.rb +16 -0
- data/lib/rets.rb +1 -1
- data/lib/rets/client.rb +3 -2
- data/lib/rets/http_client.rb +8 -8
- data/lib/rets/locking_http_client.rb +2 -2
- data/lib/rets/measuring_http_client.rb +2 -2
- data/lib/rets/parser/error_checker.rb +49 -0
- data/test/test_http_client.rb +62 -15
- metadata +28 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a9bf5e37008d7651782e347a520f24cb291931f
|
4
|
+
data.tar.gz: 22742e9f4a45db910f03358e45024ee25d8cb6e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a742d37803a7c1354bb4f8d2c087b9a20b745c984286df5c243022cbb053612cb281350f589ca259494e955b7404bfd37db18ff2812441b2a560ad33485976f0
|
7
|
+
data.tar.gz: 250667d8536d504b41fc4192d8bb124237cd48bd663d061baccca0728b6408abd2d8776cd3ccf70ba6d7458a9a56e61f83a853510be725b264940be0e0c777b9
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
@@ -3,6 +3,9 @@ Manifest.txt
|
|
3
3
|
README.md
|
4
4
|
Rakefile
|
5
5
|
bin/rets
|
6
|
+
example/connect.rb
|
7
|
+
example/get-photos.rb
|
8
|
+
example/get-property.rb
|
6
9
|
lib/rets.rb
|
7
10
|
lib/rets/client.rb
|
8
11
|
lib/rets/client_progress_reporter.rb
|
@@ -17,10 +20,13 @@ lib/rets/metadata/rets_class.rb
|
|
17
20
|
lib/rets/metadata/root.rb
|
18
21
|
lib/rets/metadata/table.rb
|
19
22
|
lib/rets/parser/compact.rb
|
23
|
+
lib/rets/parser/error_checker.rb
|
20
24
|
lib/rets/parser/multipart.rb
|
21
25
|
test/fixtures.rb
|
22
26
|
test/helper.rb
|
23
27
|
test/test_client.rb
|
28
|
+
test/test_error_checker.rb
|
29
|
+
test/test_http_client.rb
|
24
30
|
test/test_locking_http_client.rb
|
25
31
|
test/test_metadata.rb
|
26
32
|
test/test_parser_compact.rb
|
data/Rakefile
CHANGED
@@ -9,7 +9,8 @@ Hoe.plugin :gemspec
|
|
9
9
|
Hoe.spec 'rets' do
|
10
10
|
developer 'Estately, Inc. Open Source', 'opensource@estately.com'
|
11
11
|
|
12
|
-
extra_deps << [ "httpclient", "~> 2.
|
12
|
+
extra_deps << [ "httpclient", "~> 2.6.0" ]
|
13
|
+
extra_deps << [ "http-cookie", "~> 1.0.0" ]
|
13
14
|
extra_deps << [ "nokogiri", "~> 1.5" ]
|
14
15
|
|
15
16
|
extra_dev_deps << [ "mocha", "~> 0.11" ]
|
data/example/connect.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rets'
|
2
|
+
|
3
|
+
# Pass the :login_url, :username, :password and :version of RETS
|
4
|
+
client = Rets::Client.new({
|
5
|
+
login_url: 'login_url',
|
6
|
+
username: 'xxx',
|
7
|
+
password: 'xxx',
|
8
|
+
version: 'RETS/1.5'
|
9
|
+
})
|
10
|
+
|
11
|
+
begin
|
12
|
+
client.login
|
13
|
+
rescue => e
|
14
|
+
puts 'Error: ' + e.message
|
15
|
+
exit!
|
16
|
+
end
|
17
|
+
|
18
|
+
puts 'We connected! Lets log out...'
|
19
|
+
client.logout
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rets'
|
2
|
+
|
3
|
+
|
4
|
+
# Get all photos (*) for MLS ID 'mls_id'
|
5
|
+
# Pass :object_id (ie '0', '1,2', wildcard '*')
|
6
|
+
# The pass :resource (Property, Agent, MetaData, ...), :object_type (Photo, PhotoLarge), :rescource_id (ID of agent, MLS, ...)
|
7
|
+
photos = client.objects '*', {
|
8
|
+
resource: 'Property',
|
9
|
+
object_type: 'Photo',
|
10
|
+
resource_id: 'mls_id'
|
11
|
+
}
|
12
|
+
|
13
|
+
photos.each_with_index do |data, index|
|
14
|
+
File.open("property-#{index.to_s}.jpg", 'w') do |file|
|
15
|
+
file.write data.body
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
puts photos.length.to_s + ' photos saved.'
|
20
|
+
client.logout
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rets'
|
2
|
+
|
3
|
+
|
4
|
+
# Get one property
|
5
|
+
# Pass :first or :all
|
6
|
+
# Then :search_type (Property, Agent, ...), :class (Condo, Commerical, ...), :query and :limit
|
7
|
+
property = client.find :first, {
|
8
|
+
search_type: 'Property',
|
9
|
+
class: 'CLASS_NAME',
|
10
|
+
query: 'RETS_QUERY',
|
11
|
+
limit: 1
|
12
|
+
}
|
13
|
+
|
14
|
+
puts 'received property: '
|
15
|
+
puts property.inspect
|
16
|
+
client.logout
|
data/lib/rets.rb
CHANGED
data/lib/rets/client.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'http-cookie'
|
1
2
|
require 'httpclient'
|
2
3
|
require 'logger'
|
3
4
|
|
@@ -335,8 +336,8 @@ module Rets
|
|
335
336
|
hash
|
336
337
|
end
|
337
338
|
|
338
|
-
def save_cookie_store
|
339
|
-
@http_client.save_cookie_store
|
339
|
+
def save_cookie_store
|
340
|
+
@http_client.save_cookie_store
|
340
341
|
end
|
341
342
|
|
342
343
|
def http_get(url, params=nil, extra_headers={})
|
data/lib/rets/http_client.rb
CHANGED
@@ -52,13 +52,10 @@ module Rets
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
def save_cookie_store
|
55
|
+
def save_cookie_store
|
56
56
|
if options[:cookie_store]
|
57
|
-
|
58
|
-
|
59
|
-
else
|
60
|
-
@http.save_cookie_store
|
61
|
-
end
|
57
|
+
#save session cookies
|
58
|
+
@http.cookie_manager.save_cookies(true)
|
62
59
|
end
|
63
60
|
end
|
64
61
|
|
@@ -82,9 +79,12 @@ module Rets
|
|
82
79
|
end
|
83
80
|
|
84
81
|
def http_cookie(name)
|
85
|
-
http.cookies.each do |c|
|
86
|
-
|
82
|
+
@http.cookie_manager.cookies(login_url).each do |c|
|
83
|
+
if c.name.downcase == name.downcase
|
84
|
+
return c.value
|
85
|
+
end
|
87
86
|
end
|
87
|
+
|
88
88
|
nil
|
89
89
|
end
|
90
90
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Rets
|
2
|
+
module Parser
|
3
|
+
class ErrorChecker
|
4
|
+
def self.check(response)
|
5
|
+
# some RETS servers returns HTTP code 412 when session cookie expired, yet the response body
|
6
|
+
# passes XML check. We need to special case for this situation.
|
7
|
+
# This method is also called from multipart.rb where there are headers and body but no status_code
|
8
|
+
if response.respond_to?(:status_code) && response.status_code == 412
|
9
|
+
raise HttpError, "HTTP status: #{response.status_code}, body: #{response.body}"
|
10
|
+
end
|
11
|
+
|
12
|
+
# some RETS servers return success code in XML body but failure code 4xx in http status
|
13
|
+
# If xml body is present we ignore http status
|
14
|
+
|
15
|
+
if !response.body.empty?
|
16
|
+
begin
|
17
|
+
xml = Nokogiri::XML.parse(response.body, nil, nil, Nokogiri::XML::ParseOptions::STRICT)
|
18
|
+
|
19
|
+
rets_element = xml.xpath("/RETS")
|
20
|
+
unless rets_element.empty?
|
21
|
+
reply_text = (rets_element.attr("ReplyText") || rets_element.attr("replyText")).value
|
22
|
+
reply_code = (rets_element.attr("ReplyCode") || rets_element.attr("replyCode")).value.to_i
|
23
|
+
|
24
|
+
if reply_code == NoRecordsFound::ERROR_CODE
|
25
|
+
raise NoRecordsFound.new(reply_text)
|
26
|
+
elsif reply_code == NoObjectFound::ERROR_CODE
|
27
|
+
raise NoObjectFound.new(reply_text)
|
28
|
+
elsif reply_code.nonzero?
|
29
|
+
raise InvalidRequest.new(reply_code, reply_text)
|
30
|
+
else
|
31
|
+
return
|
32
|
+
end
|
33
|
+
end
|
34
|
+
rescue Nokogiri::XML::SyntaxError
|
35
|
+
#Not xml
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
if response.respond_to?(:ok?) && ! response.ok?
|
40
|
+
if response.status_code == 401
|
41
|
+
raise AuthorizationFailure.new(response.status_code, response.body)
|
42
|
+
else
|
43
|
+
raise HttpError, "HTTP status: #{response.status_code}, body: #{response.body}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/test/test_http_client.rb
CHANGED
@@ -5,7 +5,6 @@ class TestHttpClient < MiniTest::Test
|
|
5
5
|
@cm = WebAgent::CookieManager.new
|
6
6
|
|
7
7
|
@http = HTTPClient.new
|
8
|
-
@http.cookie_manager = @cm
|
9
8
|
|
10
9
|
@logger = Rets::Client::FakeLogger.new
|
11
10
|
@logger.stubs(:debug?).returns(false)
|
@@ -13,20 +12,6 @@ class TestHttpClient < MiniTest::Test
|
|
13
12
|
@http_client = Rets::HttpClient.new(@http, {}, @logger, "http://rets.rets.com/somestate/login.aspx")
|
14
13
|
end
|
15
14
|
|
16
|
-
def test_http_cookie_with_webagent_cookie
|
17
|
-
cookie1 = "RETS-Session-ID=879392834723043209; path=/; domain=rets.rets.com; expires=Wednesday, 31-Dec-2037 12:00:00 GMT"
|
18
|
-
@cm.parse(cookie1, URI.parse("http://www.rets.rets.com"))
|
19
|
-
|
20
|
-
cookie2 = "Foo=Bar; path=/; domain=rets.rets.com; expires=Wednesday, 31-Dec-2037 12:00:00 GMT"
|
21
|
-
@cm.parse(cookie2, URI.parse("http://www.rets.rets.com"))
|
22
|
-
|
23
|
-
assert_equal "879392834723043209", @http_client.http_cookie('RETS-Session-ID')
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_http_cookie_without_webagent_cookie
|
27
|
-
assert_equal nil, @http_client.http_cookie('RETS-Session-ID')
|
28
|
-
end
|
29
|
-
|
30
15
|
def test_http_get_delegates_to_client
|
31
16
|
url = 'foo@example.com'
|
32
17
|
response = stub(:response)
|
@@ -46,4 +31,66 @@ class TestHttpClient < MiniTest::Test
|
|
46
31
|
|
47
32
|
assert_equal @http_client.http_post(url, {}), response
|
48
33
|
end
|
34
|
+
|
35
|
+
class CookieManagement < MiniTest::Test
|
36
|
+
def setup
|
37
|
+
@cm = WebAgent::CookieManager.new
|
38
|
+
http = HTTPClient.new
|
39
|
+
http.cookie_manager = @cm
|
40
|
+
@client = Rets::HttpClient.new(http, {}, nil, "http://rets.rets.com/somestate/login.aspx")
|
41
|
+
end
|
42
|
+
|
43
|
+
def teardown
|
44
|
+
# Empty cookie jar
|
45
|
+
@cm.cookies = []
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_http_cookie_with_one_cookie_from_one_domain
|
49
|
+
set_cookie = "RETS-Session-ID=879392834723043209; path=/; domain=rets.rets.com; expires=Wednesday, 31-Dec-2037 12:00:00 GMT"
|
50
|
+
@cm.parse(set_cookie, URI.parse("http://www.rets.rets.com"))
|
51
|
+
assert_equal "879392834723043209", @client.http_cookie('RETS-Session-ID')
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_http_cookie_with_multiple_cookies_from_one_domain
|
55
|
+
# NOTE: Cookies are ordered alphabetically by name when retrieving
|
56
|
+
set_cookie_1 = "RETS-Session-ID=879392834723043209; path=/; domain=rets.rets.com; expires=Wednesday, 31-Dec-2037 12:00:00 GMT"
|
57
|
+
@cm.parse(set_cookie_1, URI.parse("http://www.rets.rets.com"))
|
58
|
+
|
59
|
+
set_cookie_2 = "Zoo=Bar; path=/; domain=rets.rets.com; expires=Wednesday, 31-Dec-2037 12:00:00 GMT"
|
60
|
+
@cm.parse(set_cookie_2, URI.parse("http://www.rets.rets.com"))
|
61
|
+
|
62
|
+
set_cookie_3 = "Foo=Bar; path=/; domain=rets.rets.com; expires=Wednesday, 31-Dec-2037 12:00:00 GMT"
|
63
|
+
@cm.parse(set_cookie_3, URI.parse("http://www.rets.rets.com"))
|
64
|
+
|
65
|
+
assert_equal "879392834723043209", @client.http_cookie('RETS-Session-ID')
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_http_cookie_with_no_cookies_from_domain
|
69
|
+
assert_equal nil, @client.http_cookie('RETS-Session-ID')
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_save_cookie_store
|
73
|
+
cookie_file = Tempfile.new('cookie_file').path
|
74
|
+
|
75
|
+
#setup cookie store
|
76
|
+
http_a = HTTPClient.new
|
77
|
+
http_a.set_cookie_store(cookie_file)
|
78
|
+
client_a = Rets::HttpClient.new(http_a, { cookie_store: cookie_file }, nil, "http://rets.rets.com/somestate/login.aspx")
|
79
|
+
|
80
|
+
#add cookie
|
81
|
+
cookie = "RETS-Session-ID=879392834723043209; path=/; domain=rets.rets.com; expires=Wednesday, 31-Dec-2037 12:00:00 GMT"
|
82
|
+
http_a.cookie_manager.parse(cookie, URI.parse("http://www.rets.rets.com"))
|
83
|
+
|
84
|
+
#save cookie
|
85
|
+
client_a.save_cookie_store
|
86
|
+
|
87
|
+
#create new HTTPCLient with same cookie store
|
88
|
+
http_b = HTTPClient.new
|
89
|
+
http_b.set_cookie_store(cookie_file)
|
90
|
+
client_b = Rets::HttpClient.new(http_b, { cookie_store: cookie_file }, nil, "http://rets.rets.com/somestate/login.aspx")
|
91
|
+
|
92
|
+
#check added cookie exists
|
93
|
+
assert_equal "879392834723043209", client_b.http_cookie('RETS-Session-ID')
|
94
|
+
end
|
95
|
+
end
|
49
96
|
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.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Estately, Inc. Open Source
|
@@ -16,14 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.
|
19
|
+
version: 2.6.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 2.
|
26
|
+
version: 2.6.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: http-cookie
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.0.0
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: nokogiri
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,14 +114,14 @@ dependencies:
|
|
100
114
|
requirements:
|
101
115
|
- - "~>"
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version: '3.
|
117
|
+
version: '3.13'
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
122
|
- - "~>"
|
109
123
|
- !ruby/object:Gem::Version
|
110
|
-
version: '3.
|
124
|
+
version: '3.13'
|
111
125
|
description: |-
|
112
126
|
[![Build Status](https://secure.travis-ci.org/estately/rets.png?branch=master)](http://travis-ci.org/estately/rets)
|
113
127
|
A pure-ruby library for fetching data from [RETS] servers.
|
@@ -129,6 +143,9 @@ files:
|
|
129
143
|
- README.md
|
130
144
|
- Rakefile
|
131
145
|
- bin/rets
|
146
|
+
- example/connect.rb
|
147
|
+
- example/get-photos.rb
|
148
|
+
- example/get-property.rb
|
132
149
|
- lib/rets.rb
|
133
150
|
- lib/rets/client.rb
|
134
151
|
- lib/rets/client_progress_reporter.rb
|
@@ -143,6 +160,7 @@ files:
|
|
143
160
|
- lib/rets/metadata/root.rb
|
144
161
|
- lib/rets/metadata/table.rb
|
145
162
|
- lib/rets/parser/compact.rb
|
163
|
+
- lib/rets/parser/error_checker.rb
|
146
164
|
- lib/rets/parser/multipart.rb
|
147
165
|
- test/fixtures.rb
|
148
166
|
- test/helper.rb
|
@@ -155,7 +173,8 @@ files:
|
|
155
173
|
- test/test_parser_multipart.rb
|
156
174
|
- test/vcr_cassettes/unauthorized_response.yml
|
157
175
|
homepage: http://github.com/estately/rets
|
158
|
-
licenses:
|
176
|
+
licenses:
|
177
|
+
- MIT
|
159
178
|
metadata: {}
|
160
179
|
post_install_message:
|
161
180
|
rdoc_options:
|
@@ -174,17 +193,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
174
193
|
- !ruby/object:Gem::Version
|
175
194
|
version: '0'
|
176
195
|
requirements: []
|
177
|
-
rubyforge_project:
|
178
|
-
rubygems_version: 2.2.
|
196
|
+
rubyforge_project:
|
197
|
+
rubygems_version: 2.2.3
|
179
198
|
signing_key:
|
180
199
|
specification_version: 4
|
181
200
|
summary: "[![Build Status](https://secure.travis-ci.org/estately/rets.png?branch=master)](http://travis-ci.org/estately/rets)
|
182
201
|
A pure-ruby library for fetching data from [RETS] servers"
|
183
|
-
test_files:
|
184
|
-
- test/test_client.rb
|
185
|
-
- test/test_error_checker.rb
|
186
|
-
- test/test_http_client.rb
|
187
|
-
- test/test_locking_http_client.rb
|
188
|
-
- test/test_metadata.rb
|
189
|
-
- test/test_parser_compact.rb
|
190
|
-
- test/test_parser_multipart.rb
|
202
|
+
test_files: []
|