class Fog::Aliyun::Storage::Real

Attributes

aliyun_accesskey_id[R]

Initialize connection to OSS

Notes

options parameter must include values for :aliyun_accesskey_id, :aliyun_secret_access_key and :aliyun_oss_bucket in order to create a connection. :aliyun_oss_location will be replaced by :aliyun_region_id, and it has a default value cn-hangzhou if :aliyun_oss_endpoint is not specified, it will be generated by method region_to_endpoint

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.

aliyun_accesskey_secret[R]
aliyun_oss_bucket[R]
aliyun_oss_endpoint[R]
aliyun_oss_sdk_log_path[R]
aliyun_region_id[R]

Public Class Methods

new(options = {}) click to toggle source
# File lib/fog/aliyun/storage.rb, line 84
def initialize(options = {})
  # initialize the parameters
  @aliyun_region_id = options[:aliyun_region_id] || options[:aliyun_oss_location] || DEFAULT_REGION
  @aliyun_oss_endpoint = options[:aliyun_oss_endpoint] || region_to_endpoint(@aliyun_region_id)
  @aliyun_accesskey_id = options[:aliyun_accesskey_id]
  @aliyun_accesskey_secret = options[:aliyun_accesskey_secret]
  @aliyun_oss_bucket = options[:aliyun_oss_bucket]
  @aliyun_oss_sdk_log_path=options[:aliyun_oss_sdk_log_path]
  if @aliyun_oss_sdk_log_path && !::File.exist?(@aliyun_oss_sdk_log_path)
    `touch #{@aliyun_oss_sdk_log_path}`
  end
  ENV["ALIYUN_OSS_SDK_LOG_PATH"] = @aliyun_oss_sdk_log_path
  # check for the parameters
  missing_credentials = []
  missing_credentials << :aliyun_oss_bucket unless @aliyun_oss_bucket
  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] || {}

  endpoint = @aliyun_oss_endpoint

  @aliyun_oss_endpoint = "#{DEFAULT_SCHEME}://#{endpoint}" unless endpoint.start_with?(DEFAULT_SCHEME)

  uri = URI.parse(@aliyun_oss_endpoint)
  @host = uri.host
  @path = uri.path
  @scheme = uri.scheme || DEFAULT_SCHEME
  @port = uri.port || DEFAULT_SCHEME_PORT[@scheme]

  @persistent = options[:persistent] || false
  @oss_client = AliyunOssSdk::Client.new(
                             :endpoint => @aliyun_oss_endpoint,
                             :access_key_id => @aliyun_accesskey_id,
                             :access_key_secret => @aliyun_accesskey_secret
  )

  # initiate a aliyun oss ruby sdk config and using sdk http to invoke the OSS openapi
  @oss_config = AliyunOssSdk::Config.new(
      :endpoint => @aliyun_oss_endpoint,
      :access_key_id => @aliyun_accesskey_id,
      :access_key_secret => @aliyun_accesskey_secret
  )
  @oss_http = AliyunOssSdk::HTTP.new(@oss_config)
  @oss_protocol = AliyunOssSdk::Protocol.new(@oss_config)
end

Public Instance Methods

abort_multipart_upload(bucket_name, object_name, upload_id) click to toggle source

Abort a multipart upload

@param [String] bucket_name Name of bucket to abort multipart upload on @param [String] object_name Name of object to abort multipart upload on @param [String] upload_id Id of upload to add part to

@see help.aliyun.com/document_detail/31996.html

# File lib/fog/aliyun/requests/storage/abort_multipart_upload.rb, line 15
def abort_multipart_upload(bucket_name, object_name, upload_id)
  @oss_protocol.abort_multipart_upload(bucket_name, object_name, upload_id)
end
bucket_exists?(bucket_name) click to toggle source
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 7
def bucket_exists?(bucket_name)
  @oss_client.bucket_exists?(bucket_name)
end
complete_multipart_upload(bucket_name, object_name, upload_id, parts) click to toggle source

Complete a multipart upload

