downspout 0.2.8 → 0.2.9

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.8
1
+ 0.2.9
@@ -48,22 +48,20 @@ module Downspout
48
48
  Utility method for validating a URL without initiating a download
49
49
  =end
50
50
  def self.viable_url?( url_string )
51
- $logger.info("downspout | supported_protocol? | URL : #{url_string} ")
52
-
53
- # remove user/password prefix if provided
54
- clean_url = self.extract_credentials_from_url!( url_string )
51
+ $logger.info("downspout | viable_url? | URL : #{url_string} ")
55
52
 
56
53
  begin
54
+ # remove user/password prefix if provided
55
+ clean_url = self.extract_credentials_from_url!( url_string )
56
+
57
57
  uri = URI.parse( clean_url )
58
58
  rescue URI::InvalidURIError
59
- $logger.warn("downspout | supported_protocol? | The format of the url is not valid : #{url_string}")
59
+ $logger.warn("downspout | viable_url? | The format of the url is not valid : #{url_string}")
60
60
  return false
61
61
  end
62
62
 
63
63
  return false unless self.supported_protocol?( uri.scheme )
64
64
 
65
- # TODO : do more in-depth checks on URL validity
66
-
67
65
  return true
68
66
  end
69
67
 
@@ -104,24 +102,28 @@ module Downspout
104
102
  end
105
103
 
106
104
  def self.extract_credentials_from_url!( some_url )
107
- the_uri = URI.parse( some_url )
108
105
 
109
- if the_uri.userinfo.nil? then
110
- return some_url
106
+ begin
107
+ some_uri = URI::parse( some_url )
108
+ rescue NoMethodError => e
109
+ # convert to Invalid URI as that's the more pertinent issue
110
+ raise URI::InvalidURIError, e.to_s
111
111
  end
112
112
 
113
- begin
114
- Downspout::Config.add_credential( :scheme => the_uri.scheme,
115
- :host => the_uri.host,
116
- :user_name => the_uri.user,
117
- :pass_word => the_uri.password
118
- )
119
- ensure
120
- the_uri.user = nil
121
- the_uri.password = nil
113
+ cred = Downspout::Credential.create_from_uri( some_uri )
114
+
115
+ if cred.nil? then
116
+ return some_url
122
117
  end
123
-
124
- return the_uri.to_s
118
+
119
+ Downspout::Config.add_credential( cred )
120
+
121
+ # zero out the user info
122
+ some_uri.user = nil
123
+ some_uri.password = nil
124
+
125
+ # return sanitized URL string
126
+ return some_uri.to_s
125
127
  end
126
128
 
127
129
  end
@@ -83,14 +83,21 @@ module Downspout
83
83
  end
84
84
 
85
85
  def self.add_credential( options = nil )
86
- return nil unless options && options.respond_to?(:keys)
87
- options = {:scheme => 'ftp'}.merge!( options )
86
+ return nil unless options
88
87
 
89
- c = Credential.new( options )
88
+ if (options.class == Downspout::Credential) then
89
+ c = options
90
+ else
91
+ return nil unless options.respond_to?(:keys)
92
+
93
+ options = {:scheme => 'ftp'}.merge!( options ) # defaults to FTP
90
94
 
95
+ c = Credential.new( options )
96
+ end
97
+
91
98
  $logger.debug("downspout | config | add_credential | #{c.host}, #{c.user_name}, #{c.scheme} ")
92
99
 
93
- @@credentials << c
100
+ @@credentials << c
94
101
 
95
102
  return c
96
103
  end
@@ -15,6 +15,36 @@ module Downspout
15
15
  end
16
16
  end
17
17
 
18
+ def self.create_from_url( some_url )
19
+ cred_hash = {}
20
+
21
+ begin
22
+ some_uri = URI::parse( some_url )
23
+ rescue NoMethodError => e
24
+ # convert to Invalid URI as that's the more pertinent issue
25
+ raise URI::InvalidURIError, e.to_s
26
+ end
27
+
28
+ return Credential.create_from_uri( some_uri )
29
+ end
30
+
31
+ def self.create_from_uri( some_uri )
32
+
33
+ if some_uri.userinfo.nil? then
34
+ return nil
35
+ end
36
+
37
+ cred_hash = {}
38
+ cred_hash[:scheme] = some_uri.scheme
39
+ cred_hash[:host] = some_uri.host
40
+ cred_hash[:port] = some_uri.port
41
+ cred_hash[:user_name] = some_uri.user
42
+ cred_hash[:pass_word] = some_uri.password
43
+
44
+ cred = Credential.new( cred_hash )
45
+
46
+ return cred
47
+ end
18
48
  end
