class Fog::Storage::Aliyun::Real
Attributes
Initialize connection to OSS
Notes¶ ↑
options parameter must include values for :aliyun_oss_endpoint, :aliyun_accesskey_id, :aliyun_secret_access_key, :aliyun_oss_location and :aliyun_oss_bucket in order to create a connection. if you haven't set these values in the configuration file.
Examples¶ ↑
sdb = Fog::Storage.new(:provider=>'aliyun', :aliyun_accesskey_id => your_:aliyun_accesskey_id, :aliyun_secret_access_key => your_aliyun_secret_access_key )
Parameters¶ ↑
-
options<~Hash> - config arguments for connection. Defaults to {}.
Returns¶ ↑
-
OSS object with connection to aliyun.
Public Class Methods
# File lib/fog/aliyun/storage.rb, line 61 def initialize(options = {}) # initialize the parameters @aliyun_oss_endpoint = options[:aliyun_oss_endpoint] @aliyun_oss_location = options[:aliyun_oss_location] @aliyun_accesskey_id = options[:aliyun_accesskey_id] @aliyun_accesskey_secret = options[:aliyun_accesskey_secret] @aliyun_oss_bucket = options[:aliyun_oss_bucket] # check for the parameters missing_credentials = [] missing_credentials << :aliyun_oss_endpoint unless @aliyun_oss_endpoint missing_credentials << :aliyun_oss_location unless @aliyun_oss_location missing_credentials << :aliyun_accesskey_id unless @aliyun_accesskey_id missing_credentials << :aliyun_accesskey_secret unless @aliyun_accesskey_secret raise ArgumentError, "Missing required arguments: #{missing_credentials.join(', ')}" unless missing_credentials.empty? @connection_options = options[:connection_options] || {} uri = URI.parse(@aliyun_oss_endpoint) @host = uri.host @path = uri.path @port = uri.port @scheme = uri.scheme @persistent = options[:persistent] || false end
Public Instance Methods
# File lib/fog/aliyun/requests/storage/delete_object.rb, line 26 def abort_multipart_upload(bucket, object, endpoint, uploadid) if nil == endpoint location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' end path = object + '?uploadId=' + uploadid resource = bucket + '/' + path ret = request( expects: 204, method: 'DELETE', path: path, bucket: bucket, resource: resource, endpoint: endpoint ) end
# File lib/fog/aliyun/requests/storage/put_object.rb, line 155 def complete_multipart_upload(bucket, object, endpoint, uploadId) if nil == endpoint location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' end parts = list_parts(bucket, object, endpoint, uploadId, options = {}) request_part = [] return if parts.empty? for i in 0..(parts.size - 1) part = parts[i] request_part[i] = { 'PartNumber' => part['PartNumber'], 'ETag' => part['ETag'] } end body = XmlSimple.xml_out({ 'Part' => request_part }, 'RootName' => 'CompleteMultipartUpload') path = object + '?uploadId=' + uploadId resource = bucket + '/' + path ret = request( expects: 200, method: 'POST', path: path, bucket: bucket, resource: resource, endpoint: endpoint, body: body ) end
Copy object
Parameters¶ ↑
-
source_bucket<~String> - Name of source bucket
-
source_object<~String> - Name of source object
-
target_bucket<~String> - Name of bucket to create copy in
-
target_object<~String> - Name for new copy of object
-
options<~Hash> - Additional headers options={}
# File lib/fog/aliyun/requests/storage/copy_object.rb, line 13 def copy_object(source_bucket, source_object, target_bucket, target_object, options = {}) options = options.reject { |_key, value| value.nil? } bucket = options[:bucket] bucket ||= @aliyun_oss_bucket source_bucket ||= bucket target_bucket ||= bucket headers = { 'x-oss-copy-source' => "/#{source_bucket}/#{source_object}" } location = get_bucket_location(target_bucket) endpoint = 'http://' + location + '.aliyuncs.com' resource = target_bucket + '/' + target_object request(expects: [200, 203], headers: headers, method: 'PUT', path: target_object, bucket: target_bucket, resource: resource, endpoint: endpoint) end
Delete an existing bucket
Parameters¶ ↑
-
bucket<~String> - Name of bucket to delete
# File lib/fog/aliyun/requests/storage/delete_bucket.rb, line 10 def delete_bucket(bucket) location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' resource = bucket + '/' request( expects: 204, method: 'DELETE', bucket: bucket, resource: resource, endpoint: endpoint ) end
Delete an existing container
Parameters¶ ↑
-
container<~String> - Name of container to delete
-
options
# File lib/fog/aliyun/requests/storage/delete_container.rb, line 11 def delete_container(container, options = {}) bucket = options[:bucket] bucket ||= @aliyun_oss_bucket location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' object = container + '/' resource = bucket + '/' + object request( expects: 204, method: 'DELETE', path: object, bucket: bucket, resource: resource, endpoint: endpoint ) end
Delete an existing object
Parameters¶ ↑
-
object<~String> - Name of object to delete
# File lib/fog/aliyun/requests/storage/delete_object.rb, line 10 def delete_object(object, options = {}) bucket = options[:bucket] bucket ||= @aliyun_oss_bucket location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' resource = bucket + '/' + object request( expects: 204, method: 'DELETE', path: object, bucket: bucket, resource: resource, endpoint: endpoint ) end
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 5 def get_bucket(bucket) location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' resource = bucket + '/' ret = request( expects: [200, 203], method: 'GET', bucket: bucket, resource: resource, endpoint: endpoint ) xml = ret.data[:body] result = XmlSimple.xml_in(xml) end
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 49 def get_bucket_CORSRules(bucket) location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' attribute = '?cors' resource = bucket + '/' + attribute ret = request( expects: [200, 203, 404], method: 'GET', path: attribute, bucket: bucket, resource: resource, endpoint: endpoint ) if 404 != ret.data[:status] cors = XmlSimple.xml_in(ret.data[:body])['CORSRule'][0] end end
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 33 def get_bucket_acl(bucket) location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' attribute = '?acl' resource = bucket + '/' + attribute ret = request( expects: [200, 203], method: 'GET', path: attribute, bucket: bucket, resource: resource, endpoint: endpoint ) acl = XmlSimple.xml_in(ret.data[:body])['AccessControlList'][0]['Grant'][0] end
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 67 def get_bucket_lifecycle(bucket) location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' attribute = '?lifecycle' resource = bucket + '/' + attribute ret = request( expects: [200, 203, 404], method: 'GET', path: attribute, bucket: bucket, resource: resource, endpoint: endpoint ) if 404 != ret.data[:status] lifecycle = XmlSimple.xml_in(ret.data[:body])['Rule'][0] end end
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 20 def get_bucket_location(bucket) attribute = '?location' resource = bucket + '/' + attribute ret = request( expects: [200, 203], method: 'GET', path: attribute, bucket: bucket, resource: resource ) location = XmlSimple.xml_in(ret.data[:body]) end
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 85 def get_bucket_logging(bucket) location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' attribute = '?logging' resource = bucket + '/' + attribute ret = request( expects: [200, 203], method: 'GET', path: attribute, bucket: bucket, resource: resource, endpoint: endpoint ) logging = XmlSimple.xml_in(ret.data[:body])['LoggingEnabled'][0]['TargetPrefix'] end
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 101 def get_bucket_referer(bucket) location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' attribute = '?referer' resource = bucket + '/' + attribute ret = request( expects: [200, 203], method: 'GET', path: attribute, bucket: bucket, resource: resource, endpoint: endpoint ) referer = XmlSimple.xml_in(ret.data[:body]) end
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 117 def get_bucket_website(bucket) location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' attribute = '?website' resource = bucket + '/' + attribute ret = request( expects: [200, 203, 404], method: 'GET', path: attribute, bucket: bucket, resource: resource, endpoint: endpoint ) if 404 != ret.data[:status] website = XmlSimple.xml_in(ret.data[:body]) end end
# File lib/fog/aliyun/requests/storage/get_container.rb, line 5 def get_container(container, options = {}) options = options.reject { |_key, value| value.nil? } bucket = options[:bucket] bucket ||= @aliyun_oss_bucket marker = options[:marker] maxKeys = options[:maxKeys] delimiter = '/' path = '' prefix = if container == '' || container == '.' || container.nil? nil else container + '/' end if prefix path += '?prefix=' + prefix path += '&marker=' + marker if marker path += '&max-keys=' + maxKeys if maxKeys path += '&delimiter=' + delimiter if delimiter elsif marker path += '?marker=' + marker path += '&max-keys=' + maxKeys if maxKeys path += '&delimiter=' + delimiter if delimiter elsif maxKeys path += '?max-keys=' + maxKeys path += '&delimiter=' + delimiter if delimiter elsif delimiter path += '?delimiter=' + delimiter end location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' resource = bucket + '/' ret = request( expects: [200, 203, 400], method: 'GET', path: path, resource: resource, bucket: bucket ) xml = ret.data[:body] result = XmlSimple.xml_in(xml)['CommonPrefixes'] end
List existing storage containers
Parameters¶ ↑
-
options<~Hash>:
-
'maxKeys'<~Integer> - Upper limit to number of results returned
-
'marker'<~String> - Only return objects with name greater than this value
-
Returns¶ ↑
# File lib/fog/aliyun/requests/storage/get_containers.rb, line 14 def get_containers(options = {}) options = options.reject { |_key, value| value.nil? } bucket = options[:bucket] bucket ||= @aliyun_oss_bucket prefix = options[:prefix] marker = options[:marker] maxKeys = options[:maxKeys] delimiter = '/' path = '' if prefix path += '?prefix=' + prefix path += '&marker=' + marker if marker path += '&max-keys=' + maxKeys if maxKeys path += '&delimiter=' + delimiter if delimiter elsif marker path += '?marker=' + marker path += '&max-keys=' + maxKeys if maxKeys path += '&delimiter=' + delimiter if delimiter elsif maxKeys path += '?max-keys=' + maxKeys path += '&delimiter=' + delimiter if delimiter elsif delimiter path += '?delimiter=' + delimiter end location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' resource = bucket + '/' ret = request( expects: [200, 203, 400], method: 'GET', path: path, resource: resource, bucket: bucket ) xml = ret.data[:body] result = XmlSimple.xml_in(xml)['CommonPrefixes'] end
Get details for object
Parameters¶ ↑
-
object<~String> - Name of object to look for
# File lib/fog/aliyun/requests/storage/get_object.rb, line 10 def get_object(object, range = nil, options = {}) options = options.reject { |_key, value| value.nil? } bucket = options[:bucket] bucket ||= @aliyun_oss_bucket endpoint = options[:endpoint] if nil == endpoint location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' end resource = bucket + '/' + object para = { expects: [200, 206, 404], method: 'GET', path: object, bucket: bucket, resource: resource, endpoint: endpoint } if range rangeStr = 'bytes=' + range para[:headers] = { 'Range' => rangeStr } end response = request(para) response.data end
Get an expiring object http url
Parameters¶ ↑
-
container<~String> - Name of container containing object
-
object<~String> - Name of object to get expiring url for
-
expires<~Time> - An expiry time for this url
Returns¶ ↑
-
response<~Excon::Response>:
-
body<~String> - url for object
-
# File lib/fog/aliyun/requests/storage/get_object_http_url.rb, line 15 def get_object_http_url_public(object, expires, options = {}) options = options.reject { |_key, value| value.nil? } bucket = options[:bucket] bucket ||= @aliyun_oss_bucket acl = get_bucket_acl(bucket) location = get_bucket_location(bucket) if 'private' == acl expires_time = (Time.now.to_i + expires).to_s resource = bucket + '/' + object signature = sign('GET', expires_time, nil, resource) url = 'http://' + bucket + '.' + location + '.aliyuncs.com/' + object + '?OSSAccessKeyId=' + @aliyun_accesskey_id + '&Expires=' + expires_time + '&Signature=' + URI.encode(signature, '/[^!*\'()\;?:@#&%=+$,{}[]<>`" ') elsif 'public-read' == acl || 'public-read-write' == acl url = 'http://' + bucket + '.' + location + '.aliyuncs.com/' + object else url = 'acl is wrong with value:' + acl end end
Get an expiring object https url from Cloud Files
Parameters¶ ↑
-
container<~String> - Name of container containing object
-
object<~String> - Name of object to get expiring url for
-
expires<~Time> - An expiry time for this url
Returns¶ ↑
-
response<~Excon::Response>:
-
body<~String> - url for object
-
# File lib/fog/aliyun/requests/storage/get_object_https_url.rb, line 15 def get_object_https_url_public(object, expires, options = {}) options = options.reject { |_key, value| value.nil? } bucket = options[:bucket] bucket ||= @aliyun_oss_bucket acl = get_bucket_acl(bucket) location = get_bucket_location(bucket) if 'private' == acl expires_time = (Time.now.to_i + expires).to_s resource = bucket + '/' + object signature = sign('GET', expires_time, nil, resource) url = 'https://' + bucket + '.' + location + '.aliyuncs.com/' + object + '?OSSAccessKeyId=' + @aliyun_accesskey_id + '&Expires=' + expires_time + '&Signature=' + URI.encode(signature, '/[^!*\'()\;?:@#&%=+$,{}[]<>`" ') elsif 'public-read' == acl || 'public-read-write' == acl url = 'https://' + bucket + '.' + location + '.aliyuncs.com/' + object else url = 'acl is wrong with value:' + acl end end
Get headers for object
Parameters¶ ↑
-
object<~String> - Name of object to look for
# File lib/fog/aliyun/requests/storage/head_object.rb, line 10 def head_object(object, options = {}) bucket = options[:bucket] bucket ||= @aliyun_oss_bucket location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' resource = bucket + '/' + object ret = request( expects: [200, 404], method: 'HEAD', path: object, bucket: bucket, resource: resource, endpoint: endpoint ) ret end
# File lib/fog/aliyun/requests/storage/put_object.rb, line 119 def initiate_multipart_upload(bucket, object, endpoint) if nil == endpoint location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' end path = object + '?uploads' resource = bucket + '/' + path ret = request( expects: 200, method: 'POST', path: path, bucket: bucket, resource: resource, endpoint: endpoint ) uploadid = XmlSimple.xml_in(ret.data[:body])['UploadId'][0] end
# File lib/fog/aliyun/requests/storage/list_buckets.rb, line 5 def list_buckets(options = {}) prefix = options[:prefix] marker = options[:marker] maxKeys = options[:maxKeys] path = '' if prefix path += '?prefix=' + prefix path += '&marker=' + marker if marker path += '&max-keys=' + maxKeys if maxKeys elsif marker path += '?marker=' + marker path += '&max-keys=' + maxKeys if maxKeys elsif maxKeys path += '?max-keys=' + maxKeys end ret = request( expects: [200, 203], method: 'GET', path: path ) xml = ret.data[:body] result = XmlSimple.xml_in(xml)['Buckets'][0] end
# File lib/fog/aliyun/requests/storage/list_objects.rb, line 46 def list_multipart_uploads(bucket, endpoint, _options = {}) if nil == endpoint location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' end path = '?uploads' resource = bucket + '/' + path ret = request( expects: 200, method: 'GET', path: path, bucket: bucket, resource: resource, endpoint: endpoint ) uploadid = XmlSimple.xml_in(ret.data[:body])['Upload'] end
# File lib/fog/aliyun/requests/storage/list_objects.rb, line 5 def list_objects(options = {}) bucket = options[:bucket] bucket ||= @aliyun_oss_bucket prefix = options[:prefix] marker = options[:marker] maxKeys = options[:maxKeys] delimiter = options[:delimiter] path = '' if prefix path += '?prefix=' + prefix path += '&marker=' + marker if marker path += '&max-keys=' + maxKeys if maxKeys path += '&delimiter=' + delimiter if delimiter elsif marker path += '?marker=' + marker path += '&max-keys=' + maxKeys if maxKeys path += '&delimiter=' + delimiter if delimiter elsif maxKeys path += '?max-keys=' + maxKeys path += '&delimiter=' + delimiter if delimiter elsif delimiter path += '?delimiter=' + delimiter end location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' resource = bucket + '/' ret = request( expects: [200, 203, 400], method: 'GET', path: path, resource: resource, bucket: bucket ) xml = ret.data[:body] result = XmlSimple.xml_in(xml) end
# File lib/fog/aliyun/requests/storage/list_objects.rb, line 65 def list_parts(bucket, object, endpoint, uploadid, _options = {}) if nil == endpoint location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' end path = object + '?uploadId=' + uploadid resource = bucket + '/' + path ret = request( expects: 200, method: 'GET', path: path, bucket: bucket, resource: resource, endpoint: endpoint ) parts = XmlSimple.xml_in(ret.data[:body])['Part'] end
# File lib/fog/aliyun/requests/storage/put_bucket.rb, line 5 def put_bucket(bucketName) resource = bucketName + '/' ret = request( expects: [200, 203], method: 'PUT', resource: resource, bucket: bucketName ) end
Create a new container
Parameters¶ ↑
-
name<~String> - Name for container
# File lib/fog/aliyun/requests/storage/put_container.rb, line 10 def put_container(name, options = {}) bucket = options[:bucket] bucket ||= @aliyun_oss_bucket location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' path = name + '/' resource = bucket + '/' + name + '/' request( expects: [200, 203], method: 'PUT', path: path, bucket: bucket, resource: resource, endpoint: endpoint ) end
# File lib/fog/aliyun/requests/storage/put_object.rb, line 54 def put_folder(bucket, folder, endpoint) if nil == endpoint location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' end path = folder + '/' resource = bucket + '/' + folder + '/' ret = request( expects: [200, 203], method: 'PUT', path: path, bucket: bucket, resource: resource, endpoint: endpoint ) end
# File lib/fog/aliyun/requests/storage/put_object.rb, line 71 def put_multipart_object(bucket, object, file) location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' # find the right uploadid uploads = list_multipart_uploads(bucket, endpoint) if nil != uploads upload = uploads.find { |tmpupload| tmpupload['Key'][0] == object } else upload = nil end parts = nil uploadedSize = 0 start_partNumber = 1 if nil != upload uploadId = upload['UploadId'][0] parts = list_parts(bucket, object, endpoint, uploadId) if (nil != parts) && !parts.empty? if parts[-1]['Size'][0].to_i != 5_242_880 # the part is the last one, if its size is over 5m, then finish this upload complete_multipart_upload(bucket, object, endpoint, uploadId) return end uploadedSize = (parts[0]['Size'][0].to_i * (parts.size - 1)) + parts[-1]['Size'][0].to_i start_partNumber = parts[-1]['PartNumber'][0].to_i + 1 end else # create upload ID uploadId = initiate_multipart_upload(bucket, object, endpoint) end if file.size <= uploadedSize complete_multipart_upload(bucket, object, endpoint, uploadId) return end end_partNumber = (file.size + 5_242_880 - 1) / 5_242_880 file.seek(uploadedSize) for i in start_partNumber..end_partNumber body = file.read(5_242_880) upload_part(bucket, object, endpoint, i.to_s, uploadId, body) end complete_multipart_upload(bucket, object, endpoint, uploadId) end
Put details for object
Parameters¶ ↑
-
object<~String> - Name of object to look for
# File lib/fog/aliyun/requests/storage/put_object.rb, line 10 def put_object(object, file = nil, options = {}) bucket = options[:bucket] bucket ||= @aliyun_oss_bucket location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' return put_folder(bucket, object, endpoint) if nil == file # put multiparts if object's size is over 100m if file.size > 104_857_600 return put_multipart_object(bucket, object, file) end body = file.read resource = bucket + '/' + object ret = request( expects: [200, 203], method: 'PUT', path: object, bucket: bucket, resource: resource, body: body, endpoint: endpoint ) end
# File lib/fog/aliyun/requests/storage/put_object.rb, line 36 def put_object_with_body(object, body, options = {}) bucket = options[:bucket] bucket ||= @aliyun_oss_bucket location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' resource = bucket + '/' + object ret = request( expects: [200, 203], method: 'PUT', path: object, bucket: bucket, resource: resource, body: body, endpoint: endpoint ) end
# File lib/fog/aliyun/storage.rb, line 88 def reload @connection.reset end
# File lib/fog/aliyun/storage.rb, line 92 def request(params) method = params[:method] time = Time.new.utc date = time.strftime('%a, %d %b %Y %H:%M:%S GMT') endpoint = params[:endpoint] if endpoint uri = URI.parse(endpoint) host = uri.host path = uri.path port = uri.port scheme = uri.scheme else host = @host path = @path port = @port scheme = @scheme end bucket = params[:bucket] tmpHost = if bucket bucket + '.' + host else host end @connection = Fog::Core::Connection.new("#{scheme}://#{tmpHost}", @persistent, @connection_options) contentType = params[:contentType] begin headers = '' if params[:headers] params[:headers].each do |k, v| headers += "#{k}:#{v}\n" if k != 'Range' end end signature = sign(method, date, contentType, params[:resource], headers) response = @connection.request(params.merge(headers: { 'Content-Type' => contentType, 'Authorization' => 'OSS ' + @aliyun_accesskey_id + ':' + signature, 'Date' => date }.merge!(params[:headers] || {}), path: "#{path}/#{params[:path]}", query: params[:query])) rescue Excon::Errors::HTTPStatusError => error raise case error when Excon::Errors::NotFound Fog::Storage::Aliyun::NotFound.slurp(error) else error end end response end
copmute signature
# File lib/fog/aliyun/storage.rb, line 149 def sign(method, date, contentType, resource = nil, headers = nil) contentmd5 = '' canonicalizedResource = if resource '/' + resource else '/' end canonicalizedOSSHeaders = if headers headers else '' end contentTypeStr = if contentType contentType else '' end stringToSign = method + "\n" + contentmd5 + "\n" + contentTypeStr + "\n" + date + "\n" + canonicalizedOSSHeaders + canonicalizedResource digVer = OpenSSL::Digest.new('sha1') digest = OpenSSL::HMAC.digest(digVer, @aliyun_accesskey_secret, stringToSign) signature = Base64.encode64(digest) signature[-1] = '' signature end
# File lib/fog/aliyun/requests/storage/put_object.rb, line 137 def upload_part(bucket, object, endpoint, partNumber, uploadId, body) if nil == endpoint location = get_bucket_location(bucket) endpoint = 'http://' + location + '.aliyuncs.com' end path = object + '?partNumber=' + partNumber + '&uploadId=' + uploadId resource = bucket + '/' + path ret = request( expects: [200, 203], method: 'PUT', path: path, bucket: bucket, resource: resource, body: body, endpoint: endpoint ) end