qiniu-s3 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ *.swp
4
+ .DS_Store
5
+ .bundle
6
+ .config
7
+ .yardoc
8
+ Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour -f nested
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in qiniu-s3.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 why404
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,38 @@
1
+ # 关于
2
+
3
+ 此 Ruby SDK 适用于 Ruby 1.8.x, 1.9.x 版本,基于 [七牛云存储官方API](http://docs.qiniutek.com/v1/api/) 构建。使用此 SDK 构建您的网络应用程序,能让您以非常便捷地方式将数据安全地存储到七牛云存储上。无论您的网络应用是一个网站程序,还是包括从云端(服务端程序)到终端(手持设备应用)的架构的服务或应用,通过七牛云存储及其 SDK,都能让您应用程序的终端用户高速上传和下载,同时也让您的服务端更加轻盈。
4
+
5
+ ## 安装
6
+
7
+ 在您 Ruby 应用程序的 `Gemfile` 文件中,添加如下一行代码:
8
+
9
+ gem 'qiniu-s3'
10
+
11
+ 然后,在应用程序所在的目录下,可以运行 `bundle` 安装依赖包:
12
+
13
+ $ bundle
14
+
15
+ 或者,可以使用 Ruby 的包管理器 `gem` 进行安装:
16
+
17
+ $ gem install qiniu-s3
18
+
19
+ ## 使用
20
+
21
+ 参考文档:[七牛云存储 Ruby SDK 使用指南](http://docs.qiniutek.com/v1/sdk/ruby/)
22
+
23
+ ## 贡献代码
24
+
25
+ 1. Fork
26
+ 2. 创建您的特性分支 (`git checkout -b my-new-feature`)
27
+ 3. 提交您的改动 (`git commit -am 'Added some feature'`)
28
+ 4. 将您的修改记录提交到远程 `git` 仓库 (`git push origin my-new-feature`)
29
+ 5. 然后到 github 网站的该 `git` 远程仓库的 `my-new-feature` 分支下发起 Pull Request
30
+
31
+ ## 许可证
32
+
33
+ Copyright (c) 2012 why404
34
+
35
+ 基于 MIT 协议发布:
36
+
37
+ * [www.opensource.org/licenses/MIT](http://www.opensource.org/licenses/MIT)
38
+
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,2 @@
1
+ # More logical way to require 'qiniu-s3'
2
+ require File.join(File.dirname(__FILE__), 'qiniu', 's3')
@@ -0,0 +1,114 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'qiniu/s3/version'
4
+
5
+ module Qiniu
6
+ module S3
7
+ autoload :Config, 'qiniu/s3/config'
8
+ autoload :Log, 'qiniu/s3/log'
9
+ autoload :Exception, 'qiniu/s3/exceptions'
10
+ autoload :Utils, 'qiniu/s3/utils'
11
+ autoload :Auth, 'qiniu/s3/auth'
12
+ autoload :IO, 'qiniu/s3/io'
13
+ autoload :RS, 'qiniu/s3/rs'
14
+ autoload :Image, 'qiniu/s3/image'
15
+
16
+ class << self
17
+
18
+ StatusOK = 200
19
+
20
+ def establish_connection!(opts = {})
21
+ Config.initialize_connect opts
22
+ end
23
+
24
+ def login!(user, pwd)
25
+ code, data = Auth.exchange_by_password!(user, pwd)
26
+ code == StatusOK
27
+ end
28
+
29
+ def put_auth(expires_in = nil, callback_url = nil)
30
+ code, data = IO.put_auth(expires_in, callback_url)
31
+ code == StatusOK ? data["url"] : false
32
+ end
33
+
34
+ def upload(url, local_file, bucket = '', key = '', mime_type = '', custom_meta = '', callback_params = {})
35
+ code, data = IO.put_file(url, local_file, bucket, key, mime_type, custom_meta, callback_params)
36
+ code == StatusOK
37
+ end
38
+
39
+ def stat(bucket, key)
40
+ code, data = RS.stat(bucket, key)
41
+ code == StatusOK ? data : false
42
+ end
43
+
44
+ def get(bucket, key, save_as = nil, expires_in = nil, version = nil)
45
+ code, data = RS.get(bucket, key, save_as, expires_in, version)
46
+ code == StatusOK ? data : false
47
+ end
48
+
49
+ def download(bucket, key, save_as = nil, expires_in = nil, version = nil)
50
+ code, data = RS.get(bucket, key, save_as, expires_in, version)
51
+ code == StatusOK ? data["url"] : false
52
+ end
53
+
54
+ def delete(bucket, key)
55
+ code, data = RS.delete(bucket, key)
56
+ code == StatusOK
57
+ end
58
+
59
+ def batch(command, bucket, keys)
60
+ code, data = RS.batch(command, bucket, keys)
61
+ code == StatusOK ? data : false
62
+ end
63
+
64
+ def batch_stat(bucket, keys)
65
+ code, data = RS.batch_stat(bucket, keys)
66
+ code == StatusOK ? data : false
67
+ end
68
+
69
+ def batch_get(bucket, keys)
70
+ code, data = RS.batch_get(bucket, keys)
71
+ code == StatusOK ? data : false
72
+ end
73
+
74
+ def batch_download(bucket, keys)
75
+ code, data = RS.batch_get(bucket, keys)
76
+ return false unless code == StatusOK
77
+ links = []
78
+ data.each { |e| links << e["data"]["url"] }
79
+ links
80
+ end
81
+
82
+ def batch_delete(bucket, keys)
83
+ code, data = RS.batch_delete(bucket, keys)
84
+ code == StatusOK ? data : false
85
+ end
86
+
87
+ def publish(domain, bucket)
88
+ code, data = RS.publish(domain, bucket)
89
+ code == StatusOK
90
+ end
91
+
92
+ def unpublish(domain)
93
+ code, data = RS.unpublish(domain)
94
+ code == StatusOK
95
+ end
96
+
97
+ def drop(bucket)
98
+ code, data = RS.drop(bucket)
99
+ code == StatusOK
100
+ end
101
+
102
+ def image_info(url)
103
+ code, data = Image.info(url)
104
+ code == StatusOK ? data : false
105
+ end
106
+
107
+ def image_preview_url(url, spec)
108
+ Image.preivew_url(url, spec)
109
+ end
110
+
111
+ end
112
+
113
+ end
114
+ end
@@ -0,0 +1,74 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'qiniu/s3/exceptions'
4
+
5
+ module Qiniu
6
+ module S3
7
+ module Auth
8
+ class << self
9
+ include Utils
10
+
11
+ def exchange_by_password!(username, password)
12
+ @username = username
13
+ @password = password
14
+ post_data = {
15
+ :client_id => Config.settings[:client_id],
16
+ :grant_type => "password",
17
+ :username => username,
18
+ :password => password
19
+ }
20
+ code, data = http_request Config.settings[:auth_url], post_data
21
+ reset_token(data["access_token"], data["refresh_token"]) if code == 200
22
+ [code, data]
23
+ end
24
+
25
+ def exchange_by_refresh_token!(refresh_token)
26
+ post_data = {
27
+ :client_id => Config.settings[:client_id],
28
+ :grant_type => "refresh_token",
29
+ :refresh_token => refresh_token
30
+ }
31
+ code, data = http_request Config.settings[:auth_url], post_data
32
+ reset_token(data["access_token"], data["refresh_token"]) if code == 200
33
+ [code, data]
34
+ end
35
+
36
+ def reset_token(access_token, refresh_token)
37
+ @access_token = access_token
38
+ @refresh_token = refresh_token
39
+ end
40
+
41
+ def call(url, data, retry_times = 0)
42
+ raise MissingAccessToken if @access_token.nil?
43
+ code, data = http_request url, data, {:access_token => @access_token}
44
+ if code == 401
45
+ raise MissingRefreshToken if @refresh_token.nil?
46
+ code, data = exchange_by_refresh_token!(@refresh_token)
47
+ if code == 401
48
+ raise MissingUsernameOrPassword if (@username.nil? || @password.nil?)
49
+ code, data = exchange_by_password!(@username, @password)
50
+ end
51
+ if code == 200
52
+ retry_times += 1
53
+ if Config.settings[:auto_reconnect] && retry_times < Config.settings[:max_retry_times]
54
+ return call(url, data, retry_times)
55
+ end
56
+ end
57
+ end
58
+ [code, data]
59
+ end
60
+
61
+ def request(url, data = nil)
62
+ begin
63
+ code, data = Auth.call(url, data)
64
+ rescue [MissingAccessToken, MissingRefreshToken, MissingUsernameOrPassword] => e
65
+ Log.logger.error e
66
+ code, data = 401, {}
67
+ end
68
+ [code, data]
69
+ end
70
+
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,54 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # USAGE WAY 1:
4
+ # Qbox::Config.initialize_connect :client_id => "<ClientID>",
5
+ # :client_secret => "<ClientSecret>"
6
+ #
7
+ # USAGE WAY 2:
8
+ # Qbox::Config.load "path/to/your_project/config/qiniu.yml"
9
+ #
10
+
11
+ require "qiniu/s3/version"
12
+
13
+ module Qiniu
14
+ module S3
15
+ module Config
16
+ class << self
17
+
18
+ DEFAULT_OPTIONS = {
19
+ :user_agent => 'Qiniu-S3-Ruby-SDK-' + VERSION + '()',
20
+ :method => :post,
21
+ :content_type => 'application/x-www-form-urlencoded',
22
+ :auth_url => "https://acc.qbox.me/oauth2/token",
23
+ :rs_host => "http://rs.qbox.me:10100",
24
+ :io_host => "http://io.qbox.me",
25
+ :client_id => "<YOUR_APP_CLIENT_ID>",
26
+ :client_secret => "<YOUR_APP_CLIENT_SECRET>",
27
+ :auto_reconnect => true,
28
+ :max_retry_times => 5
29
+ }
30
+
31
+ REQUIRED_OPTION_KEYS = [:client_id, :client_secret, :auth_url, :rs_host, :io_host]
32
+
33
+ attr_reader :settings, :default_params
34
+
35
+ def load config_file
36
+ if File.exist?(config_file)
37
+ config_options = YAML.load_file(config_file)
38
+ initialize_connect(config_options)
39
+ else
40
+ raise MissingConfError, config_file
41
+ end
42
+ end
43
+
44
+ def initialize_connect options = {}
45
+ @settings = DEFAULT_OPTIONS.merge(options)
46
+ REQUIRED_OPTION_KEYS.each do |opt|
47
+ raise MissingArgsError, [opt] unless @settings.has_key?(opt)
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,88 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Qiniu
4
+ module S3
5
+
6
+ class Exception < RuntimeError
7
+ def to_s
8
+ inspect
9
+ end
10
+ end
11
+
12
+ class ResponseError < Exception
13
+ attr_reader :response
14
+
15
+ def initialize(message, response = nil)
16
+ @response = response
17
+ super(message)
18
+ end
19
+
20
+ def http_code
21
+ @response.code.to_i if @response
22
+ end
23
+
24
+ def http_body
25
+ @response.body if @response
26
+ end
27
+
28
+ def inspect
29
+ "#{message}: #{http_body}"
30
+ end
31
+ end
32
+
33
+ class RequestFailed < ResponseError
34
+ def message
35
+ "HTTP status code #{http_code}"
36
+ end
37
+
38
+ def to_s
39
+ message
40
+ end
41
+ end
42
+
43
+ class MissingArgsError < Exception
44
+ def initialize(missing_keys)
45
+ key_list = missing_keys.map {|key| key.to_s}.join(' and the ')
46
+ super("You did not provide both required args. Please provide the #{key_list}.")
47
+ end
48
+ end
49
+
50
+ class MissingAccessToken < MissingArgsError
51
+ def initialize
52
+ super([:access_token])
53
+ end
54
+ end
55
+
56
+ class MissingRefreshToken < MissingArgsError
57
+ def initialize
58
+ super([:refresh_token])
59
+ end
60
+ end
61
+
62
+ class MissingUsernameOrPassword < MissingArgsError
63
+ def initialize
64
+ super([:username, :password])
65
+ end
66
+ end
67
+
68
+ class InvalidArgsError < Exception
69
+ def initialize(invalid_keys)
70
+ key_list = invalid_keys.map {|key| key.to_s}.join(' and the ')
71
+ super("#{key_list} should not be empty.")
72
+ end
73
+ end
74
+
75
+ class MissingConfError < Exception
76
+ def initialize(missing_conf_file)
77
+ super("Error, missing #{missing_conf_file}. You must have #{missing_conf_file} to configure your client id and secret.")
78
+ end
79
+ end
80
+
81
+ class NoSuchFileError < Exception
82
+ def initialize(missing_file)
83
+ super("Error, no such file #{missing_file}.")
84
+ end
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Qiniu
4
+ module S3
5
+ module Image
6
+ class << self
7
+ include Utils
8
+
9
+ def info(url)
10
+ Utils.http_request url + '/imageInfo', nil, {:method => :get}
11
+ end
12
+
13
+ def preivew_url(url, spec)
14
+ url + '/imagePreview/' + spec.to_s
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end