@param [String] bucket_name Name of bucket to complete multipart upload for @param [String] object_name Name of object to complete multipart upload for @param [String] upload_id Id of upload to add part to @param [Array] parts Array of etag and number as Strings for parts

@see help.aliyun.com/document_detail/31995.html

# File lib/fog/aliyun/requests/storage/complete_multipart_upload.rb, line 15
def complete_multipart_upload(bucket_name, object_name, upload_id, parts)
  @oss_protocol.complete_multipart_upload(bucket_name, object_name, upload_id, parts)
end
copy_object(source_bucket_name, source_object_name, target_bucket_name, target_object_name, options = {}) click to toggle source

Copy object

Parameters

  • source_bucket_name<~String> - Name of source bucket

  • source_object_name<~String> - Name of source object

  • target_bucket_name<~String> - Name of bucket to create copy in

  • target_object_name<~String> - Name for new copy of object

  • options<~Hash> - Additional headers options={}

# File lib/fog/aliyun/requests/storage/copy_object.rb, line 15
def copy_object(source_bucket_name, source_object_name, target_bucket_name, target_object_name, options = {})
  headers = { 'x-oss-copy-source' => "/#{source_bucket_name}#{object_to_path(source_object_name)}" }.merge!(options)
  resources = {
      :bucket => target_bucket_name,
      :object => target_object_name
  }
  http_options = {
      :headers => headers
  }
  @oss_http.put(resources, http_options)
end
delete_bucket(bucket_name) click to toggle source

Delete an existing bucket

Parameters

  • bucket_name<~String> - Name of bucket to delete

# File lib/fog/aliyun/requests/storage/delete_bucket.rb, line 12
def delete_bucket(bucket_name)
  @oss_protocol.delete_bucket(bucket_name)
end
delete_multiple_objects(bucket_name, object_names, options = {}) click to toggle source

Delete multiple objects from OSS

@param bucket_name [String] Name of bucket containing object to delete @param object_names [Array] Array of object names to delete

@see help.aliyun.com/document_detail/31983.html

# File lib/fog/aliyun/requests/storage/delete_multiple_objects.rb, line 13
def delete_multiple_objects(bucket_name, object_names, options = {})
  bucket = @oss_client.get_bucket(bucket_name)
  bucket.batch_delete_objects(object_names, options)
end
delete_object(bucket_name, object_name, options = {}) click to toggle source

Delete an existing object

Parameters

  • bucket_name<~String> - Name of bucket to delete

  • object_name<~String> - Name of object to delete

# File lib/fog/aliyun/requests/storage/delete_object.rb, line 13
def delete_object(bucket_name, object_name, options = {})
  # TODO Support versionId
  # if version_id = options.delete('versionId')
  #   query = {'versionId' => version_id}
  # else
  #   query = {}
  # end
  @oss_http.delete({:bucket => bucket_name, :object => object_name}, {:headers => options})
end
escape(string) click to toggle source
# File lib/fog/aliyun/storage.rb, line 149
def escape(string)
  string.gsub(/([^a-zA-Z0-9_.\-~\/]+)/) {
    "%" + $1.unpack("H2" * $1.bytesize).join("%").upcase
  }
end
get_bucket(bucket_name, options = {}) click to toggle source
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 11
def get_bucket(bucket_name, options = {})
  unless bucket_name
    raise ArgumentError.new('bucket_name is required')
  end

  # Set the GetBucket max limitation to 1000
  maxKeys = options[:max_keys] || 1000
  maxKeys = maxKeys.to_i
  maxKeys = [maxKeys, 1000].min

  options[:limit] = maxKeys
  options.delete(:max_keys)

  @oss_protocol.list_objects(bucket_name, options)
end
get_bucket_CORSRules(bucket_name) click to toggle source
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 31
def get_bucket_CORSRules(bucket_name)
  @oss_protocol.get_bucket_cors(bucket_name)
end
get_bucket_acl(bucket_name) click to toggle source
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 27
def get_bucket_acl(bucket_name)
  @oss_protocol.get_bucket_acl(bucket_name)
end
get_bucket_lifecycle(bucket_name) click to toggle source
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 35
def get_bucket_lifecycle(bucket_name)
  @oss_protocol.get_bucket_lifecycle(bucket_name)
