Skip to content

Instantly share code, notes, and snippets.

@gccyugi
Created May 18, 2012 06:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gccyugi/2723675 to your computer and use it in GitHub Desktop.
Save gccyugi/2723675 to your computer and use it in GitHub Desktop.
upyun-ruby-api
# -*- coding: utf-8 -*-
#
# :author yugi
# :email gccyugi@gmail.com
# :update 2012/5/18 14:56
module UpyunHttpMixin
def md5(s)
require 'digest/md5'
Digest::MD5.hexdigest(s)
end
def basic_auth(headers, username, password)
require 'base64'
data = Base64.strict_encode64(username + ':' + password)
headers['Authorization'] = 'Basic ' + data
end
def upyun_auth(headers, method, path, username, password)
date = Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
content_length = headers['Content-Length'] || 0
sign = "#{method}&#{path}&#{date}&#{content_length}&#{md5(password)}"
headers['Date'] = date
headers['Authorization'] = "UpYun #{username}:#{md5(sign)}"
end
def res_ok?(res)
res.code == '200'
end
def res_errmsg(res)
"#{res.code} #{res.message} #{res.class.name}"
end
def request(method, path, data=nil, options={})
require 'net/http'
require 'uri'
uri = URI.parse(path)
headers = {}.merge(options)
if @auth_type == :basic
basic_auth(headers, @username, @password)
else
upyun_auth(headers, method, uri.path, @username, @password)
end
Net::HTTP.start(uri.host, uri.port) do |http|
if method == 'HEAD'
return http.head(uri.request_uri, headers)
else
return http.send_request(method, uri.request_uri, data, headers)
end
end
end
end
class Upyun
attr_accessor :bucketname, :username, :password
attr_accessor :api_domain, :auth_type
include UpyunHttpMixin
def initialize(bucketname, username, password,
api_domain='http://v0.api.upyun.com',
auth_type=:upyun)
@bucketname = bucketname
@username = username
@password = password
@api_domain = api_domain
@auth_type = auth_type
end
def usage(path='/')
res = request('GET', _generate_path(path) + '?usage')
res_ok?(res) ? res.body : [nil, res_errmsg(res)]
end
def ls(path='/')
res = request('GET', _generate_path(path))
if res_ok?(res)
files = res.body.split("\n").map do |line|
name, type, size, timestamp = line.split("\t")
{
:name => name,
:is_folder => type == 'N',
:size => size.to_i,
:timestamp => timestamp.to_i,
}
end
return files
end
[nil, res_errmsg(res)]
end
def touch(path, data, md5_checksum=nil, auto_mkdir=false)
options = {}
options['Content-MD5'] = md5_checksum if md5_checksum
options['mkdir'] = 'true' if auto_mkdir
options['Content-Length'] = data.size.to_s
res = request('PUT', _generate_path(path), data, options)
res_ok?(res)
end
def touch_image(path, data, secret_code=nil,
md5_checksum=nil, auto_mkdir=false)
options = {}
options['Content-Secret'] = secret_code if secret_code
options['Content-MD5'] = md5_checksum if md5_checksum
options['mkdir'] = 'true' if auto_mkdir
options['Content-Length'] = data.size.to_s
res = request('PUT', _generate_path(path), data, options)
if res_ok?(res)
return {
:is_folder => res['x-upyun-file-type'] != 'file',
:width => res['x-upyun-width'].to_i,
:height => res['x-upyun-height'].to_i,
:frames => res['x-upyun-frames'].to_i
}
end
res_errmsg(res)
end
def cat(path)
res = request('GET', _generate_path(path))
res_ok?(res) ? res.body : [nil, res_errmsg(res)]
end
def stat(path)
res = request('HEAD', _generate_path(path))
if res_ok?(res)
return {
:is_folder => res['x-upyun-file-type'] != 'file',
:size => res['x-upyun-file-size'].to_i,
:timestamp => res['x-upyun-file-date'].to_i
}
end
res_errmsg(res)
end
def mkdir(path, auto_mkdir=false)
options = {'folder' => 'create'}
options['mkdir'] = 'true' if auto_mkdir
res = request('POST', _generate_path(path), nil, options)
res_ok?(res)
end
def rmdir(path)
rm(path)
end
def rm(path)
res = request('DELETE', _generate_path(path))
res_ok?(res)
end
def _generate_path(filename=nil)
path = "#{@api_domain}/#{@bucketname}"
filename ? path + filename : path
end
end
=begin
s = Upyun.new('<bucket-name>', '<operator-name>', '<operator-pwd>')
# usage
rc, errmsg = s.usage
puts "usage: #{rc}" if rc
# mkdir
puts s.mkdir('/tmp')
puts s.mkdir('/tmp/1/2', true)
s.ls.each { |e| puts e }
# rmdir
puts s.rmdir('/tmp/1/2')
puts s.rmdir('/tmp/1')
puts s.rmdir('/tmp')
# touch
puts s.touch('/a.txt', 'hijcak')
# cat
rc, errmsg = s.cat('/a.txt')
puts "data of a.txt is: #{rc}" if rc
# stat
rc, errmsg = s.stat('/a.txt')
puts rc if rc
# rm
puts s.rm('/a.txt')
#ls
s.ls.each { |e| puts e }
=end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment