rets 0.3.0 → 0.4.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.
data/CHANGELOG.md CHANGED
@@ -1,4 +1,8 @@
1
- ### 0.3.0.rc.1
1
+ ### 0.4.0 / 2012-08-29
2
+
3
+ * fix: update authentication header to uri matches path
4
+
5
+ ### 0.3.0 / 2012-07-31
2
6
 
3
7
  * correctly handle digest authentication
4
8
 
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.3.0'
11
+ VERSION = '0.4.0'
12
12
 
13
13
  AuthorizationFailure = Class.new(ArgumentError)
14
14
  InvalidRequest = Class.new(ArgumentError)
data/lib/rets/client.rb CHANGED
@@ -1,12 +1,12 @@
1
1
  module Rets
2
- Session = Struct.new(:authorization, :capabilities, :cookies)
2
+ Session = Struct.new(:auth_digest, :capabilities, :cookies)
3
3
 
4
4
  class Client
5
5
  DEFAULT_OPTIONS = { :persistent => true }
6
6
 
7
7
  include Authentication
8
8
 
9
- attr_accessor :uri, :options, :authorization, :logger
9
+ attr_accessor :login_uri, :options, :logger, :auth_digest
10
10
  attr_writer :capabilities, :metadata
11
11
 
12
12
  def initialize(options)
@@ -16,26 +16,26 @@ module Rets
16
16
 
17
17
  def clean_setup
18
18
 
19
+ @auth_digest = nil
20
+ @cached_metadata = nil
19
21
  @capabilities = nil
22
+ @connection = nil
20
23
  @cookies = nil
21
24
  @metadata = nil
22
- @cached_metadata = nil
23
25
  @tries = nil
24
- @connection = nil
25
- self.authorization = nil
26
26
  self.capabilities = nil
27
27
 
28
- uri = URI.parse(@options[:login_url])
28
+ uri = URI.parse(@options[:login_url])
29
29
 
30
- uri.user = @options.key?(:username) ? CGI.escape(@options[:username]) : nil
31
- uri.password = @options.key?(:password) ? CGI.escape(@options[:password]) : nil
30
+ uri.user = @options.key?(:username) ? CGI.escape(@options[:username]) : nil
31
+ uri.password = @options.key?(:password) ? CGI.escape(@options[:password]) : nil
32
32
 
33
- self.options = DEFAULT_OPTIONS.merge(@options)
34
- self.uri = uri
33
+ self.options = DEFAULT_OPTIONS.merge(@options)
34
+ self.login_uri = uri
35
35
 
36
- self.logger = @options[:logger] || FakeLogger.new
36
+ self.logger = @options[:logger] || FakeLogger.new
37
37
 
38
- self.session = @options.delete(:session) if @options[:session]
38
+ self.session = @options.delete(:session) if @options[:session]
39
39
  @cached_metadata = @options[:metadata] || nil
40
40
  end
41
41
 
@@ -44,7 +44,7 @@ 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
- response = request(uri.path)
47
+ response = request(login_uri.path)
48
48
  self.capabilities = extract_capabilities(Nokogiri.parse(response.body))
49
49
  raise UnknownResponse, "Cannot read rets server capabilities." unless @capabilities
50
50
  @capabilities
@@ -267,7 +267,7 @@ module Rets
267
267
  end
268
268
 
269
269
  def raw_request(path, body = nil, extra_headers = {}, &reader)
270
- headers = build_headers.merge(extra_headers)
270
+ headers = build_headers(path).merge(extra_headers)
271
271
 
272
272
  post = Net::HTTP::Post.new(path, headers)
273
273
  post.body = body.to_s
@@ -280,7 +280,7 @@ POST #{path}
280
280
  #{binary?(body.to_s) ? '<<< BINARY BODY >>>' : body.to_s}
281
281
  EOF
282
282
 
283
- connection_args = [Net::HTTP::Persistent === connection ? uri : nil, post].compact
283
+ connection_args = [Net::HTTP::Persistent === connection ? login_uri : nil, post].compact
284
284
 
