Created
May 18, 2012 06:57
-
-
Save gccyugi/2723675 to your computer and use it in GitHub Desktop.
upyun-ruby-api
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# | |
# :author yugi | |
# :email [email protected] | |
# :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