pinch 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README.rdoc +17 -0
  2. data/Rakefile +1 -0
  3. data/lib/pinch.rb +57 -19
  4. data/spec/pinch_spec.rb +24 -0
  5. metadata +29 -11
@@ -31,6 +31,23 @@ The specs currently blows up on MagLev.
31
31
 
32
32
  puts data
33
33
 
34
+ == Patch to use Pinch against Amazon S3 storage with pre-signed urls
35
+ AWS S3 storage verifies url signature against HTTP verb, therefore requiring different pre-signed urls for HEAD and GET requests. Patch extends Pinch gem to accept hash or 2 urls, allowing to fetch items stored in zip archives on S3.
36
+
37
+ require 'pinch'
38
+
39
+ require 'right_aws'
40
+
41
+ s3 = RightAws::S3Generator.new('...','...')
42
+
43
+ bucket = s3.bucket('my-bucket')
44
+
45
+ head_ticket = bucket.key('test.zip').head
46
+
47
+ get_ticket = bucket.key('test.zip').get
48
+
49
+ data=Pinch.get({:head => head_url, :get => get_url},'data.json')
50
+
34
51
  == LICENSE
35
52
 
36
53
  Copyright (c) 2011 Peter Hellberg and Edward Patel
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rake/testtask'
2
+ require 'bundler/gem_tasks'
2
3
 
3
4
  task :default => :test
4
5
 
@@ -6,63 +6,100 @@ require 'pinch_response'
6
6
  # @author Peter Hellberg
7
7
  # @author Edward Patel
8
8
  class Pinch
9
- VERSION = "0.3.0"
9
+ VERSION = "0.3.1"
10
10
 
11
- attr_reader :uri
11
+ attr_reader :get_uri, :user, :pass
12
12
 
13
13
  ##
14
14
  # Retrieve a file from inside a zip file, over the network!
15
15
  #
16
16
  # @param [String] url Full URL to the ZIP file
17
17
  # @param [String] file_name Name of the file inside the ZIP archive
18
+ # @param [String] user (Optional) Username for Basic Authentication
19
+ # @param [String] pass (Optional) Password for Basic Authentication
18
20
  # @return [String] File data, ready to be displayed/saved
19
21
  # @example
20
22
  #
21
23
  # puts Pinch.get('http://peterhellberg.github.com/pinch/test.zip', 'data.json')
22
24
  #
23
- def self.get(url, file_name, &block)
24
- new(url).get(file_name, &block)
25
+ def self.get(url, file_name, user = nil, pass = nil, &block)
26
+ new(url, user, pass).get(file_name, &block)
25
27
  end
26
28
 
27
29
  ##
28
30
  # List of files inside the zip file
29
31
  #
30
32
  # @param [String] url Full URL to the ZIP file
33
+ # @param [String] user (Optional) Username for Basic Authentication
34
+ # @param [String] pass (Optional) Password for Basic Authentication
31
35
  # @return [Array] List of all the files in the ZIP archive
32
36
  # @example
33
37
  #
34
38
  # Pinch.file_list('http://peterhellberg.github.com/pinch/test.zip').first #=> "data.json"
35
39
  #
36
- def self.file_list(url)
37
- new(url).file_list
40
+ def self.file_list(url, user = nil, pass = nil)
41
+ new(url, user, pass).file_list
38
42
  end
39
43
 
40
44
  ##
41
45
  # Retrieve the size of the ZIP file
42
46
  #
43
47
  # @param [String] url Full URL to the ZIP file
48
+ # @param [String] user (Optional) Username for Basic Authentication
49
+ # @param [String] pass (Optional) Password for Basic Authentication
44
50
  # @return [Fixnum] Size of the ZIP file
45
51
  # @example
46
52
  #
47
53
  # Pinch.content_length('http://peterhellberg.github.com/pinch/test.zip') #=> 2516612
48
54
  #