285
285
  response = connection.request(*connection_args) do |res|
286
286
  res.read_body(&reader)
@@ -301,13 +301,8 @@ EOF
301
301
  def digest_auth_request(path, body = nil, extra_headers = {}, &reader)
302
302
  response = raw_request(path, body, extra_headers, &reader)
303
303
  if Net::HTTPUnauthorized === response
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)
304
+ @auth_digest = extract_digest_header(response)
305
+ if @auth_digest
311
306
  response = raw_request(path, body, extra_headers, &reader)
312
307
  if Net::HTTPUnauthorized === response
313
308
  raise AuthorizationFailure, "Authorization failed, check credentials?"
@@ -317,6 +312,16 @@ EOF
317
312
  response
318
313
  end
319
314
 
315
+ def authorization(path)
316
+ return nil unless @auth_digest
317
+ uri2 = URI.parse(login_uri.to_s)
318
+ uri2.user = login_uri.user
319
+ uri2.password = login_uri.password
320
+ uri2.path = path
321
+ build_auth(@auth_digest, uri2, tries)
322
+ end
323
+
324
+
320
325
  def request(*args, &block)
321
326
  handle_response(digest_auth_request(*args, &block))
322
327
  end
@@ -383,13 +388,13 @@ EOF
383
388
  end
384
389
 
385
390
  def session=(session)
386
- self.authorization = session.authorization
387
- self.capabilities = session.capabilities
388
- self.cookies = session.cookies
391
+ self.auth_digest = session.auth_digest
392
+ self.capabilities = session.capabilities
393
+ self.cookies = session.cookies
389
394
  end
390
395
 
391
396
  def session
392
- Session.new(authorization, capabilities, cookies)
397
+ Session.new(auth_digest, capabilities, cookies)
393
398
  end
394
399
 
395
400
 
@@ -435,7 +440,7 @@ EOF
435
440
  def connection
436
441
  @connection ||= options[:persistent] ?
437
442
  persistent_connection :
438
- Net::HTTP.new(uri.host, uri.port)
443
+ Net::HTTP.new(login_uri.host, login_uri.port)
439
444
  end
440
445
 
441
446
  def persistent_connection
@@ -457,15 +462,16 @@ EOF
457
462
  options[:version] || "RETS/1.7.2"
458
463
  end
459
464
 
460
- def build_headers
465
+ def build_headers(path)
461
466
  headers = {
462
467
  "User-Agent" => user_agent,
463
- "Host" => "#{uri.host}:#{uri.port}",
468
+ "Host" => "#{login_uri.host}:#{login_uri.port}",
464
469
  "RETS-Version" => rets_version
465
470
  }
466
471
 
467
- headers.merge!("Authorization" => authorization) if authorization
468
- headers.merge!("Cookie" => cookies) if cookies
472
+ auth = authorization(path)
473
+ headers.merge!("Authorization" => auth) if auth
474
+ headers.merge!("Cookie" => cookies) if cookies
469
475
 
470
476
  if options[:ua_password]
471
477
  headers.merge!(
data/test/test_client.rb CHANGED
@@ -11,8 +11,8 @@ class TestClient < Test::Unit::TestCase
11
11
  :login_url => "http://example.com",
12
12
  :username => "bob@example.com")
13
13
 
14
- assert_equal CGI.escape("bob@example.com"), client.uri.user
15
- assert_nil client.uri.password
14
+ assert_equal CGI.escape("bob@example.com"), client.login_uri.user
15
+ assert_nil client.login_uri.password
16
16
  end
17
17
 
18
18
  def test_initialize_adds_escaped_password_to_uri
@@ -21,7 +21,7 @@ class TestClient < Test::Unit::TestCase
21
21
  :username => "bob",
22
22
  :password => "secret@2!")
23
23
 