end
get_bucket_location(bucket_name) click to toggle source

Get location constraint for an OSS bucket

@param bucket_name [String] name of bucket to get location constraint for

@see help.aliyun.com/document_detail/31967.html

note: The OSS Ruby sdk does not support get_bucket_location and there needs to parse response

# File lib/fog/aliyun/requests/storage/get_bucket_location.rb, line 15
def get_bucket_location(bucket_name)
  data = @oss_http.get({:bucket => bucket_name, :sub_res => { 'location' => nil} }, {})
  doc = parse_xml(data.body)
  doc.at_css("LocationConstraint").text
end
get_bucket_logging(bucket_name) click to toggle source
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 39
def get_bucket_logging(bucket_name)
  @oss_protocol.get_bucket_logging(bucket_name)
end
get_bucket_referer(bucket_name) click to toggle source
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 43
def get_bucket_referer(bucket_name)
  @oss_protocol.get_bucket_referer(bucket_name)
end
get_bucket_website(bucket_name) click to toggle source
# File lib/fog/aliyun/requests/storage/get_bucket.rb, line 47
def get_bucket_website(bucket_name)
  @oss_protocol.get_bucket_website(bucket_name)
end
get_object(bucket_name, object_name, options = {}, &block) click to toggle source

Get details for object

Parameters

  • object_name<~String> - Name of object to look for

# File lib/fog/aliyun/requests/storage/get_object.rb, line 12
def get_object(bucket_name, object_name, options = {}, &block)
  options = options.reject { |_key, value| value.nil? }
  unless bucket_name
    raise ArgumentError.new('bucket_name is required')
  end
  unless object_name
    raise ArgumentError.new('object_name is required')
  end
  # Using OSS ruby SDK to fix performance issue
  http_options = { :headers => {} }
  http_options[:query] = options.delete('query') || {}

  http_options[:headers].merge!(options)
  if options['If-Modified-Since']
    http_options[:headers]['If-Modified-Since'] = Fog::Time.at(options['If-Modified-Since'].to_i).to_date_header
  end
  if options['If-Unmodified-Since']
    http_options[:headers]['If-Unmodified-Since'] = Fog::Time.at(options['If-Unmodified-Since'].to_i).to_date_header
  end

  if block_given?
    http_options[:response_block] = Proc.new {}
  end

  resources = {
      :bucket => bucket_name,
      :object => object_name
  }

  @oss_http.get(resources, http_options, &block)

end
get_object_acl(bucket_name, object_name, options = {}) click to toggle source

Get access control list for an S3 object

@param bucket_name [String] name of bucket containing object @param object_name [String] name of object to get access control list for @param options [Hash] @option options versionId [String] specify a particular version to retrieve

# File lib/fog/aliyun/requests/storage/get_object_acl.rb, line 13
def get_object_acl(bucket_name, object_name, options = {})
  unless bucket_name
    raise ArgumentError.new('bucket_name is required')
  end
  unless object_name
    raise ArgumentError.new('object_name is required')
  end

  # At present, sdk does not support versionId
  # if version_id = options.delete('versionId')
  #   query['versionId'] = version_id
  # end
  @oss_protocol.get_object_acl(bucket_name, object_name)
end
get_object_http_url_public(bucket_name, object_name, expires) click to toggle source

Get an expiring object http url

Parameters

  • bucket_name<~String> - Name of bucket

  • object_name<~String> - Name of object to get expiring url for

  • expires<~Integer> - 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 19
def get_object_http_url_public(bucket_name, object_name, expires)
  bucket = @oss_client.get_bucket(bucket_name)
  acl = bucket.acl()

  if acl == 'private'
    expires_time = (Time.now.to_i + (expires.nil? ? 0 : expires.to_i)).to_s
    resource = bucket_name + '/' + object_name
    signature = sign('GET', expires_time, nil, resource)
    'http://' + bucket_name + '.' + @host + '/' + object_name +
      '?OSSAccessKeyId=' + @aliyun_accesskey_id + '&Expires=' + expires_time +
      '&Signature=' + Addressable::URI.encode_component(signature, Addressable::URI::CharacterClasses::UNRESERVED + '|')
  elsif acl == 'public-read' || acl == 'public-read-write'
    'http://' + bucket_name + '.' + @host + '/' + object_name
  else
    'acl is wrong with value:' + acl
  end
