class Aliyun::Connection

Attributes

aliyun_alias_host[R]

The alias host

aliyun_external_host[R]

The external host

aliyun_internal_host[R]

The internal host

aliyun_protocol[R]
aliyun_protocol_relative_url[R]
aliyun_upload_host[R]

The upload host according to the connection configurations

Public Class Methods

new(options = {}) click to toggle source

Initialize the OSS connection

@param [Hash] An options to specify connection details @option access_id [String] used to set “Authorization” request header @option access_key [String] the access key @option bucket [String] bucket used to access @option data_center [String] available data center name, e.g. 'cn-hangzhou' @option internal [true, false] if the service should be accessed through internal network @option host_alias [String] the alias of the host, such as the CDN domain name @option protocol [String] 'http' or 'https', default to 'http' @option protocol_relative_url [true, false] if to use protocol relative url, en.wikipedia.org/wiki/Wikipedia:Protocol-relative_URL @note both access_id and acces_key are related to authorization algorithm:

https://docs.aliyun.com/#/pub/oss/api-reference/access-control&signature-header
# File lib/aliyun/connection.rb, line 38
def initialize(options = {})
  @aliyun_access_id = options[:access_id]
  @aliyun_access_key = options[:access_key]
  @aliyun_bucket = options[:bucket]
  @aliyun_protocol_relative_url = !!options[:protocol_relative_url]
  @aliyun_protocol = options[:protocol] || 'http'

  @aliyun_upload_host = "#{@aliyun_bucket}.#{get_endpoint(options)}"
  @aliyun_internal_host = "#{@aliyun_bucket}.#{get_endpoint(options.merge(internal: true))}"
  @aliyun_external_host = "#{@aliyun_bucket}.#{get_endpoint(options.merge(internal: false))}"
  @aliyun_alias_host = options[:host_alias] || @aliyun_upload_host
end

Public Instance Methods

delete(path) click to toggle source

Delete a file from the OSS docs.aliyun.com/#/pub/oss/api-reference/object&DeleteObject

@param path [String] the path to retrieve the file on remote storage @return [String] the expired url to the file, if the file deleted successfully @return [nil] if the delete operation failed

# File lib/aliyun/connection.rb, line 122
def delete(path)
  path = format_path(path)
  bucket_path = get_bucket_path(path)
  date = gmtdate
  headers = {
    'Host' => @aliyun_upload_host,
    'Date' => date,
    'Authorization' => sign('DELETE', bucket_path, '', '', date)
  }
  url = path_to_url(path)
  response = RestClient.delete(url, headers)
  response.code == 204 ? url : nil
end
exists?(path) click to toggle source

Determine if the file exists on the OSS docs.aliyun.com/#/pub/oss/api-reference/object&HeadObject

@param path [String] the path to retrieve the file on remote storage @return [true] if file exists @return [false] if file could not be found

# File lib/aliyun/connection.rb, line 161
def exists?(path)
  head(path).empty? ? false : true
end
format_path(path) click to toggle source

remove leading slashes in the path

@param path [String] the path to retrieve the file on remote storage @return [String] the new string after removing leading slashed

# File lib/aliyun/connection.rb, line 177
def format_path(path)
  path.blank? ? '' : path.gsub(%r{^/+}, '')
end
get(path) click to toggle source

Download the file from OSS docs.aliyun.com/#/pub/oss/api-reference/object&GetObject

@param path [String] the path to retrieve the file on remote storage @return [?] the file content consist of bytes

# File lib/aliyun/connection.rb, line 141
def get(path)
  path = format_path(path)
  bucket_path = get_bucket_path(path)
  date = gmtdate
  headers = {
    'Host' => @aliyun_upload_host,
    'Date' => date,
    'Authorization' => sign('GET', bucket_path, '', '', date)
  }
  url = path_to_url(path)
  response = RestClient.get(url, headers)
  response.body
end
get_bucket_path(path) click to toggle source

A path consis of the bucket name and file name docs.aliyun.com/#/pub/oss/api-reference/access-control&signature-header

@param path [String] the path to retrieve the file on remote storage @return [String] the expected bucket path, e.g. “test-bucket/oss-api.pdf”

# File lib/aliyun/connection.rb, line 186
def get_bucket_path(path)
  [@aliyun_bucket, path].join('/')
end
gmtdate() click to toggle source

