class Canistor::Storage::Upload
Constants
- META_HEADERS
Attributes
bucket[RW]
headers[R]
id[RW]
key[RW]
parts[RW]
region[RW]
Public Class Methods
new(**attributes)
click to toggle source
# File lib/canistor/storage/upload.rb, line 14 def initialize(**attributes) @id = SecureRandom.hex(64) @parts = {} @headers = {} attributes.each do |name, value| send("#{name}=", value) end end
Public Instance Methods
get(context)
click to toggle source
# File lib/canistor/storage/upload.rb, line 27 def get(context) list_parts(context) end
post(context, subject)
click to toggle source
# File lib/canistor/storage/upload.rb, line 50 def post(context, subject) catch(:rendered_error) do object = Canistor::Storage::Object.new( region: region, bucket: bucket, key: key ) object.write(headers, String.new) each_part_in_body(context) do |part| object.data << part.data end show_complete_upload(context, object) object end end
put(context, subject)
click to toggle source
# File lib/canistor/storage/upload.rb, line 31 def put(context, subject) params = CGI::parse(context.http_request.endpoint.query.to_s) if params.has_key?('uploads') write(context.http_request.headers) show_initiate_upload(context) elsif params.has_key?('partNumber') part_number = Integer(params['partNumber'][0]) part = find_or_build_part(subject, context, part_number) parts[part_number] = part part.put(context, subject) else raise( RuntimeError, "Implementation should never attempt to PUT an upload when there " \ "is no uploads or partNumber parameter present in the request." ) end end
write(headers)
click to toggle source
# File lib/canistor/storage/upload.rb, line 23 def write(headers) self.headers = headers end
Private Instance Methods
each_part() { |parts| ... }
click to toggle source
# File lib/canistor/storage/upload.rb, line 145 def each_part(&block) parts.keys.sort.each do |number| yield parts[number] end end
each_part_in_body(context) { |found| ... }
click to toggle source
# File lib/canistor/storage/upload.rb, line 112 def each_part_in_body(context) document = Nokogiri::XML.parse(context.http_request.body.read) number = 0 document.css('Part').each do |element| part_number = Integer(element.css('PartNumber').text) if part_number > number part_etag = element.css('ETag').text found = find_part(part_number, part_etag) if found yield found else Canistor::ErrorHandler.serve_invalid_part( context, id, part_number, part_etag ) throw :rendered_error end number = part_number else Canistor::ErrorHandler.serve_invalid_part_order(context, id) throw :rendered_error end end end
find_or_build_part(subject, context, part_number)
click to toggle source
# File lib/canistor/storage/upload.rb, line 82 def find_or_build_part(subject, context, part_number) parts[part_number] || Canistor::Storage::Part.new( region: subject.region, bucket: subject.bucket, key: subject.key, upload_id: id, number: part_number ) end
find_part(part_number, part_etag)
click to toggle source
# File lib/canistor/storage/upload.rb, line 136 def find_part(part_number, part_etag) if part = parts[part_number] if part.etag == part_etag return part end end nil end
headers=(headers)
click to toggle source
# File lib/canistor/storage/upload.rb, line 73 def headers=(headers) return if headers.nil? headers.each do |name, value| if META_HEADERS.include?(name) @headers[name] = value end end end
list_parts(context)
click to toggle source
# File lib/canistor/storage/upload.rb, line 151 def list_parts(context) context.http_response.signal_headers( 200, 'date' => Time.now.httpdate, 'x-amz-request-id' => SecureRandom.hex(8).upcase ) context.http_response.signal_data(to_upload_parts_xml(context)) end
show_complete_upload(context, etag)
click to toggle source
# File lib/canistor/storage/upload.rb, line 103 def show_complete_upload(context, etag) context.http_response.signal_headers( 200, 'date' => Time.now.httpdate, 'x-amz-request-id' => SecureRandom.hex(8).upcase ) context.http_response.signal_data(to_complete_xml(context, etag)) end
show_initiate_upload(context)
click to toggle source
# File lib/canistor/storage/upload.rb, line 92 def show_initiate_upload(context) context.http_response.signal_headers( 200, 'date' => Time.now.httpdate, 'x-amz-request-id' => SecureRandom.hex(8).upcase ) unless context.http_request.http_method == 'HEAD' context.http_response.signal_data(to_initiate_xml(context)) end end
to_complete_xml(context, object)
click to toggle source
# File lib/canistor/storage/upload.rb, line 172 def to_complete_xml(context, object) Nokogiri::XML::Builder.new do |xml| xml.CompleteMultipartUploadResult( xmlns: 'http://s3.amazonaws.com/doc/2006-03-01/' ) do xml.Location object.location xml.Bucket object.bucket xml.Key object.key xml.ETag object.etag end end.to_xml end
to_initiate_xml(context)
click to toggle source
# File lib/canistor/storage/upload.rb, line 160 def to_initiate_xml(context) Nokogiri::XML::Builder.new do |xml| xml.InitiateMultipartUploadResult( xmlns: 'http://s3.amazonaws.com/doc/2006-03-01/' ) do xml.Bucket bucket xml.Key key xml.UploadId id end end.to_xml end
to_upload_parts_xml(context)
click to toggle source
# File lib/canistor/storage/upload.rb, line 185 def to_upload_parts_xml(context) Nokogiri::XML::Builder.new do |xml| xml.ListPartsResult( xmlns: 'http://s3.amazonaws.com/doc/2006-03-01/' ) do xml.Bucket bucket xml.Key key xml.UploadId id each_part do |part| xml.Part do xml.PartNumber part.number xml.ETag part.etag xml.Size part.size end end end end.to_xml end