end
get_object_https_url_public(bucket_name, object_name, expires) click to toggle source

Get an expiring object https url from Cloud Files

Parameters

  • bucket_name<~String> - Name of bucket

  • object_name<~String> - Name of object to get expiring url for

  • expires<~Integer> - 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 19
def get_object_https_url_public(bucket_name, object_name, expires)
  bucket = @oss_client.get_bucket(bucket_name)
  acl = bucket.acl()

  if acl == 'private'
    expires_time = (Time.now.to_i + (expires.nil? ? 0 : expires.to_i)).to_s
    resource = bucket_name + '/' + object_name
    signature = sign('GET', expires_time, nil, resource)
    'https://' + bucket_name + '.' + @host + '/' + object_name +
      '?OSSAccessKeyId=' + @aliyun_accesskey_id + '&Expires=' + expires_time +
      '&Signature=' + Addressable::URI.encode_component(signature, Addressable::URI::CharacterClasses::UNRESERVED + '|')
  elsif acl == 'public-read' || acl == 'public-read-write'
    'https://' + bucket_name + '.' + @host + '/' + object_name
  else
    'acl is wrong with value:' + acl
  end
end
get_service() click to toggle source

List information about OSS buckets for authorized user

# File lib/fog/aliyun/requests/storage/get_service.rb, line 7
def get_service
  @oss_protocol.list_buckets
end
head_object(bucket_name, object_name, options={}) click to toggle source

Get headers for object

Parameters

  • object_name<~String> - Name of object to look for

# File lib/fog/aliyun/requests/storage/head_object.rb, line 12
def head_object(bucket_name, object_name, options={})
  unless bucket_name
    raise ArgumentError.new('bucket_name is required')
  end
  unless object_name
    raise ArgumentError.new('object_name is required')
  end

  # Currently, the ruby sdk does not support versionId
  # if version_id = options.delete('versionId')
  #   query = {'versionId' => version_id}
  # end
  headers = {}
  headers['If-Modified-Since'] = Fog::Time.at(options['If-Modified-Since'].to_i).to_date_header if options['If-Modified-Since']
  headers['If-Unmodified-Since'] = Fog::Time.at(options['If-Unmodified-Since'].to_i).to_date_header if options['If-Modified-Since']
  headers.merge!(options)
  resources = {
      :bucket => bucket_name,
      :object => object_name
  }
  http_options = {
      :headers => headers
  }
  @oss_http.head(resources, http_options)
end
initiate_multipart_upload(bucket_name, object_name, options = {}) click to toggle source

Initiate a multipart upload

@param bucket_name [String] Name of bucket to create @param object_name [String] Name of object to create @param options [Hash]

@see help.aliyun.com/document_detail/31992.html

# File lib/fog/aliyun/requests/storage/initiate_multipart_upload.rb, line 13
def initiate_multipart_upload(bucket_name, object_name, options = {})
  @oss_protocol.initiate_multipart_upload(bucket_name, object_name, options)
end
list_buckets(options = {}) click to toggle source
# File lib/fog/aliyun/requests/storage/list_buckets.rb, line 7
def list_buckets(options = {})
  maxKeys = options[:max_keys] || 1000
  maxKeys = maxKeys.to_i
  maxKeys = [maxKeys, 1000].min

  options[:limit] = maxKeys
  options.delete(:max_keys)
  @oss_protocol.list_buckets(options)
end
list_multipart_uploads(bucket_name, _options = {}) click to toggle source
# File lib/fog/aliyun/requests/storage/list_objects.rb, line 17
def list_multipart_uploads(bucket_name, _options = {})
  @oss_protocol.list_multipart_uploads(bucket_name, _options)