19
49
 
20
50
  end
@@ -167,13 +167,23 @@ module Downspout
167
167
 
168
168
  # look up the credentials for this host
169
169
  cred = Downspout::Config.credentials.select{|c| c.scheme == 'ftp' }.select{ |c| c.host == @uri.host }.first
170
+
170
171
  if cred.nil? then
171
- $logger.warn("downspout | downloader | net_ftp_download | No credentials found for '#{@uri.host}'.")
172
- # proceed anyway - slight possibility it's an un-authorized FTP account...
172
+ $logger.warn("downspout | downloader | net_ftp_download | No established credentials found for '#{@uri.host}'.")
173
+
174
+ # attempt to extract credential from the URL
175
+ cred = Downspout::Credential.create_from_url( @url )
173
176
  else
174
177
  $logger.debug("downspout | downloader | net_ftp_download | Loaded credentials for #{cred.host} ...")
175
178
  end
176
179
 
180
+ if cred.nil? then
181
+ $logger.warn("downspout | downloader | net_ftp_download | No embedded credentials found in URL.")
182
+ # proceed anyway - slight possibility it's an un-authorized FTP account...
183
+ else
184
+ $logger.warn("downspout | downloader | net_ftp_download | Using embedded credentials found in URL with user: #{cred.user_name}.")
185
+ end
186
+
177
187
  begin
178
188
  ftp = Net::FTP.open( @uri.host ) do |ftp|
179
189
  ftp.login( cred.user_name, cred.pass_word ) unless cred.nil?
@@ -240,7 +250,12 @@ module Downspout
240
250
  raise Downspout::ExcessiveRedirects, 'HTTP redirect too deep'
241
251
  end
242
252
 
243
- u = URI.parse( url_str )
253
+ begin
254
+ u = URI.parse( url_str )
255
+ rescue NoMethodError => e
256
+ # convert to Invalid URI as that's the more pertinent issue
257
+ raise URI::InvalidURIError, e.to_s
258
+ end
244
259
 
245
260
  http = Net::HTTP.new( u.host, u.port )
246
261
 
@@ -4,51 +4,12 @@ class FocusedTest < Test::Unit::TestCase
4
4
  context "Downspout" do
5
5
  context "Focus" do
6
6
  setup do
7
- @expected_url = "https://download.github.com/rails-rails-v2.3.11-0-gb0c3d45.tar.gz"
8
- @header_str = "HTTP/1.1 302 Found
9
- Server: nginx/0.7.67
10
- Date: Mon, 18 Apr 2011 01:53:16 GMT
11
- Content-Type: text/html; charset=utf-8
12
- Connection: keep-alive
13
- Status: 302 Found
14
- Location: https://nodeload.github.com/rails/rails/tarball/v2.3.11
15
- X-Runtime: 3ms
16
- Content-Length: 121
17
- Set-Cookie: _gh_sess=BAh7BzoRbG9jYWxlX2d1ZXNzMCIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVzZWR7AA%3D%3D--719def2ab2d99283383e374327fcdbb716c45c12; path=/; expires=Fri, 01 Jan 2021 00:00:00 GMT; secure; HttpOnly
18
- Cache-Control: no-cache
19
- Strict-Transport-Security: max-age=2592000
20
-
21
- HTTP/1.1 302 Moved Temporarily
22
- Server: nginx/0.7.67
23
- Date: Mon, 18 Apr 2011 01:53:17 GMT
24
- Transfer-Encoding: chunked
25
- Connection: keep-alive
26
- Location: https://download.github.com/rails-rails-v2.3.11-0-gb0c3d45.tar.gz
27
-
28
- HTTP/1.1 200 OK
29
- Server: nginx/0.7.67
30
- Date: Mon, 18 Apr 2011 01:53:17 GMT
31
- Content-Type: application/octet-stream
32
- Content-Length: 3416081
33
- Last-Modified: Mon, 18 Apr 2011 01:45:25 GMT
34
- Connection: keep-alive
35
- Accept-Ranges: bytes"
7
+ @test_string = "foo"
36
8
  end
