qiniu_jxb 6.2.4
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.
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +118 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +37 -0
- data/LICENSE +22 -0
- data/README.md +47 -0
- data/Rakefile +21 -0
- data/docs/README.md +790 -0
- data/lib/qiniu-rs.rb +2 -0
- data/lib/qiniu.rb +209 -0
- data/lib/qiniu/abstract.rb +22 -0
- data/lib/qiniu/adt.rb +46 -0
- data/lib/qiniu/auth.rb +234 -0
- data/lib/qiniu/config.rb +58 -0
- data/lib/qiniu/exceptions.rb +120 -0
- data/lib/qiniu/fop.rb +4 -0
- data/lib/qiniu/http.rb +137 -0
- data/lib/qiniu/image.rb +38 -0
- data/lib/qiniu/log.rb +15 -0
- data/lib/qiniu/management.rb +128 -0
- data/lib/qiniu/misc.rb +33 -0
- data/lib/qiniu/pfop.rb +124 -0
- data/lib/qiniu/resumable_upload.rb +319 -0
- data/lib/qiniu/storage.rb +5 -0
- data/lib/qiniu/tokens/access_token.rb +21 -0
- data/lib/qiniu/tokens/download_token.rb +31 -0
- data/lib/qiniu/tokens/qbox_token.rb +38 -0
- data/lib/qiniu/tokens/upload_token.rb +47 -0
- data/lib/qiniu/upload.rb +138 -0
- data/lib/qiniu/utils.rb +109 -0
- data/lib/qiniu/version.rb +17 -0
- data/qiniu.gemspec +29 -0
- data/spec/qiniu/abstract_spec.rb +30 -0
- data/spec/qiniu/auth_spec.rb +81 -0
- data/spec/qiniu/image_logo_for_test.png +0 -0
- data/spec/qiniu/image_spec.rb +89 -0
- data/spec/qiniu/management_spec.rb +156 -0
- data/spec/qiniu/misc_spec.rb +59 -0
- data/spec/qiniu/pfop_spec.rb +89 -0
- data/spec/qiniu/qiniu_spec.rb +329 -0
- data/spec/qiniu/tokens/qbox_token_spec.rb +29 -0
- data/spec/qiniu/upload_spec.rb +308 -0
- data/spec/qiniu/utils_spec.rb +49 -0
- data/spec/qiniu/version_spec.rb +10 -0
- data/spec/spec_helper.rb +19 -0
- metadata +220 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'hmac-sha1'
|
4
|
+
require 'qiniu/config'
|
5
|
+
require 'qiniu/utils'
|
6
|
+
|
7
|
+
module Qiniu
|
8
|
+
class AccessToken
|
9
|
+
|
10
|
+
include Utils
|
11
|
+
|
12
|
+
attr_accessor :access_key, :secret_key
|
13
|
+
|
14
|
+
def generate_encoded_digest(signature)
|
15
|
+
hmac = HMAC::SHA1.new(@secret_key)
|
16
|
+
hmac.update(signature)
|
17
|
+
urlsafe_base64_encode(hmac.digest)
|
18
|
+
end
|
19
|
+
|
20
|
+
end # AccessToken
|
21
|
+
end # module Qiniu
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'qiniu/tokens/access_token'
|
5
|
+
require 'qiniu/utils'
|
6
|
+
|
7
|
+
module Qiniu
|
8
|
+
class DownloadToken < AccessToken
|
9
|
+
|
10
|
+
include Utils
|
11
|
+
|
12
|
+
attr_accessor :pattern, :expires_in
|
13
|
+
|
14
|
+
def initialize(opts = {})
|
15
|
+
@pattern = opts[:pattern]
|
16
|
+
@expires_in = opts[:expires_in] || 3600
|
17
|
+
end
|
18
|
+
|
19
|
+
def generate_signature
|
20
|
+
params = {"S" => @pattern, "E" => Time.now.to_i + @expires_in}
|
21
|
+
Utils.urlsafe_base64_encode(params.to_json)
|
22
|
+
end
|
23
|
+
|
24
|
+
def generate_token
|
25
|
+
signature = generate_signature
|
26
|
+
encoded_digest = generate_encoded_digest(signature)
|
27
|
+
%Q(#{@access_key}:#{encoded_digest}:#{signature})
|
28
|
+
end
|
29
|
+
|
30
|
+
end # moidule DownloadToken
|
31
|
+
end # module Qiniu
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'cgi'
|
4
|
+
require 'json'
|
5
|
+
require 'qiniu/tokens/access_token'
|
6
|
+
|
7
|
+
module Qiniu
|
8
|
+
class QboxToken < AccessToken
|
9
|
+
|
10
|
+
include Utils
|
11
|
+
|
12
|
+
attr_accessor :url, :params
|
13
|
+
|
14
|
+
def initialize(opts = {})
|
15
|
+
@url = opts[:url]
|
16
|
+
@params = opts[:params]
|
17
|
+
end
|
18
|
+
|
19
|
+
def generate_signature
|
20
|
+
uri = URI.parse(@url)
|
21
|
+
signature = uri.path
|
22
|
+
query_string = uri.query
|
23
|
+
signature += '?' + query_string if !query_string.nil? && !query_string.empty?
|
24
|
+
signature += "\n"
|
25
|
+
if @params.is_a?(Hash)
|
26
|
+
params_string = HTTP.generate_query_string(@params)
|
27
|
+
signature += params_string
|
28
|
+
end
|
29
|
+
signature
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate_token
|
33
|
+
encoded_digest = generate_encoded_digest(generate_signature)
|
34
|
+
%Q(#{@access_key}:#{encoded_digest})
|
35
|
+
end
|
36
|
+
|
37
|
+
end # module QboxToken
|
38
|
+
end # module Qiniu
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'qiniu/tokens/access_token'
|
5
|
+
require 'qiniu/utils'
|
6
|
+
|
7
|
+
module Qiniu
|
8
|
+
class UploadToken < AccessToken
|
9
|
+
|
10
|
+
include Utils
|
11
|
+
|
12
|
+
attr_accessor :scope, :expires_in, :callback_url, :callback_body, :callback_body_type, :customer, :escape, :async_options, :return_body, :return_url
|
13
|
+
|
14
|
+
def initialize(opts = {})
|
15
|
+
@scope = opts[:scope]
|
16
|
+
@expires_in = opts[:expires_in] || 3600
|
17
|
+
@callback_url = opts[:callback_url]
|
18
|
+
@callback_body = opts[:callback_body]
|
19
|
+
@callback_body_type = opts[:callback_body_type]
|
20
|
+
@customer = opts[:customer]
|
21
|
+
@escape = opts[:escape]
|
22
|
+
@async_options = opts[:async_options]
|
23
|
+
@return_body = opts[:return_body]
|
24
|
+
@return_url = opts[:return_url]
|
25
|
+
end
|
26
|
+
|
27
|
+
def generate_signature
|
28
|
+
params = {:scope => @scope, :deadline => Time.now.to_i + @expires_in}
|
29
|
+
params[:callbackUrl] = @callback_url if !@callback_url.nil? && !@callback_url.empty?
|
30
|
+
params[:callbackBody] = @callback_body if !@callback_body.nil? && !@callback_body.empty?
|
31
|
+
params[:callbackBodyType] = @callback_body_type if !@callback_body_type.nil? && !@callback_body_type.empty?
|
32
|
+
params[:customer] = @customer if !@customer.nil? && !@customer.empty?
|
33
|
+
params[:escape] = 1 if @escape == 1 || @escape == true
|
34
|
+
params[:asyncOps] = @async_options if !@async_options.nil? && !@async_options.empty?
|
35
|
+
params[:returnBody] = @return_body if !@return_body.nil? && !@return_body.empty?
|
36
|
+
params[:returnUrl] = @return_url if !@return_url.nil? && !@return_url.empty?
|
37
|
+
Utils.urlsafe_base64_encode(params.to_json)
|
38
|
+
end
|
39
|
+
|
40
|
+
def generate_token
|
41
|
+
signature = generate_signature
|
42
|
+
encoded_digest = generate_encoded_digest(signature)
|
43
|
+
%Q(#{@access_key}:#{encoded_digest}:#{signature})
|
44
|
+
end
|
45
|
+
|
46
|
+
end # module UploadToken
|
47
|
+
end # module Qiniu
|
data/lib/qiniu/upload.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# vim: sw=2 ts=2
|
3
|
+
|
4
|
+
module Qiniu
|
5
|
+
module Storage
|
6
|
+
class << self
|
7
|
+
include Utils
|
8
|
+
|
9
|
+
def upload_with_token(uptoken,
|
10
|
+
local_file,
|
11
|
+
bucket,
|
12
|
+
key = nil,
|
13
|
+
mime_type = nil,
|
14
|
+
custom_meta = nil,
|
15
|
+
callback_params = nil,
|
16
|
+
enable_crc32_check = false,
|
17
|
+
rotate = nil)
|
18
|
+
action_params = _generate_action_params(
|
19
|
+
local_file,
|
20
|
+
bucket,
|
21
|
+
key,
|
22
|
+
mime_type,
|
23
|
+
custom_meta,
|
24
|
+
enable_crc32_check,
|
25
|
+
rotate
|
26
|
+
)
|
27
|
+
|
28
|
+
if callback_params.nil?
|
29
|
+
callback_params = {:bucket => bucket, :key => key, :mime_type => mime_type}
|
30
|
+
end
|
31
|
+
callback_query_string = HTTP.generate_query_string(callback_params)
|
32
|
+
|
33
|
+
url = Config.settings[:up_host] + '/upload'
|
34
|
+
post_data = {
|
35
|
+
:params => callback_query_string,
|
36
|
+
:action => action_params,
|
37
|
+
:file => File.new(local_file, 'rb'),
|
38
|
+
:multipart => true
|
39
|
+
}
|
40
|
+
if !uptoken.nil? then
|
41
|
+
post_data[:auth] = uptoken unless uptoken.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
return HTTP.api_post(url, post_data)
|
45
|
+
end # upload_with_token
|
46
|
+
|
47
|
+
def upload_with_token_2(uptoken,
|
48
|
+
local_file,
|
49
|
+
key = nil,
|
50
|
+
x_vars = nil, opts={})
|
51
|
+
### 构造URL
|
52
|
+
url = Config.settings[:up_host]
|
53
|
+
url[/\/*$/] = ''
|
54
|
+
url += '/'
|
55
|
+
|
56
|
+
### 构造HTTP Body
|
57
|
+
if local_file.is_a?(String)
|
58
|
+
tmp = Tempfile.new('foo')
|
59
|
+
tmp.write(local_file)
|
60
|
+
tmp.close
|
61
|
+
local_file = tmp
|
62
|
+
end
|
63
|
+
file = File.new(local_file, 'rb')
|
64
|
+
if not opts[:content_type].nil?
|
65
|
+
file.define_singleton_method("content_type") do
|
66
|
+
opts[:content_type]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
post_data = {
|
71
|
+
:file => file,
|
72
|
+
:multipart => true,
|
73
|
+
}
|
74
|
+
if not uptoken.nil?
|
75
|
+
post_data[:token] = uptoken
|
76
|
+
end
|
77
|
+
if not key.nil?
|
78
|
+
post_data[:key] = key
|
79
|
+
end
|
80
|
+
if x_vars.is_a?(Hash)
|
81
|
+
post_data.merge!(x_vars)
|
82
|
+
end
|
83
|
+
|
84
|
+
### 发送请求
|
85
|
+
HTTP.api_post(url, post_data)
|
86
|
+
end # upload_with_token_2
|
87
|
+
|
88
|
+
### 授权举例
|
89
|
+
# put_policy.bucket | put_policy.key | key | 语义 | 授权
|
90
|
+
# :---------------- | :------------- | :------ | :--- | :---
|
91
|
+
# trivial_bucket | <nil> | <nil> | 新增 | 允许,最终key为1)使用put_policy.save_key生成的值或2)资源内容的Hash值
|
92
|
+
# trivial_bucket | <nil> | foo.txt | 新增 | 允许
|
93
|
+
# trivial_bucket | <nil> | bar.jpg | 新增 | 允许
|
94
|
+
# trivial_bucket | foo.txt | <nil> | 覆盖 | 允许,由SDK将put_policy.key赋值给key实现
|
95
|
+
# trivial_bucket | foo.txt | foo.txt | 覆盖 | 允许
|
96
|
+
# trivial_bucket | foo.txt | bar.jpg | 覆盖 | 禁止,put_policy.key与key不一致
|
97
|
+
def upload_with_put_policy(put_policy,
|
98
|
+
local_file,
|
99
|
+
key = nil,
|
100
|
+
x_vars = nil, opts={})
|
101
|
+
uptoken = Auth.generate_uptoken(put_policy)
|
102
|
+
if key.nil? then
|
103
|
+
key = put_policy.key
|
104
|
+
end
|
105
|
+
|
106
|
+
return upload_with_token_2(uptoken, local_file, key, x_vars, opts)
|
107
|
+
end # upload_with_put_policy
|
108
|
+
|
109
|
+
private
|
110
|
+
def _generate_action_params(local_file,
|
111
|
+
bucket,
|
112
|
+
key = nil,
|
113
|
+
mime_type = nil,
|
114
|
+
custom_meta = nil,
|
115
|
+
enable_crc32_check = false,
|
116
|
+
rotate = nil)
|
117
|
+
raise NoSuchFileError, local_file unless File.exist?(local_file)
|
118
|
+
|
119
|
+
if key.nil?
|
120
|
+
key = Digest::SHA1.hexdigest(local_file + Time.now.to_s)
|
121
|
+
end
|
122
|
+
|
123
|
+
entry_uri = bucket + ':' + key
|
124
|
+
if mime_type.nil? || mime_type.empty?
|
125
|
+
mime = MIME::Types.type_for local_file
|
126
|
+
mime_type = mime.empty? ? 'application/octet-stream' : mime[0].content_type
|
127
|
+
end
|
128
|
+
|
129
|
+
action_params = '/rs-put/' + Utils.urlsafe_base64_encode(entry_uri) + '/mimeType/' + Utils.urlsafe_base64_encode(mime_type)
|
130
|
+
action_params += '/meta/' + Utils.urlsafe_base64_encode(custom_meta) unless custom_meta.nil?
|
131
|
+
action_params += '/crc32/' + Utils.crc32checksum(local_file).to_s if enable_crc32_check
|
132
|
+
action_params += '/rotate/' + rotate if !rotate.nil? && rotate.to_i >= 0
|
133
|
+
action_params
|
134
|
+
end # _generate_action_params
|
135
|
+
|
136
|
+
end # class << self
|
137
|
+
end # module Storage
|
138
|
+
end # module Qiniu
|
data/lib/qiniu/utils.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'cgi'
|
5
|
+
require 'json'
|
6
|
+
require 'zlib'
|
7
|
+
require 'base64'
|
8
|
+
require 'rest_client'
|
9
|
+
require 'hmac-sha1'
|
10
|
+
require 'qiniu/exceptions'
|
11
|
+
|
12
|
+
module Qiniu
|
13
|
+
module Utils extend self
|
14
|
+
|
15
|
+
def urlsafe_base64_encode content
|
16
|
+
Base64.encode64(content).strip.gsub('+', '-').gsub('/','_').gsub(/\r?\n/, '')
|
17
|
+
end
|
18
|
+
|
19
|
+
def urlsafe_base64_decode encoded_content
|
20
|
+
Base64.decode64 encoded_content.gsub('_','/').gsub('-', '+')
|
21
|
+
end
|
22
|
+
|
23
|
+
def encode_entry_uri(bucket, key)
|
24
|
+
entry_uri = bucket + ':' + key
|
25
|
+
urlsafe_base64_encode(entry_uri)
|
26
|
+
end
|
27
|
+
|
28
|
+
def safe_json_parse(data)
|
29
|
+
JSON.parse(data)
|
30
|
+
rescue JSON::ParserError
|
31
|
+
{}
|
32
|
+
end
|
33
|
+
|
34
|
+
def debug(msg)
|
35
|
+
if Config.settings[:enable_debug]
|
36
|
+
Log.logger.debug(msg)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
### 已过时,仅作为兼容接口保留
|
41
|
+
def send_request_with url, data = nil, options = {}
|
42
|
+
options[:method] = Config.settings[:method] unless options[:method]
|
43
|
+
options[:content_type] = Config.settings[:content_type] unless options[:content_type]
|
44
|
+
header_options = {
|
45
|
+
:accept => :json,
|
46
|
+
:user_agent => Config.settings[:user_agent]
|
47
|
+
}
|
48
|
+
auth_token = nil
|
49
|
+
if !options[:qbox_signature_token].nil? && !options[:qbox_signature_token].empty?
|
50
|
+
auth_token = 'QBox ' + options[:qbox_signature_token]
|
51
|
+
elsif !options[:upload_signature_token].nil? && !options[:upload_signature_token].empty?
|
52
|
+
auth_token = 'UpToken ' + options[:upload_signature_token]
|
53
|
+
elsif options[:access_token]
|
54
|
+
auth_token = 'Bearer ' + options[:access_token]
|
55
|
+
end
|
56
|
+
header_options.merge!('Authorization' => auth_token) unless auth_token.nil?
|
57
|
+
case options[:method]
|
58
|
+
when :get
|
59
|
+
response = RestClient.get(url, header_options)
|
60
|
+
when :post
|
61
|
+
header_options.merge!(:content_type => options[:content_type])
|
62
|
+
response = RestClient.post(url, data, header_options)
|
63
|
+
end
|
64
|
+
code = response.respond_to?(:code) ? response.code.to_i : 0
|
65
|
+
unless HTTP.is_response_ok?(code)
|
66
|
+
raise RequestFailed.new("Request Failed", response)
|
67
|
+
else
|
68
|
+
data = {}
|
69
|
+
body = response.respond_to?(:body) ? response.body : {}
|
70
|
+
raw_headers = response.respond_to?(:raw_headers) ? response.raw_headers : {}
|
71
|
+
data = safe_json_parse(body) unless body.empty?
|
72
|
+
end
|
73
|
+
[code, data, raw_headers]
|
74
|
+
end # send_request_with
|
75
|
+
|
76
|
+
### 已过时,仅作为兼容接口保留
|
77
|
+
def http_request url, data = nil, options = {}
|
78
|
+
retry_times = 0
|
79
|
+
begin
|
80
|
+
retry_times += 1
|
81
|
+
send_request_with url, data, options
|
82
|
+
rescue Errno::ECONNRESET => err
|
83
|
+
if Config.settings[:auto_reconnect] && retry_times < Config.settings[:max_retry_times]
|
84
|
+
retry
|
85
|
+
else
|
86
|
+
Log.logger.error err
|
87
|
+
end
|
88
|
+
rescue => e
|
89
|
+
Log.logger.warn "#{e.message} => Utils.http_request('#{url}')"
|
90
|
+
code = 0
|
91
|
+
data = {}
|
92
|
+
body = {}
|
93
|
+
if e.respond_to? :response
|
94
|
+
res = e.response
|
95
|
+
code = res.code.to_i if res.respond_to? :code
|
96
|
+
body = res.respond_to?(:body) ? res.body : ""
|
97
|
+
raw_headers = res.respond_to?(:raw_headers) ? res.raw_headers : {}
|
98
|
+
data = safe_json_parse(body) unless body.empty?
|
99
|
+
end
|
100
|
+
[code, data, raw_headers]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def crc32checksum(filepath)
|
105
|
+
File.open(filepath, "rb") { |f| Zlib.crc32 f.read }
|
106
|
+
end
|
107
|
+
|
108
|
+
end # module Utils
|
109
|
+
end # module Qiniu
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Qiniu
|
4
|
+
module Version
|
5
|
+
MAJOR = 6
|
6
|
+
MINOR = 2
|
7
|
+
PATCH = 4
|
8
|
+
# Returns a version string by joining <tt>MAJOR</tt>, <tt>MINOR</tt>, and <tt>PATCH</tt> with <tt>'.'</tt>
|
9
|
+
#
|
10
|
+
# Example
|
11
|
+
#
|
12
|
+
# Version.to_s # '1.0.2'
|
13
|
+
def self.to_s
|
14
|
+
[MAJOR, MINOR, PATCH].join('.')
|
15
|
+
end
|
16
|
+
end # Version
|
17
|
+
end # module Qiniu
|
data/qiniu.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path('../lib/qiniu/version', __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.authors = ["why404","BluntBlade"]
|
7
|
+
gem.email = ["sdk@qiniu.com"]
|
8
|
+
gem.description = %q{Qiniu Resource (Cloud) Storage SDK for Ruby. See: http://developer.qiniu.com/docs/v6/sdk/ruby-sdk.html}
|
9
|
+
gem.summary = %q{Qiniu Resource (Cloud) Storage SDK for Ruby}
|
10
|
+
gem.homepage = "https://github.com/qiniu/ruby-sdk"
|
11
|
+
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.name = "qiniu_jxb"
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
gem.version = Qiniu::Version.to_s
|
18
|
+
gem.license = "MIT"
|
19
|
+
|
20
|
+
# specify any dependencies here; for example:
|
21
|
+
gem.add_development_dependency "rake", ">= 0.9"
|
22
|
+
gem.add_development_dependency "rspec", ">= 2.11"
|
23
|
+
gem.add_development_dependency "fakeweb", "~> 1.3"
|
24
|
+
gem.add_runtime_dependency "json", "~> 1.7"
|
25
|
+
gem.add_runtime_dependency "rest-client", "~> 1.6"
|
26
|
+
gem.add_runtime_dependency "mime-types", "~> 1.19"
|
27
|
+
gem.add_runtime_dependency "ruby-hmac", "~> 0.4"
|
28
|
+
gem.add_runtime_dependency "jruby-openssl", "~> 0.7" if RUBY_PLATFORM == "java"
|
29
|
+
end
|