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.
- data/README.rdoc +17 -0
- data/Rakefile +1 -0
- data/lib/pinch.rb +57 -19
- data/spec/pinch_spec.rb +24 -0
- metadata +29 -11
data/README.rdoc
CHANGED
@@ -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
data/lib/pinch.rb
CHANGED
@@ -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.
|
9
|
+
VERSION = "0.3.1"
|
10
10
|
|
11
|
-
attr_reader :
|
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
|
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
|
-
|
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
|
-
|
90
|
-
|
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 #{@
|
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
|
-
@
|
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 #{@
|
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(@
|
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(@
|
289
|
+
connection(@get_uri).request(request, &block)
|
252
290
|
end
|
253
291
|
|
254
292
|
##
|
data/spec/pinch_spec.rb
CHANGED
@@ -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.
|
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-
|
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:
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '4.0'
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements:
|
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:
|
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:
|
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:
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
40
50
|
none: false
|
41
51
|
requirements:
|
42
52
|
- - ~>
|
43
53
|
- !ruby/object:Gem::Version
|
44
|
-
version: '2.
|
54
|
+
version: '2.2'
|
45
55
|
type: :development
|
46
56
|
prerelease: false
|
47
|
-
version_requirements:
|
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.
|
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!
|