37
9
 
38
- should "grep last location header" do
39
- last_location = @header_str.scan(/Location\:\s?(.*)\W/).last.first
40
-
41
- assert_equal @expected_url, last_location
10
+ should "behave properly" do
11
+ assert_equal @test_string, "foo"
42
12
  end
43
-
44
- should "match last_location method" do
45
- @obj = Downspout::Downloader.new( :url => "http://bad.url/path" )
46
- last_location = @obj.send('curb_last_location', @header_str )
47
-
48
- assert_equal String, last_location.class
49
- assert_equal @expected_url, last_location
50
- end
51
-
52
13
  end
53
14
  end
54
15
  end
@@ -114,11 +114,27 @@ class DownspoutTest < Test::Unit::TestCase
114
114
  end
115
115
 
116
116
  should "be accepted with FTP protocol containing user & password" do
117
+ num = Downspout::Config.credentials.size
118
+
117
119
  assert Downspout.viable_url?( "ftp://uzer:passw0rd@host.domain.tld/resource/file.format" )
120
+
121
+ assert_equal num + 1, Downspout::Config.credentials.size
122
+
123
+ assert_equal 'host.domain.tld', Downspout::Config.credentials.last.host
118
124
  end
119
125
 
120
126
  end
121
127
  end
122
128
 
129
+ should "clean URLs with user & password via extract credentials" do
130
+ test_url = "ftp://uzer:passw0rd@host.domain.tld/resource/file.format"
131
+
132
+ new_url = Downspout.extract_credentials_from_url!( test_url )
133
+
134
+ assert !(new_url == test_url)
135
+ assert_equal URI::parse( test_url ).host, URI::parse( new_url ).host
136
+ assert_equal URI::parse( test_url ).path, URI::parse( new_url ).path
137
+ end
138
+
123
139
  end
124
140
  end
@@ -4,28 +4,75 @@ class CredentialTest < Test::Unit::TestCase
4
4
  context "Downspout" do
5
5
  context "Credential" do
6
6
 
7
- should "respond to scheme" do
8
- assert Downspout::Credential.new.respond_to?(:scheme)
7
+ context "object" do
8
+
9
+ should "respond to scheme" do
10
+ assert Downspout::Credential.new.respond_to?(:scheme)
11
+ end
12
+
13
+ should "respond to host" do
14
+ assert Downspout::Credential.new.respond_to?(:host)
15
+ end
16
+
17
+ should "respond to port" do
18
+ assert Downspout::Credential.new.respond_to?(:port)
19
+ end
20
+
21
+ should "respond to user_name" do
22
+ assert Downspout::Credential.new.respond_to?(:user_name)
23
+ end
24
+
25
+ should "respond to pass_word" do
26
+ assert Downspout::Credential.new.respond_to?(:pass_word)
27
+ end
28
+
9
29
  end
10
30
 
11
- should "respond to host" do
12
- assert Downspout::Credential.new.respond_to?(:host)
13
- end
14
-
15
- should "respond to port" do
16
- assert Downspout::Credential.new.respond_to?(:port)
17
- end
18
31
 