end
list_objects(bucket_name, options = {}) click to toggle source
# File lib/fog/aliyun/requests/storage/list_objects.rb, line 7
def list_objects(bucket_name, options = {})
  maxKeys = options[:max_keys] || 1000
  maxKeys = maxKeys.to_i
  maxKeys = [maxKeys, 1000].min

  options[:limit] = maxKeys
  options.delete(:max_keys)
  @oss_protocol.list_objects(bucket_name, options)
end
list_parts(bucket_name, object_name, upload_id, _options = {}) click to toggle source
# File lib/fog/aliyun/requests/storage/list_objects.rb, line 21
def list_parts(bucket_name, object_name, upload_id, _options = {})
  @oss_protocol.list_parts(bucket_name, object_name, upload_id, _options)
end
object_to_path(object_name=nil) click to toggle source
# File lib/fog/aliyun/storage.rb, line 145
def object_to_path(object_name=nil)
  '/' + escape(object_name.to_s).gsub('%2F','/')
end
put_bucket(bucket_name, options = {}) click to toggle source
# File lib/fog/aliyun/requests/storage/put_bucket.rb, line 7
def put_bucket(bucket_name, options = {})
  @oss_protocol.create_bucket(bucket_name, options)
end
put_object(bucket_name, object_name, data, options = {}) click to toggle source

Put details for object

Parameters

  • bucket_name<~String> - Name of bucket to look for

  • object_name<~String> - Object of object to look for

  • data<~File>

  • options<~Hash>

# File lib/fog/aliyun/requests/storage/put_object.rb, line 15
def put_object(bucket_name, object_name, data, options = {})
  if data.is_a? ::File
    @oss_protocol.put_object(bucket_name, object_name, options)do |sw|
      while line = data.read(16*1024)
        sw.write(line)
      end
    end
  else
    content=StringIO.new(data.dup)
    @oss_protocol.put_object(bucket_name, object_name, options)do |sw|
      while line=content.read(16*1024)
        sw.write(line)
      end
    end
    content.close
  end
end
region_to_endpoint(region = nil) click to toggle source
# File lib/fog/aliyun/storage.rb, line 136
def region_to_endpoint(region = nil)
  case region.to_s
  when ''
    "oss-#{DEFAULT_REGION}.aliyuncs.com"
  else
    "oss-#{region}.aliyuncs.com"
  end
end
reload() click to toggle source
# File lib/fog/aliyun/storage.rb, line 132
def reload
  @connection.reset
end
request(params) click to toggle source
# File lib/fog/aliyun/storage.rb, line 155
def request(params)
  method = params[:method]
  time = Time.new.utc
  date = time.strftime('%a, %d %b %Y %H:%M:%S GMT')

  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::Aliyun::Storage::NotFound.slurp(error)
          else
            error
          end
  end

  response
end
sign(method, date, contentType, resource = nil, headers = nil) click to toggle source

copmute signature

# File lib/fog/aliyun/storage.rb, line 198
def sign(method, date, contentType, resource = nil, headers = nil)
  contentmd5 = ''

  canonicalizedResource = if resource
                            '/' + resource
                          else
                            '/'
                          end

  canonicalizedOSSHeaders = headers || ''

  contentTypeStr = contentType || ''

  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
upload_part(bucket_name, object_name, upload_id, part_number, data) click to toggle source

Upload a part for a multipart upload

@param bucket_name [String] Name of bucket to add part to @param object_name [String] Name of object to add part to @param upload_id [String] Id of upload to add part to @param part_number [String] Index of part in upload @param data [File||String] Content for part

@see help.aliyun.com/document_detail/31993.html

# File lib/fog/aliyun/requests/storage/upload_part.rb, line 16
def upload_part(bucket_name, object_name, upload_id, part_number, data)
  @oss_protocol.upload_part(bucket_name, object_name, upload_id, part_number) do |sw|
      sw.write(data)
  end
end

Private Instance Methods

parse_xml(content) click to toggle source
# File lib/fog/aliyun/requests/storage/get_bucket_location.rb, line 23
def parse_xml(content)
  doc = Nokogiri::XML(content) do |config|
    config.options |= Nokogiri::XML::ParseOptions::NOBLANKS
  end

  doc
end