24
- assert_equal CGI.escape("secret@2!"), client.uri.password
24
+ assert_equal CGI.escape("secret@2!"), client.login_uri.password
25
25
  end
26
26
 
27
27
  def test_initialize_merges_default_options
@@ -58,11 +58,11 @@ class TestClient < Test::Unit::TestCase
58
58
  post = mock()
59
59
  post.expects(:body=).with("fake body")
60
60
 
61
- headers = @client.build_headers
61
+ headers = @client.build_headers('path')
62
62
 
63
63
  Net::HTTP::Post.expects(:new).with("/foo", headers).returns(post)
64
64
 
65
- @client.connection.expects(:request).with(@client.uri, post).returns(stub_everything)
65
+ @client.connection.expects(:request).with(@client.login_uri, post).returns(stub_everything)
66
66
 
67
67
  @client.expects(:handle_cookies)
68
68
  @client.expects(:handle_response)
@@ -77,7 +77,7 @@ class TestClient < Test::Unit::TestCase
77
77
  end
78
78
 
79
79
  def test_request_passes_correct_arguments_to_persistent_connection
80
- @client.connection.expects(:request).with(@client.uri, instance_of(Net::HTTP::Post)).returns(stub_everything)
80
+ @client.connection.expects(:request).with(@client.login_uri, instance_of(Net::HTTP::Post)).returns(stub_everything)
81
81
 
82
82
  @client.stubs(:handle_cookies)
83
83
  @client.stubs(:handle_response)
@@ -213,18 +213,18 @@ class TestClient < Test::Unit::TestCase
213
213
  "User-Agent" => "Client/1.0",
214
214
  "Host" => "example.com:80",
215
215
  "RETS-Version" => "RETS/1.7.2"},
216
- @client.build_headers)
216
+ @client.build_headers('path'))
217
217
  end
218
218
 
219
219
  def test_build_headers_provides_authorization
220
- @client.authorization = "Just trust me"
220
+ @client.expects(:authorization).returns("Just trust me")
221
221
 
222
222
  assert_equal({
223
223
  "Authorization" => "Just trust me",
224
224
  "User-Agent" => "Client/1.0",
225
225
  "Host" => "example.com:80",
226
226
  "RETS-Version" => "RETS/1.7.2"},
227
- @client.build_headers)
227
+ @client.build_headers('path'))
228
228
  end
229
229
 
230
230
  def test_build_headers_provides_cookies
@@ -235,7 +235,7 @@ class TestClient < Test::Unit::TestCase
235
235
  "User-Agent" => "Client/1.0",
236
236
  "Host" => "example.com:80",
237
237
  "RETS-Version" => "RETS/1.7.2"},
238
- @client.build_headers)
238
+ @client.build_headers('path'))
239
239
  end
240
240
 
241
241
 
@@ -289,33 +289,33 @@ DIGEST
289
289
 
290
290
 
291
291
  def test_session_restores_state
292
- session = Rets::Session.new("Digest auth", {"Foo" => "/foo"}, "sessionid=123")
292
+ session = Rets::Session.new({:digest => 'true'}, {"Foo" => "/foo"}, "sessionid=123")
293
293
 
294
294
  @client.session = session
295
295
 
296
- assert_equal("Digest auth", @client.authorization)
296
+ assert_equal({:digest => 'true'}, @client.auth_digest)
297
297
  assert_equal({"Foo" => "/foo"}, @client.capabilities)
298
298
  assert_equal("sessionid=123", @client.cookies)
299
299
  end
300
300
 
301
301
  def test_session_dumps_state
302
- @client.authorization = "Digest auth"
302
+ @client.auth_digest = {:digest => 'true'}
303
303
  @client.capabilities = {"Foo" => "/foo"}
304
304
  @client.cookies = "session-id=123"
305
305
 
306
306
  session = @client.session
307
307
 
308
- assert_equal("Digest auth", session.authorization)
308
+ assert_equal({:digest => 'true'}, session.auth_digest)
309
309
  assert_equal({"Foo" => "/foo"}, session.capabilities)