49
- def self.content_length(url)
50
- new(url).content_length
55
+ def self.content_length(url, user = nil, pass = nil)
56
+ new(url, user, pass).content_length
51
57
  end
52
58
 
53
59
  ##
54
60
  # Initializes a new Pinch object
55
61
  #
56
- # @param [String] url Full URL to the ZIP file
62
+ # @param [String or Hash] url Full URL to the ZIP file or hash with different URLs for HTTP verbs, e.g.
63
+ # {
64
+ # :head => 'my-url-signed-for-head-verb'
65
+ # :get => 'my-url-signed-for-get-verb'
66
+ # }
67
+ # @param [String] user (Optional) Username for Basic Authentication
68
+ # @param [String] pass (Optional) Password for Basic Authentication
57
69
  # @param [Fixnum] redirects (Optional) Number of redirects to follow
58
70
  # @note You might want to use Pinch.get instead.
59
71
  #
60
- def initialize(url, redirects = 5)
61
- @uri = URI.parse(url)
72
+ def initialize(url, user = nil, pass = nil, redirects = 5)
73
+ if url.respond_to? :fetch
74
+ @get_uri = URI.parse(url.fetch(:get))
75
+ @head_uri = URI.parse(url.fetch(:head))
76
+ else
77
+ @get_uri = @head_uri = URI.parse(url)
78
+ end
79
+
80
+ @user = user
81
+ @pass = pass
62
82
  @files = {}
63
83
  @redirects = redirects
64
84
  end
65
85
 
86
+ ##
87
+ # Set Username and Password for Basic Authentication
88
+ #
89
+ # @param [String] username (Optional) Username for Basic Authentication
90
+ # @param [String] password (Optional) Password for Basic Authentication
91
+ # @return [Pinch] Returns self to support chained calls
92
+ # @example
93
+ #
94
+ # puts Pinch.new('http://code.mrgossett.com/pinch_test.zip').auth('pinch_test','thisisjustatest').get('data.json')
95
+ #
96
+ def auth(username, password)
97
+ @user = username
98
+ @pass = password
99
+
100
+ return self
101
+ end
102
+
66
103
  ##
67
104
  # @note You might want to use Pinch.file_list instead.
68
105
  #
@@ -86,9 +123,9 @@ class Pinch
86
123
  #
87
124
  def content_length
88
125
  @content_length ||= begin
89
- response = connection(@uri).start { |http|
90
- http.head(@uri.path)
91
- }
126
+ request = Net::HTTP::Head.new(@head_uri.request_uri)
127
+ request.basic_auth(@user, @pass) unless @user.nil? || @pass.nil?
128
+ response = connection(@head_uri).request(request)
92
129
 
93
130
  # Raise exception if the response code isn’t in the 2xx range
94
131
  response.error! unless response.kind_of?(Net::HTTPSuccess)
@@ -96,17 +133,17 @@ class Pinch
96
133
  # Raise exception if the server doesn’t support the Range header
97
134
  unless (response['Accept-Ranges'] or "").include?('bytes')
98
135
  raise RangeHeaderException,
99
- "Range HTTP header not supported on #{@uri.host}"
136
+ "Range HTTP header not supported on #{@head_uri.host}"
100
137
  end
101
138
 
102
139
  response['Content-Length'].to_i
103
140
  rescue Net::HTTPRetriableError => e
104
- @uri = URI.parse(e.response['Location'])
141
+ @head_uri = URI.parse(e.response['Location'])
105
142
 
106
143
  if (@redirects -= 1) > 0
107
144
  retry
108
145
  else
109
- raise TooManyRedirects, "Gave up at on #{@uri.host}"
146
+ raise TooManyRedirects, "Gave up at on #{@head_uri.host}"
110
147
  end
111
148
  end
112
149
  end
@@ -246,9 +283,10 @@ private
246
283
  ##
247
284
  # Get range of data from URL
248
285
  def fetch_data(offset_start, offset_end, &block)
249
- request = Net::HTTP::Get.new(@uri.request_uri)
286
+ request = Net::HTTP::Get.new(@get_uri.request_uri)
287
+ request.basic_auth(@user, @pass) unless @user.nil? || @pass.nil?
250
288
  request.set_range(offset_start..offset_end)
251
- connection(@uri).request(request, &block)
289
+ connection(@get_uri).request(request, &block)
252
290
  end
253
291
 
254
292
  ##
@@ -111,6 +111,30 @@ describe Pinch do
111
111
  end
112
112
  end
113
113
  end
114
+
115
+ describe "when calling get on the example ZIP file behind HTTP Basic Authentication" do
116
+ before do
117
+ @url = 'http://code.mrgossett.com/pinch_test.zip'
118
+ @file = 'data.json'
119
+ @data = "{\"gem\":\"pinch\",\"authors\":[\"Peter Hellberg\",\"Edward Patel\"],\"github_url\":\"https://github.com/peterhellberg/pinch\"}\n"
120
+ end
121
+
122
+ it "should retrieve the contents of the file data.json with valid authentication" do
123
+ VCR.use_cassette('valid_basic_auth') do
124
+ data = Pinch.get @url, @file, 'pinch_test', 'thisisjustatest'
125
+ data.must_equal @data
126
+ data.size.must_equal 114
127
+ end
128
+ end
129
+
130
+ it "should not retrieve the contents of the file data.json with invalid authentication" do
131
+ VCR.use_cassette('invalid_basic_auth') do
132
+ lambda {
133
+ Pinch.get @url, @file, 'invalid_username', 'invalid_password'
134
+ }.must_raise Net::HTTPServerException
135
+ end
136
+ end
137
+ end
114
138
 
115
139
  describe "Pinch.file_list" do
116
140
  it "should return a list with all the file names in the ZIP file" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pinch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,22 +10,27 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-05-27 00:00:00.000000000 Z
13
+ date: 2012-10-26 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: minitest
17
- requirement: &70160741137260 !ruby/object:Gem::Requirement
17
+ requirement: !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
21
21
  - !ruby/object:Gem::Version
22
- version: '2.12'
22
+ version: '4.0'
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: *70160741137260
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: '4.0'
26
31
  - !ruby/object:Gem::Dependency
27
32
  name: fakeweb
28
- requirement: &70160741136600 !ruby/object:Gem::Requirement
33
+ requirement: !ruby/object:Gem::Requirement
29
34
  none: false
30
35
  requirements:
31
36
  - - ~>
@@ -33,18 +38,28 @@ dependencies:
33
38
  version: '1.3'
34
39
  type: :development
35
40
  prerelease: false
36
- version_requirements: *70160741136600
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '1.3'
37
47
  - !ruby/object:Gem::Dependency
38
48
  name: vcr
39
- requirement: &70160741136020 !ruby/object:Gem::Requirement
49
+ requirement: !ruby/object:Gem::Requirement
40
50
  none: false
41
51
  requirements:
42
52
  - - ~>
43
53
  - !ruby/object:Gem::Version
44
- version: '2.0'
54
+ version: '2.2'
45
55
  type: :development
46
56
  prerelease: false
47
- version_requirements: *70160741136020
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '2.2'
48
63
  description: Pinch makes it possible to download a specific file from within a ZIP
49
64
  file over HTTP 1.1.
50
65
  email: peter@c7.se
@@ -84,9 +99,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
99
  - - ! '>='
85
100
  - !ruby/object:Gem::Version
86
101
  version: '0'
102
+ segments:
103
+ - 0
104
+ hash: 752809128111839856
87
105
  requirements: []
88
106
  rubyforge_project:
89
- rubygems_version: 1.8.15
107
+ rubygems_version: 1.8.24
90
108
  signing_key:
91
109
  specification_version: 3
92
110
  summary: Retrieve a file from inside a zip file, over the network!