s33r 0.2 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/s3cli.rb +25 -16
- data/html/classes/MIME.html +120 -0
- data/html/classes/MIME/InvalidContentType.html +119 -0
- data/html/classes/MIME/Type.html +1173 -0
- data/html/classes/MIME/Types.html +566 -0
- data/html/classes/Net.html +108 -0
- data/html/classes/Net/HTTPGenericRequest.html +233 -0
- data/html/classes/Net/HTTPResponse.html +242 -0
- data/html/classes/S33r.html +743 -0
- data/html/classes/S33r/BucketListing.html +372 -0
- data/html/classes/S33r/Client.html +981 -0
- data/html/classes/S33r/NamedBucket.html +620 -0
- data/html/classes/S33r/S33rException.html +118 -0
- data/html/classes/S33r/S33rException/BucketListingMaxKeysError.html +111 -0
- data/html/classes/S33r/S33rException/InvalidBucketListing.html +111 -0
- data/html/classes/S33r/S33rException/MalformedBucketName.html +111 -0
- data/html/classes/S33r/S33rException/MethodNotAvailable.html +111 -0
- data/html/classes/S33r/S33rException/MissingRequiredHeaders.html +111 -0
- data/html/classes/S33r/S33rException/MissingResource.html +111 -0
- data/html/classes/S33r/S33rException/UnsupportedCannedACL.html +111 -0
- data/html/classes/S33r/S33rException/UnsupportedHTTPMethod.html +111 -0
- data/html/classes/S33r/S3Object.html +307 -0
- data/html/classes/S33r/S3User.html +171 -0
- data/html/classes/S33r/Sync.html +151 -0
- data/html/classes/XML.html +200 -0
- data/html/classes/XML/Document.html +125 -0
- data/html/classes/XML/Node.html +124 -0
- data/html/created.rid +1 -0
- data/html/files/CHANGELOG.html +101 -0
- data/html/files/MIT-LICENSE.html +129 -0
- data/html/files/README_txt.html +209 -0
- data/html/files/lib/s33r/bucket_listing_rb.html +116 -0
- data/html/files/lib/s33r/client_rb.html +110 -0
- data/html/files/lib/s33r/core_rb.html +113 -0
- data/html/files/lib/s33r/libxml_extensions_rb.html +107 -0
- data/html/files/lib/s33r/mimetypes_rb.html +120 -0
- data/html/files/lib/s33r/named_bucket_rb.html +101 -0
- data/html/files/lib/s33r/s33r_exception_rb.html +101 -0
- data/html/files/lib/s33r/s33r_http_rb.html +108 -0
- data/html/files/lib/s33r/sync_rb.html +101 -0
- data/html/files/lib/s33r_rb.html +101 -0
- data/html/fr_class_index.html +52 -0
- data/html/fr_file_index.html +39 -0
- data/html/fr_method_index.html +126 -0
- data/html/index.html +24 -0
- data/html/rdoc-style.css +208 -0
- data/lib/s33r/bucket_listing.rb +69 -60
- data/lib/s33r/client.rb +150 -73
- data/lib/s33r/core.rb +56 -44
- data/lib/s33r/libxml_extensions.rb +10 -5
- data/lib/s33r/mimetypes.rb +3 -2
- data/lib/s33r/named_bucket.rb +89 -24
- data/lib/s33r/{s3_exception.rb → s33r_exception.rb} +2 -2
- data/lib/s33r/{net_http_overrides.rb → s33r_http.rb} +29 -21
- data/lib/s33r/sync.rb +4 -2
- data/test/cases/spec_bucket_listing.rb +10 -13
- data/test/cases/spec_client.rb +65 -0
- data/test/cases/spec_core.rb +16 -11
- data/test/cases/spec_namedbucket.rb +32 -0
- data/test/cases/spec_sync.rb +6 -5
- data/test/cases/spec_xml.rb +1 -1
- data/test/files/client_config.yml +6 -0
- data/test/files/namedbucket_config.yml +12 -0
- data/test/{s3_test_constants.rb → test_setup.rb} +7 -6
- metadata +63 -11
- data/LICENSE.txt +0 -22
- data/MIT-LICENSE +0 -21
- data/README.txt +0 -19
- data/bin/config.yml +0 -5
- data/test/cases/unit_client.rb +0 -40
- data/test/cases/unit_named_bucket.rb +0 -12
data/lib/s33r/core.rb
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'time'
|
3
|
+
require 'net/http'
|
4
|
+
require 'net/https'
|
5
|
+
require 'openssl'
|
6
|
+
require 'xml/libxml'
|
7
|
+
|
8
|
+
# Module to handle S3 operations which don't require an internet connection,
|
9
|
+
# i.e. data validation and request-building operations;
|
10
|
+
# also holds all the constants relating to S3.
|
11
|
+
#
|
1
12
|
# Parts of this code are heavily based on Amazon's code. Here's their license:
|
2
13
|
#
|
3
14
|
# This software code is made available "AS IS" without warranties of any
|
@@ -8,35 +19,28 @@
|
|
8
19
|
# Digital Services, Inc. or its affiliates with respect to your use of
|
9
20
|
# this software code. (c) 2006 Amazon Digital Services, Inc. or its
|
10
21
|
# affiliates.
|
11
|
-
|
12
|
-
require 'base64'
|
13
|
-
require 'time'
|
14
|
-
require 'net/http'
|
15
|
-
require 'net/https'
|
16
|
-
require 'openssl'
|
17
|
-
require 'xml/libxml'
|
18
|
-
|
19
|
-
# this module handles operations which don't require an internet connection,
|
20
|
-
# i.e. data validation and request building operations;
|
21
|
-
# it also holds all the constants relating to S3
|
22
|
-
module S3
|
22
|
+
module S33r
|
23
23
|
HOST = 's3.amazonaws.com'
|
24
24
|
PORT = 443
|
25
25
|
NON_SSL_PORT = 80
|
26
26
|
METADATA_PREFIX = 'x-amz-meta-'
|
27
|
+
# Size of each chunk (in bytes) to be sent per request when putting files.
|
28
|
+
DEFAULT_CHUNK_SIZE = 1048576
|
27
29
|
AWS_HEADER_PREFIX = 'x-amz-'
|
28
30
|
AWS_AUTH_HEADER_VALUE = "AWS %s:%s"
|
29
31
|
INTERESTING_HEADERS = ['content-md5', 'content-type', 'date']
|
32
|
+
# Headers which must be included with every request to S3.
|
30
33
|
REQUIRED_HEADERS = ['Content-Type', 'Date']
|
31
34
|
CANNED_ACLS = ['private', 'public-read', 'public-read-write', 'authenticated-read']
|
35
|
+
# HTTP methods which S3 will respond to.
|
32
36
|
METHOD_VERBS = ['GET', 'PUT', 'HEAD', 'POST', 'DELETE']
|
33
|
-
#
|
37
|
+
# Maximum number which can be passed in max-keys parameter when GETting bucket list.
|
34
38
|
BUCKET_LIST_MAX_MAX_KEYS = 1000
|
35
|
-
#
|
39
|
+
# Default number of seconds an authenticated URL will last for (15 minutes).
|
36
40
|
DEFAULT_EXPIRY_SECS = 60 * 15
|
37
41
|
|
38
|
-
#
|
39
|
-
# modified (slightly) from the Amazon sample code
|
42
|
+
# Build canonical string for signing;
|
43
|
+
# modified (slightly) from the Amazon sample code.
|
40
44
|
def generate_canonical_string(method, path, headers={}, expires=nil)
|
41
45
|
interesting_headers = {}
|
42
46
|
headers.each do |key, value|
|
@@ -77,14 +81,14 @@ module S3
|
|
77
81
|
return buf
|
78
82
|
end
|
79
83
|
|
80
|
-
#
|
84
|
+
# Get the value for the AWS authentication header.
|
81
85
|
def generate_auth_header_value(method, path, headers, aws_access_key, aws_secret_access_key)
|
82
|
-
raise
|
86
|
+
raise S33rException::MethodNotAvailable, "Method %s not available" % method if !METHOD_VERBS.include?(method)
|
83
87
|
|
84
88
|
# check the headers needed for authentication have been set
|
85
89
|
missing_headers = REQUIRED_HEADERS - headers.keys
|
86
90
|
if !(missing_headers.empty?)
|
87
|
-
raise
|
91
|
+
raise S33rException::MissingRequiredHeaders,
|
88
92
|
"Headers required for AWS auth value are missing: " + missing_headers.join(', ')
|
89
93
|
end
|
90
94
|
|
@@ -94,24 +98,22 @@ module S3
|
|
94
98
|
AWS_AUTH_HEADER_VALUE % [aws_access_key, signature]
|
95
99
|
end
|
96
100
|
|
97
|
-
#
|
98
|
-
# hmac sha1 sum, and then base64 encoding it
|
101
|
+
# Encode the given string with the aws_secret_access_key, by taking the
|
102
|
+
# hmac sha1 sum, and then base64 encoding it.
|
99
103
|
def generate_signature(aws_secret_access_key, str)
|
100
104
|
digest = OpenSSL::HMAC::digest(OpenSSL::Digest::Digest.new("SHA1"), aws_secret_access_key, str)
|
101
105
|
Base64.encode64(digest).strip
|
102
106
|
end
|
103
107
|
|
104
|
-
#
|
108
|
+
# Build the headers required with every S3 request (Date and Content-Type);
|
105
109
|
# options hash can contain extra header settings, as follows:
|
106
110
|
# :date and :content_type are required headers, and set to defaults if not supplied
|
107
111
|
def add_default_headers(headers, options={})
|
108
|
-
|
109
112
|
# set the default headers required by AWS
|
110
113
|
missing_headers = REQUIRED_HEADERS - headers.keys
|
111
114
|
|
112
115
|
if missing_headers.include?('Content-Type')
|
113
|
-
|
114
|
-
headers['Content-Type'] = content_type
|
116
|
+
headers['Content-Type'] = options[:content_type] || ''
|
115
117
|
end
|
116
118
|
|
117
119
|
if missing_headers.include?('Date')
|
@@ -122,8 +124,8 @@ module S3
|
|
122
124
|
headers
|
123
125
|
end
|
124
126
|
|
125
|
-
#
|
126
|
-
#
|
127
|
+
# Add metadata headers, correctly prefixing them first.
|
128
|
+
# Returns headers with the metadata headers appended.
|
127
129
|
def metadata_headers(headers, metadata={})
|
128
130
|
unless metadata.empty?
|
129
131
|
metadata.each { |key, value| headers[METADATA_PREFIX + key] = value }
|
@@ -131,36 +133,34 @@ module S3
|
|
131
133
|
headers
|
132
134
|
end
|
133
135
|
|
134
|
-
#
|
136
|
+
# Add a canned ACL setter header.
|
135
137
|
def canned_acl_header(canned_acl, headers={})
|
136
138
|
unless canned_acl.nil?
|
137
139
|
unless CANNED_ACLS.include?(canned_acl)
|
138
|
-
raise
|
140
|
+
raise S33rException::UnsupportedCannedACL, "The canned ACL #{canned_acl} is not supported"
|
139
141
|
end
|
140
142
|
headers[AWS_HEADER_PREFIX + 'acl'] = canned_acl
|
141
143
|
end
|
142
144
|
headers
|
143
145
|
end
|
144
146
|
|
145
|
-
#
|
146
|
-
#
|
147
|
+
# Guess a file's mime type.
|
148
|
+
# If the mime_type for a file cannot be guessed, "text/plain" is used.
|
147
149
|
def guess_mime_type(file_name)
|
148
150
|
mime_type = MIME::Types.type_for(file_name)[0]
|
149
|
-
mime_type
|
151
|
+
mime_type ||= MIME::Types['text/plain'][0]
|
150
152
|
mime_type
|
151
153
|
end
|
152
154
|
|
153
|
-
#
|
155
|
+
# Ensure that a bucket_name is well-formed (no leading or trailing slash).
|
154
156
|
def bucket_name_valid?(bucket_name)
|
155
|
-
if '/' == bucket_name[0,1]
|
156
|
-
raise
|
157
|
-
elsif '/' == bucket_name[-1,1]
|
158
|
-
raise S3Exception::MalformedBucketName, "Bucket name cannot have a trailing slash"
|
157
|
+
if ('/' == bucket_name[0,1] || '/' == bucket_name[-1,1])
|
158
|
+
raise S33rException::MalformedBucketName, "Bucket name cannot have a leading or trailing slash"
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
162
|
-
#
|
163
|
-
#
|
162
|
+
# Convert a hash of name/value pairs to querystring variables.
|
163
|
+
# Name for a variable can be a string or symbol.
|
164
164
|
def generate_querystring(pairs={})
|
165
165
|
str = ''
|
166
166
|
if pairs.size > 0
|
@@ -169,7 +169,9 @@ module S3
|
|
169
169
|
str
|
170
170
|
end
|
171
171
|
|
172
|
-
#
|
172
|
+
# Build URLs from fragments.
|
173
|
+
# Does similar job to File.join but puts forward slash between arguments
|
174
|
+
# (only if it's not already there).
|
173
175
|
def url_join(*args)
|
174
176
|
url_start = ''
|
175
177
|
url_end = args.join('/')
|
@@ -185,14 +187,15 @@ module S3
|
|
185
187
|
# replace any multiple forward slashes (except those in the scheme)
|
186
188
|
url_end = url_end.gsub(/\/{2,}/, '/')
|
187
189
|
|
188
|
-
|
190
|
+
url_start + url_end
|
189
191
|
end
|
190
192
|
|
191
|
-
|
193
|
+
# The public URL for this key (which only works if public-read ACL is set).
|
194
|
+
def s3_public_url(bucket_name, resource_key)
|
192
195
|
"http://" + HOST + '/' + bucket_name + '/' + resource_key
|
193
196
|
end
|
194
197
|
|
195
|
-
#
|
198
|
+
# Generate a get-able URL for an S3 resource key which passes authentication in querystring.
|
196
199
|
# int expires: when the URL expires (seconds since the epoch)
|
197
200
|
def s3_authenticated_url(aws_access_key, aws_secret_access_key, bucket_name, resource_key,
|
198
201
|
expires)
|
@@ -204,6 +207,15 @@ module S3
|
|
204
207
|
querystring = generate_querystring({ 'Signature' => signature, 'Expires' => expires,
|
205
208
|
'AWSAccessKeyId' => aws_access_key })
|
206
209
|
|
207
|
-
return
|
210
|
+
return s3_public_url(bucket_name, resource_key) + querystring
|
211
|
+
end
|
212
|
+
|
213
|
+
# Turn keys in a hash hsh into symbols.
|
214
|
+
# Returns a hash with 'symbolised' keys.
|
215
|
+
def S33r.keys_to_symbols(hsh)
|
216
|
+
symbolised = hsh.inject({}) do |symbolised, key_value|
|
217
|
+
symbolised.merge({key_value[0].to_sym => key_value[1]})
|
218
|
+
end
|
219
|
+
symbolised
|
208
220
|
end
|
209
221
|
end
|
@@ -1,8 +1,11 @@
|
|
1
|
-
#
|
1
|
+
# Convenience methods for libxml classes.
|
2
2
|
module XML
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
3
|
+
# Find first matching element and return its content
|
4
|
+
# (intended for use as a mixed-in method for Document instances).
|
5
|
+
#
|
6
|
+
# +xpath+: XPath query to run against self.
|
7
|
+
#
|
8
|
+
# Returns nil if no element matches +xpath+.
|
6
9
|
def xget(xpath)
|
7
10
|
nodes = self.find(xpath).to_a
|
8
11
|
if nodes.empty?
|
@@ -12,17 +15,19 @@ module XML
|
|
12
15
|
end
|
13
16
|
end
|
14
17
|
|
15
|
-
#
|
18
|
+
# Parse an XML string into an XML::Document instance.
|
16
19
|
def XML.get_xml_doc(xml_str)
|
17
20
|
parser = XML::Parser.new
|
18
21
|
parser.string = xml_str
|
19
22
|
parser.parse
|
20
23
|
end
|
21
24
|
|
25
|
+
# Make custom methods accessible to Document class.
|
22
26
|
class Document
|
23
27
|
include XML
|
24
28
|
end
|
25
29
|
|
30
|
+
# Make custom methods accessible to Node class.
|
26
31
|
class Node
|
27
32
|
include XML
|
28
33
|
end
|
data/lib/s33r/mimetypes.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# TODO: clarify license
|
2
|
+
#
|
2
3
|
# MIME::Types for Ruby
|
3
4
|
# Version 1.15
|
4
5
|
#
|
@@ -7,7 +8,7 @@
|
|
7
8
|
# $Id: types.rb,v 1.4 2006/02/12 21:27:22 austin Exp $
|
8
9
|
#
|
9
10
|
# The ChangeLog contains all details on revisions.
|
10
|
-
|
11
|
+
#
|
11
12
|
|
12
13
|
# The namespace for MIME applications, tools, and libraries.
|
13
14
|
module MIME
|
data/lib/s33r/named_bucket.rb
CHANGED
@@ -1,52 +1,117 @@
|
|
1
|
-
|
1
|
+
#-- TODO: provide access to metadata on the enclosed bucket_listing
|
2
|
+
require File.join(File.dirname(__FILE__), 'client')
|
2
3
|
|
3
|
-
module
|
4
|
-
#
|
4
|
+
module S33r
|
5
|
+
# Wraps the S33r::Client class to make it more convenient for use with a single bucket.
|
5
6
|
class NamedBucket < Client
|
6
|
-
attr_accessor :bucket_name
|
7
|
+
attr_accessor :bucket_name, :strict, :public_contents, :dump_requests
|
8
|
+
|
9
|
+
# Initialize an instance from a config_file. The config. file can include a separate
|
10
|
+
# +options+ section specifying options specific to NamedBucket instances (see the initialize method
|
11
|
+
# for more details).
|
12
|
+
# Other options are as for S33r::Client.init.
|
13
|
+
def NamedBucket.init(config_file)
|
14
|
+
aws_access_key, aws_secret_access_key, options, _ = super.class.load_config(config_file)
|
15
|
+
NamedBucket.new(aws_access_key, aws_secret_access_key, options)
|
16
|
+
end
|
7
17
|
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
|
12
|
-
|
18
|
+
# Initialize a NamedBucket instance.
|
19
|
+
#
|
20
|
+
# +options+ is a hash of options for this instance:
|
21
|
+
# * <tt>:default_bucket => 'xxxx'</tt>: name of the bucket this client is attached to.
|
22
|
+
# * <tt>:public_contents => true</tt>: all items put into bucket are made public (can be overridden per request).
|
23
|
+
# * <tt>:strict => true</tt>: check whether the bucket exists before attempting to initialize; initialization \
|
24
|
+
# fails if the bucket does not exist
|
25
|
+
def initialize(aws_access_key, aws_secret_access_key, options={}, &block)
|
26
|
+
super(aws_access_key, aws_secret_access_key, options)
|
27
|
+
|
28
|
+
@bucket_name = options[:default_bucket]
|
13
29
|
|
14
30
|
# holds a BucketListing instance
|
15
31
|
@bucket_listing = nil
|
16
32
|
|
17
33
|
# all content should be created as public-read
|
18
|
-
@
|
19
|
-
|
20
|
-
super(aws_access_key, aws_secret_access_key, options)
|
34
|
+
@public_contents = (true == options[:public_contents])
|
35
|
+
@client_headers.merge!(canned_acl_header('public-read')) if @public_contents
|
21
36
|
|
22
|
-
|
23
|
-
|
37
|
+
@strict = (true == options[:strict])
|
38
|
+
if ((@strict && !bucket_exists?(@bucket_name)) || @bucket_name.nil?)
|
39
|
+
raise S33rException::MissingResource, "The specified bucket name #{@bucket_name} does not exist or is invalid"
|
24
40
|
end
|
41
|
+
|
42
|
+
yield self if block_given?
|
25
43
|
end
|
26
|
-
|
27
|
-
|
28
|
-
|
44
|
+
|
45
|
+
# Are all objects added to this bucket made public by default?
|
46
|
+
def public_contents?
|
47
|
+
@public_contents
|
29
48
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
49
|
+
|
50
|
+
# Is this a strict bucket (i.e. the target bucket must exist on S3)?
|
51
|
+
def strict?
|
52
|
+
@strict
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get a single object from a bucket as a blob.
|
56
|
+
def [](key)
|
57
|
+
get_resource(@bucket_name, key).body
|
33
58
|
end
|
34
59
|
|
60
|
+
# Get a BucketListing instance for the content of this bucket.
|
35
61
|
def listing
|
36
|
-
|
37
|
-
|
38
|
-
|
62
|
+
_, @bucket_listing = list_bucket(@bucket_name)
|
63
|
+
@bucket_listing
|
64
|
+
end
|
65
|
+
|
66
|
+
# Get a pretty list of the keys in the bucket.
|
67
|
+
def keys
|
68
|
+
listing.pretty
|
69
|
+
end
|
70
|
+
|
71
|
+
# List content of the bucket, and attach each item to this bucket as it is yielded.
|
72
|
+
def each_item
|
73
|
+
listing.contents.each_value { |item| item.named_bucket = self; yield item }
|
74
|
+
end
|
75
|
+
|
76
|
+
# Does this bucket exist?
|
77
|
+
# Returns true if the bucket this NamedBucket is mapped to exists.
|
78
|
+
def exists?
|
79
|
+
bucket_exists?(@bucket_name)
|
39
80
|
end
|
40
81
|
|
82
|
+
# Put a string into a key inside the bucket.
|
41
83
|
def put_text(string, resource_key, headers={})
|
42
84
|
super(string, @bucket_name, resource_key, headers)
|
43
85
|
end
|
44
86
|
|
87
|
+
# Put a file into the bucket.
|
45
88
|
def put_file(filename, resource_key=nil, headers={}, options={})
|
46
89
|
super(filename, @bucket_name, resource_key, headers, options)
|
47
90
|
end
|
48
91
|
|
49
|
-
#
|
92
|
+
# Put a generic resource (e.g. from a data stream) into the bucket.
|
93
|
+
def put_stream(data, resource_key, headers={})
|
94
|
+
put_resource(@bucket_name, resource_key, data, headers)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Delete the bucket.
|
98
|
+
def delete(headers={}, options={})
|
99
|
+
delete_bucket(@bucket_name, headers, options)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Delete an object from the bucket.
|
103
|
+
#
|
104
|
+
# Returns boolean (true = deletion worked OK).
|
105
|
+
def delete_key(resource_key, headers={})
|
106
|
+
response = delete_resource(@bucket_name, resource_key, headers)
|
107
|
+
listing
|
108
|
+
response.ok?
|
109
|
+
end
|
110
|
+
|
111
|
+
# Generate an authenticated URL (see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/)
|
112
|
+
# for an object inside this bucket.
|
113
|
+
#
|
114
|
+
# +expires+: time in secs since the epoch when the link should become invalid.
|
50
115
|
def s3_authenticated_url(resource_key, expires=(Time.now.to_i + DEFAULT_EXPIRY_SECS))
|
51
116
|
super(@aws_access_key, @aws_secret_access_key, @bucket_name, resource_key, expires)
|
52
117
|
end
|
@@ -1,21 +1,22 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
|
3
|
-
#
|
3
|
+
# Addtions to the Net::HTTP classes
|
4
4
|
|
5
|
-
#
|
5
|
+
# Adds some convenience functions for checking response status.
|
6
6
|
class Net::HTTPResponse
|
7
7
|
attr_accessor :success
|
8
|
+
attr_writer :body
|
8
9
|
|
9
10
|
def ok?
|
10
11
|
success
|
11
12
|
end
|
12
13
|
|
13
14
|
def success
|
14
|
-
|
15
|
+
code == '200'
|
15
16
|
end
|
16
17
|
|
17
18
|
def not_found
|
18
|
-
|
19
|
+
code = '404'
|
19
20
|
end
|
20
21
|
|
21
22
|
def to_s
|
@@ -23,13 +24,34 @@ class Net::HTTPResponse
|
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
|
-
#
|
27
|
-
# when streaming data from large files
|
27
|
+
# Modification of Net::HTTP base class to enable larger chunk sizes to be used
|
28
|
+
# when streaming data from large files.
|
29
|
+
#
|
30
|
+
# N.B. does _not_ alter the behaviour of this class unless you set chunk_size
|
31
|
+
# using the accessor.
|
28
32
|
class Net::HTTPGenericRequest
|
33
|
+
# Size of chunks (in bytes) to send when streaming body data.
|
29
34
|
attr_accessor :chunk_size
|
30
35
|
|
36
|
+
# Dump initial line and raw request headers (useful for visual debugging).
|
37
|
+
#
|
38
|
+
# Switch on request debugging by passing <tt>:dump_requests => true</tt> to S33r::Client
|
39
|
+
# constructor.
|
40
|
+
def to_s
|
41
|
+
str = "*******\n" +
|
42
|
+
"#{self.class::METHOD} #{@path} HTTP/1.1\n" +
|
43
|
+
"Host: #{S33r::HOST}\n"
|
44
|
+
|
45
|
+
self.each_capitalized do |key, value|
|
46
|
+
str += "#{key}: #{value}\n"
|
47
|
+
end
|
48
|
+
str += "*******\n\n"
|
49
|
+
str
|
50
|
+
end
|
51
|
+
|
31
52
|
private
|
32
|
-
|
53
|
+
# Minor alterations to original source to enable variable chunk sizes.
|
54
|
+
def send_request_with_body_stream(sock, ver, path, f) # :doc:
|
33
55
|
raise ArgumentError, "Content-Length not given and Transfer-Encoding is not `chunked'" unless content_length() or chunked?
|
34
56
|
unless content_type()
|
35
57
|
warn 'net/http: warning: Content-Type did not set; using application/x-www-form-urlencoded' if $VERBOSE
|
@@ -48,18 +70,4 @@ class Net::HTTPGenericRequest
|
|
48
70
|
end
|
49
71
|
end
|
50
72
|
end
|
51
|
-
end
|
52
|
-
|
53
|
-
class Net::HTTPRequest
|
54
|
-
def to_s
|
55
|
-
str = "*******\n" +
|
56
|
-
"#{self.class::METHOD} #{@path} HTTP/1.1\n" +
|
57
|
-
"Host: #{S3::HOST}\n"
|
58
|
-
|
59
|
-
self.each_capitalized do |key, value|
|
60
|
-
str += "#{key}: #{value}\n"
|
61
|
-
end
|
62
|
-
str += "*******\n\n"
|
63
|
-
str
|
64
|
-
end
|
65
73
|
end
|