310
310
  assert_equal("session-id=123", session.cookies)
311
311
  end
312
312
 
313
313
  def test_initialize_with_session_restores_state
314
- session = Rets::Session.new("Digest auth", {"Foo" => "/foo"}, "sessionid=123")
314
+ session = Rets::Session.new({:digest => true}, {"Foo" => "/foo"}, "sessionid=123")
315
315
 
316
316
  client = Rets::Client.new(:login_url => "http://example.com", :session => session)
317
317
 
318
- assert_equal("Digest auth", client.authorization)
318
+ assert_equal({:digest => true}, client.auth_digest)
319
319
  assert_equal({"Foo" => "/foo"}, client.capabilities)
320
320
  assert_equal("sessionid=123", client.cookies)
321
321
  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
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-22 00:00:00.000000000 Z
12
+ date: 2012-08-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: net-http-persistent
@@ -44,13 +44,13 @@ dependencies:
44
44
  - !ruby/object:Gem::Version
45
45
  version: 1.5.2
46
46
  - !ruby/object:Gem::Dependency
47
- name: mocha
47
+ name: rdoc
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: 0.11.0
53
+ version: '3.10'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,15 +58,15 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 0.11.0
61
+ version: '3.10'
62
62
  - !ruby/object:Gem::Dependency
63
- name: vcr
63
+ name: mocha
64
64
  requirement: !ruby/object:Gem::Requirement
65
65
  none: false
66
66
  requirements:
67
67
  - - ~>
68
68
  - !ruby/object:Gem::Version
69
- version: 2.2.2
69
+ version: 0.11.0
70
70
  type: :development
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -74,15 +74,15 @@ dependencies:
74
74
  requirements:
75
75
  - - ~>
76
76
  - !ruby/object:Gem::Version
77
- version: 2.2.2
77
+ version: 0.11.0
78
78
  - !ruby/object:Gem::Dependency
79
- name: webmock
79
+ name: vcr
80
80
  requirement: !ruby/object:Gem::Requirement
81
81
  none: false
82
82
  requirements:
83
83
  - - ~>
84
84
  - !ruby/object:Gem::Version
85
- version: 1.8.0
85
+ version: 2.2.2
86
86
  type: :development
87
87
  prerelease: false
88
88
  version_requirements: !ruby/object:Gem::Requirement
@@ -90,15 +90,15 @@ dependencies:
90
90
  requirements:
91
91
  - - ~>
92
92
  - !ruby/object:Gem::Version
93
- version: 1.8.0
93
+ version: 2.2.2
94
94
  - !ruby/object:Gem::Dependency
95
- name: rdoc
95
+ name: webmock
96
96
  requirement: !ruby/object:Gem::Requirement
97
97
  none: false
98
98
  requirements:
99
99
  - - ~>
100
100
  - !ruby/object:Gem::Version
101
- version: '3.10'
101
+ version: 1.8.0
102
102
  type: :development
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
@@ -106,7 +106,7 @@ dependencies:
106
106
  requirements:
107
107
  - - ~>
108
108
  - !ruby/object:Gem::Version
109
- version: '3.10'
109
+ version: 1.8.0
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: hoe
112
112
  requirement: !ruby/object:Gem::Requirement
@@ -114,7 +114,7 @@ dependencies:
114
114
  requirements:
115
115
  - - ~>
116
116
  - !ruby/object:Gem::Version
117
- version: '2.13'
117
+ version: '3.0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
@@ -122,7 +122,7 @@ dependencies:
122
122
  requirements:
123
123
  - - ~>
124
124
  - !ruby/object:Gem::Version
125
- version: '2.13'
125
+ version: '3.0'
126
126
  description: ! '[![Build Status](https://secure.travis-ci.org/estately/rets.png?branch=master)](http://travis-ci.org/estately/rets)
127
127
 
128
128
  A pure-ruby library for fetching data from [RETS] servers.