19
- should "respond to user_name" do
20
- assert Downspout::Credential.new.respond_to?(:user_name)
32
+ context "created from URL" do
33
+
34
+ should "return nil if no credential extractable from otherwise valid URL" do
35
+ @my_url = "ftp://ftp-test.domain.tld/path/2011-04-01_13-42-52/file.ext"
36
+
37
+ @no_cred = Downspout::Credential.create_from_url( @my_url )
38
+
39
+ assert_nil @no_cred
40
+ end
41
+
42
+ should "create credential from URL with embedded info" do
43
+ @my_url = "ftp://test-name:test-secret@ftp-test.domain.tld/path/2011-04-01_13-42-52/file.ext"
44
+
45
+ @my_cred = Downspout::Credential.create_from_url( @my_url )
46
+
47
+ assert_not_nil @my_cred
48
+
49
+ assert_equal Downspout::Credential, @my_cred.class
50
+
51
+ assert_equal 'ftp', @my_cred.scheme
52
+ assert_equal 'ftp-test.domain.tld', @my_cred.host
53
+ assert_equal 21, @my_cred.port
54
+ assert_equal 'test-name', @my_cred.user_name
55
+ assert_equal 'test-secret', @my_cred.pass_word
56
+ end
57
+
58
+ should "raise error when parsing invalid URL [partially encoded]" do
59
+ @bad_url = "ftp:%20%20test-name:test-secret@ftp-test.domain.tld/path/2011-04-01_13-42-52/file.ext"
60
+
61
+ assert_raise URI::InvalidURIError do
62
+ @bad_cred = Downspout::Credential.create_from_url( @bad_url )
63
+ end
64
+ end
65
+
66
+ should "raise error when parsing invalid URL [inserted space]" do
67
+ @bad_url = "ft p://test-name:test-secret@ftp-test.domain.tld/path/2011-04-01_13-42-52/file.ext"
68
+
69
+ assert_raise URI::InvalidURIError do
70
+ @bad_cred = Downspout::Credential.create_from_url( @bad_url )
71
+ end
72
+ end
73
+
21
74
  end
22
-
23
- should "respond to pass_word" do
24
- assert Downspout::Credential.new.respond_to?(:pass_word)
25
- end
26
-
27
75
  end
28
-
29
76
  end
30
77
 
31
78
  end
@@ -243,4 +243,51 @@ class DownloaderTest < Test::Unit::TestCase
243
243
 
244
244
  end
245
245
 
246
+ context "last location for curb redirects" do
247
+ setup do
248
+ @expected_url = "https://download.github.com/rails-rails-v2.3.11-0-gb0c3d45.tar.gz"
249
+ @header_str = "HTTP/1.1 302 Found
250
+ Server: nginx/0.7.67
251
+ Date: Mon, 18 Apr 2011 01:53:16 GMT
252
+ Content-Type: text/html; charset=utf-8
253
+ Connection: keep-alive
254
+ Status: 302 Found
255
+ Location: https://nodeload.github.com/rails/rails/tarball/v2.3.11
256
+ X-Runtime: 3ms
257
+ Content-Length: 121
258
+ Cache-Control: no-cache
259
+ Strict-Transport-Security: max-age=2592000
260
+
261
+ HTTP/1.1 302 Moved Temporarily
262
+ Server: nginx/0.7.67
263
+ Date: Mon, 18 Apr 2011 01:53:17 GMT
264
+ Transfer-Encoding: chunked
265
+ Connection: keep-alive
266
+ Location: https://download.github.com/rails-rails-v2.3.11-0-gb0c3d45.tar.gz
267
+
268
+ HTTP/1.1 200 OK
269
+ Server: nginx/0.7.67
270
+ Date: Mon, 18 Apr 2011 01:53:17 GMT
271
+ Content-Type: application/octet-stream
272
+ Content-Length: 3416081
273
+ Last-Modified: Mon, 18 Apr 2011 01:45:25 GMT
274
+ Connection: keep-alive
275
+ Accept-Ranges: bytes"
276
+ end
277
+
278
+ should "grep last location header" do
279
+ last_location = @header_str.scan(/Location\:\s?(.*)\W/).last.first
280
+
281
+ assert_equal @expected_url, last_location
282
+ end
283
+
284
+ should "match last_location method" do
285
+ @obj = Downspout::Downloader.new( :url => "http://bad.url/path" )
286
+ last_location = @obj.send('curb_last_location', @header_str )
287
+
288
+ assert_equal String, last_location.class
289
+ assert_equal @expected_url, last_location
290
+ end
291
+ end
292
+
246
293
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: downspout
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 8
10
- version: 0.2.8
9
+ - 9
10
+ version: 0.2.9
11
11
  platform: ruby
12
12
  authors:
13
13
  - Phi.Sanders
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-17 00:00:00 -04:00
18
+ date: 2011-04-27 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency