pinch 0.3.0 → 0.3.1

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.
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!