s33r 0.2 → 0.3
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/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
|