The GMT format time referenced from HTTP 1.1 docs.aliyun.com/#/pub/oss/api-reference/public-header

@return [String] a string represents the formated time, e.g. “Wed, 05 Sep. 2012 23:00:00 GMT”

# File lib/aliyun/connection.rb, line 169
def gmtdate
  Time.now.gmtime.strftime('%a, %d %b %Y %H:%M:%S GMT')
end
head(path) click to toggle source

Return the meta informations for a file specified by the path docs.aliyun.com/#/pub/oss/api-reference/object&HeadObject

@param path [String] the path of file storaged in Aliyun OSS @return [Hash] the meta data of the file @note the example headers will be like:

{
 {:date=>"Sun, 02 Aug 2015 02:42:45 GMT",
 :content_type=>"image/jpg",
 :content_length=>"125198",
 :connection=>"close",
 :accept_ranges=>"bytes",
 :etag=>"\"336262A42E5B99AFF5B8BC66611FC156\"",
 :last_modified=>"Sun, 01 Dec 2013 16:39:57 GMT",
 :server=>"AliyunOSS",
 :x_oss_object_type=>"Normal",
 :x_oss_request_id=>"55BD83A5D4C05BDFF4A329E0"}}
# File lib/aliyun/connection.rb, line 70
def head(path)
  path = format_path(path)
  bucket_path = get_bucket_path(path)
  date = gmtdate
  headers = {
    'Host' => @aliyun_upload_host,
    'Date' => date,
    'Authorization' => sign('HEAD', bucket_path, '', '', date)
  }
  url = path_to_url(path)
  RestClient.head(url, headers).headers
rescue RestClient::ResourceNotFound
  {}
end
path_to_url(path) click to toggle source

The full path contains host name to the file

@param path [String] the path to retrieve the file on remote storage @return [String] the expected full path, e.g. “martin-test.oss-cn-hangzhou.aliyuncs.com/oss-api.pdf

# File lib/aliyun/connection.rb, line 194
def path_to_url(path)
  URI.encode(path =~ %r{^https?://} ? path : "http://#{aliyun_upload_host}/#{path}")
end
put(path, file, options = {}) click to toggle source

Upload File to Aliyun OSS docs.aliyun.com/#/pub/oss/api-reference/object&PutObject

@param path [String] the target storing path on the oss @param file [File] an instance of File represents a file to be uploaded @param options [Hash]

- content_type - MimeType value for the file, default is "image/jpg"

@return [String] The downloadable url of the uploaded file @return [nil] if the uploading failed

# File lib/aliyun/connection.rb, line 95
def put(path, file, options = {})
  path = format_path(path)
  bucket_path = get_bucket_path(path)
  content_md5 = Digest::MD5.file(file).base64digest
  content_type = options[:content_type] || 'image/jpg'
  date = gmtdate
  url = path_to_url(path)
  auth_sign = sign('PUT', bucket_path, content_md5, content_type, date)
  headers = {
    'Authorization' => auth_sign,
    'Content-Md5' => content_md5,
    'Content-Type' => content_type,
    'Content-Length' => file.size,
    'Date' => date,
    'Host' => @aliyun_upload_host,
    'Expect' => '100-Continue'
  }
  response = RestClient.put(url, file, headers)
  response.code == 200 ? path_to_url(path) : nil
end

Private Instance Methods

sign(verb, path, content_md5, content_type, date) click to toggle source

The signature algorithm docs.aliyun.com/#/pub/oss/api-reference/access-control&signature-header

@param verb [String] the request verb, e.g. “GET” or “DELETE” @param content_md5 [String] the md5 value for the content to be uploaded @param content_type [String] the content type of the file, e.g. “application/pdf” @param date [String] the GMT formatted date string

# File lib/aliyun/connection.rb, line 207
def sign(verb, path, content_md5, content_type, date)
  canonicalized_oss_headers = ''
  canonicalized_resource = "/#{path}"
  string_to_sign = [
    verb, content_md5, content_type, date,
    canonicalized_oss_headers + canonicalized_resource
  ].join("\n")
  digest = OpenSSL::Digest.new('sha1')
  h = OpenSSL::HMAC.digest(digest, @aliyun_access_key, string_to_sign)
  "OSS #{@aliyun_access_id}:#{Base64.encode64(h)}"
end