qiniu 6.1.0 → 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5df0656bef38c727a292ffe6ec54aba7ab0c8cac
4
- data.tar.gz: 69d504ea0f9c61410e96600f55aa5cbea08f331e
3
+ metadata.gz: beb8c598a8ae3aabebea6aca70a992aa8cbfb20a
4
+ data.tar.gz: a23e588d3da392c136bb4112f17163658de5dc8f
5
5
  SHA512:
6
- metadata.gz: c74fb96b07fee02ab56fb4b25b9ac52637ea478bd3da685238644c0f1b034662211d7b9d483d50b428fc5c69030cb5bae148e14ba0059c4029e80c1d9c498240
7
- data.tar.gz: f76c79b88f64661c3876f77ecff944d9bb63ce25ac389d3cfb826abc515ce1646c5edfd44312ba43e907629114b61ca0801c6b883c920ba2312e3ae29a5f1b5a
6
+ metadata.gz: 328f544c77cbe62e969704ce39f84a5f2a1f71e5d284cfadb3d5b6750ecef3002c48f5421cea24e7a6711e4a563d6eba908e13fc7abaf3f9d12c944304a9027b
7
+ data.tar.gz: 872dc200b4fa640c965f3b10416c210142f302cc0cbd0c81e0010aab3727c520d7cb2ad0190065a32cb2b1456cee5edd31cf5230d30767f62dfd88cc0bf5f3d4
data/.travis.yml CHANGED
@@ -7,7 +7,6 @@ rvm:
7
7
  - 2.1.1
8
8
  - jruby-18mode
9
9
  - jruby-19mode
10
- - jruby-head
11
10
  - ree
12
11
  before_script:
13
12
  - export QINIU_ACCESS_KEY=LGRqJsjX7LAvtdtX6hhyxs861lS57HwnOQmJsOuX
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## CHANGE LOG
2
2
 
3
+ ### v6.2.0
4
+
5
+ - 重写与授权相关的函数并归入Qiniu::Auth空间,原授权凭证生成类维持不变。
6
+
7
+ - 添加Qiniu::Storage::PutPolicy类和Qiniu::Storage#upload_with_put_policy方法,并推荐使用两者组合实现单文件上传。
8
+
3
9
  ### v6.1.0
4
10
 
5
11
  - Qiniu::Storage所有上传接口返回第三个值raw_headers,类型为Hash,包含已解析的HTTP响应报文中的所有Header信息。
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- qiniu (6.1.0)
4
+ qiniu (6.2.0)
5
5
  json (~> 1.7)
6
6
  mime-types (~> 1.19)
7
7
  rest-client (~> 1.6)
data/lib/qiniu/auth.rb CHANGED
@@ -1,17 +1,146 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ # vim: sw=2 ts=2
3
+
4
+ require 'hmac-sha1'
5
+ require 'uri'
2
6
 
3
7
  require 'qiniu/exceptions'
4
8
 
5
9
  module Qiniu
6
10
  module Auth
11
+ DEFAULT_AUTH_SECONDS = 3600
12
+
13
+ class << self
14
+ def calculate_deadline(expires_in, deadline = nil)
15
+ ### 授权期计算
16
+ if expires_in.is_a?(Integer) && expires_in > 0 then
17
+ # 指定相对时间,单位:秒
18
+ return Time.now.to_i + expires_in
19
+ elsif deadline.is_a?(Integer) then
20
+ # 指定绝对时间,常用于调试和单元测试
21
+ return deadline
22
+ end
23
+
24
+ # 默认授权期1小时
25
+ return Time.now.to_i + DEFAULT_AUTH_SECONDS
26
+ end # calculate_deadline
27
+ end # class << self
28
+
29
+ class PutPolicy
30
+ private
31
+ def initialize(bucket,
32
+ key = nil,
33
+ expires_in = DEFAULT_AUTH_SECONDS,
34
+ deadline = nil)
35
+ ### 设定scope参数(必填项目)
36
+ self.scope!(bucket, key)
37
+
38
+ ### 设定deadline参数(必填项目)
39
+ @expires_in = expires_in
40
+ @deadline = Auth.calculate_deadline(expires_in, deadline)
41
+ end # initialize
42
+
43
+ PARAMS = {
44
+ # 字符串类型参数
45
+ :scope => "scope" ,
46
+ :save_key => "saveKey" ,
47
+ :end_user => "endUser" ,
48
+ :return_url => "returnUrl" ,
49
+ :return_body => "returnBody" ,
50
+ :callback_url => "callbackUrl" ,
51
+ :callback_body => "callbackBody" ,
52
+ :persistent_ops => "persistentOps" ,
53
+ :persistent_notify_url => "persistentNotifyUrl" ,
54
+ :transform => "transform" ,
55
+
56
+ # 数值类型参数
57
+ :deadline => "deadline" ,
58
+ :insert_only => "insertOnly" ,
59
+ :fsize_limit => "fsizeLimit" ,
60
+ :detect_mime => "detectMime" ,
61
+ :mime_limit => "mimeLimit" ,
62
+ :fop_timeout => "fopTimeout"
63
+ } # PARAMS
64
+
65
+ public
66
+ attr_reader :bucket, :key
67
+
68
+ def scope!(bucket, key = nil)
69
+ @bucket = bucket
70
+ @key = key
71
+
72
+ if key.nil? then
73
+ # 新增语义,文件已存在则失败
74
+ @scope = bucket
75
+ else
76
+ # 覆盖语义,文件已存在则直接覆盖
77
+ @scope = "#{bucket}:#{key}"
78
+ end
79
+ end # scope!
80
+
81
+ def expires_in!(seconds)
82
+ if !seconds.nil? then
83
+ return @expires_in
84
+ end
85
+
86
+ @epires_in = seconds
87
+ @deadline = Auth.calculate_deadline(seconds)
88
+
89
+ return @expires_in
90
+ end # expires_in!
91
+
92
+ def expires_in=(seconds)
93
+ return expires_in!(seconds)
94
+ end # expires_in=
95
+
96
+ def expires_in
97
+ return @expires_in
98
+ end # expires_in
99
+
100
+ def allow_mime_list! (list)
101
+ @mime_limit = list
102
+ end # allow_mime_list!
103
+
104
+ def deny_mime_list! (list)
105
+ @mime_limit = "!#{list}"
106
+ end # deny_mime_list!
107
+
108
+ def insert_only!
109
+ @insert_only = 1
110
+ end # insert_only!
111
+
112
+ def detect_mime!
113
+ @detect_mime = 1
114
+ end # detect_mime!
115
+
116
+ def to_json
117
+ args = {}
118
+
119
+ PARAMS.each_pair do |key, fld|
120
+ val = self.__send__(key)
121
+ if !val.nil? then
122
+ args[fld] = val
123
+ end
124
+ end
125
+
126
+ return args.to_json
127
+ end # to_json
128
+
129
+ PARAMS.each_pair do |key, fld|
130
+ attr_accessor key
131
+ end
132
+ end # class PutPolicy
7
133
 
8
134
  class << self
9
135
 
10
136
  include Utils
11
137
 
12
138
  def call_with_signature(url, data, retry_times = 0, options = {})
13
- code, data, raw_headers = http_request url, data, options.merge({:qbox_signature_token => generate_qbox_signature(url, data, options[:mime])})
14
- [code, data, raw_headers]
139
+ return Utils.http_request(
140
+ url,
141
+ data,
142
+ options.merge({:qbox_signature_token => generate_acctoken(url, data)})
143
+ )
15
144
  end # call_with_signature
16
145
 
17
146
  def request(url, data = nil, options = {})
@@ -19,6 +148,90 @@ module Qiniu
19
148
  [code, data, raw_headers]
20
149
  end # request
21
150
 
151
+ EMPTY_ARGS = {}
152
+
153
+ ### 生成下载授权URL
154
+ def authorize_download_url(url, args = EMPTY_ARGS)
155
+ ### 提取AK/SK信息
156
+ access_key = Config.settings[:access_key]
157
+ secret_key = Config.settings[:secret_key]
158
+
159
+ ### 授权期计算
160
+ e = Auth.calculate_deadline(args[:expires_in], args[:deadline])
161
+
162
+ ### URL变换:追加授权期参数
163
+ if url.index('?').is_a?(Fixnum) then
164
+ # 已有参数
165
+ download_url = "#{url}&e=#{e}"
166
+ else
167
+ # 尚无参数
168
+ download_url = "#{url}?e=#{e}"
169
+ end
170
+
171
+ ### 生成数字签名
172
+ sign = HMAC::SHA1.new(secret_key).update(download_url).digest
173
+ encoded_sign = Utils.urlsafe_base64_encode(sign)
174
+
175
+ ### 生成下载授权凭证
176
+ dntoken = "#{access_key}:#{encoded_sign}"
177
+
178
+ ### 返回下载授权URL
179
+ return "#{download_url}&token=#{dntoken}"
180
+ end # authorize_download_url
181
+
182
+ def generate_acctoken(url, body = '')
183
+ ### 提取AK/SK信息
184
+ access_key = Config.settings[:access_key]
185
+ secret_key = Config.settings[:secret_key]
186
+
187
+ ### 解析URL,生成待签名字符串
188
+ uri = URI.parse(url)
189
+ signing_str = uri.path
190
+
191
+ # 如有QueryString部分,则需要加上
192
+ query_string = uri.query
193
+ if query_string.is_a?(String) && !query_string.empty?
194
+ signing_str += '?' + query_string
195
+ end
196
+
197
+ # 追加换行符
198
+ signing_str += "\n"
199
+
200
+ # 如果有Body,则也加上
201
+ # (仅限于mime == "application/x-www-form-urlencoded"的情况)
202
+ if body.is_a?(String) && !body.empty?
203
+ signing_str += body
204
+ end
205
+
206
+ ### 生成数字签名
207
+ sign = HMAC::SHA1.new(secret_key).update(signing_str).digest
208
+ encoded_sign = Utils.urlsafe_base64_encode(sign)
209
+
210
+ ### 生成管理授权凭证
211
+ acctoken = "#{access_key}:#{encoded_sign}"
212
+
213
+ ### 返回管理授权凭证
214
+ return acctoken
215
+ end # generate_acctoken
216
+
217
+ def generate_uptoken(put_policy)
218
+ ### 提取AK/SK信息
219
+ access_key = Config.settings[:access_key]
220
+ secret_key = Config.settings[:secret_key]
221
+
222
+ ### 生成待签名字符串
223
+ encoded_put_policy = Utils.urlsafe_base64_encode(put_policy.to_json)
224
+
225
+ ### 生成数字签名
226
+ sign = HMAC::SHA1.new(secret_key).update(encoded_put_policy).digest
227
+ encoded_sign = Utils.urlsafe_base64_encode(sign)
228
+
229
+ ### 生成上传授权凭证
230
+ uptoken = "#{access_key}:#{encoded_sign}:#{encoded_put_policy}"
231
+
232
+ ### 返回上传授权凭证
233
+ return uptoken
234
+ end # generate_uptoken
22
235
  end # class << self
23
236
 
24
237
  end # module Auth
@@ -9,10 +9,21 @@ module Qiniu
9
9
  Auth.request Config.settings[:rs_host] + '/buckets'
10
10
  end # buckets
11
11
 
12
- def mkbucket(bucket_name)
13
- Auth.request Config.settings[:rs_host] + '/mkbucket/' + bucket_name
12
+ PRIVATE_BUCKET = 0
13
+ PUBLIC_BUCKET = 1
14
+
15
+ def mkbucket(bucket_name, is_public = PUBLIC_BUCKET)
16
+ Auth.request Config.settings[:rs_host] + '/mkbucket2/' + bucket_name + '/public/' + is_public.to_s
14
17
  end # mkbucket
15
18
 
19
+ def make_a_private_bucket(bucket_name)
20
+ return mkbucket(bucket_name, PRIVATE_BUCKET)
21
+ end # make_a_private_bucket
22
+
23
+ def make_a_public_bucket(bucket_name)
24
+ return mkbucket(bucket_name, PUBLIC_BUCKET)
25
+ end # make_a_public_bucket
26
+
16
27
  def stat(bucket, key)
17
28
  Auth.request Config.settings[:rs_host] + '/stat/' + encode_entry_uri(bucket, key)
18
29
  end # stat
data/lib/qiniu/upload.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ # vim: sw=2 ts=2
2
3
 
3
4
  module Qiniu
4
5
  module Storage
@@ -61,6 +62,27 @@ module Qiniu
61
62
  Utils.http_request url, post_data
62
63
  end # upload_with_token_2
63
64
 
65
+ ### 授权举例
66
+ # put_policy.bucket | put_policy.key | key | 语义 | 授权
67
+ # :---------------- | :------------- | :------ | :--- | :---
68
+ # trivial_bucket | <nil> | <nil> | 新增 | 允许,最终key为1)使用put_policy.save_key生成的值或2)资源内容的Hash值
69
+ # trivial_bucket | <nil> | foo.txt | 新增 | 允许
70
+ # trivial_bucket | <nil> | bar.jpg | 新增 | 允许
71
+ # trivial_bucket | foo.txt | <nil> | 覆盖 | 允许,由SDK将put_policy.key赋值给key实现
72
+ # trivial_bucket | foo.txt | foo.txt | 覆盖 | 允许
73
+ # trivial_bucket | foo.txt | bar.jpg | 覆盖 | 禁止,put_policy.key与key不一致
74
+ def upload_with_put_policy(put_policy,
75
+ local_file,
76
+ key = nil,
77
+ x_vars = nil)
78
+ uptoken = Auth.generate_uptoken(put_policy)
79
+ if key.nil? then
80
+ key = put_policy.key
81
+ end
82
+
83
+ return upload_with_token_2(uptoken, local_file, key, x_vars)
84
+ end # upload_with_put_policy
85
+
64
86
  private
65
87
  def _generate_action_params(local_file,
66
88
  bucket,
data/lib/qiniu/utils.rb CHANGED
@@ -128,26 +128,5 @@ module Qiniu
128
128
  File.open(filepath, "rb") { |f| Zlib.crc32 f.read }
129
129
  end
130
130
 
131
- def generate_qbox_signature(url, params, mime = nil)
132
- access_key = Config.settings[:access_key]
133
- secret_key = Config.settings[:secret_key]
134
- uri = URI.parse(url)
135
- signature = uri.path
136
- query_string = uri.query
137
- signature += '?' + query_string if !query_string.nil? && !query_string.empty?
138
- signature += "\n"
139
- if params.is_a?(Hash)
140
- params_string = generate_query_string(params)
141
- signature += params_string
142
- end
143
- if mime.is_a?(String) && mime == "application/x-www-form-urlencoded" && params.is_a?(String)
144
- signature += params
145
- end
146
- hmac = HMAC::SHA1.new(secret_key)
147
- hmac.update(signature)
148
- encoded_digest = urlsafe_base64_encode(hmac.digest)
149
- %Q(#{access_key}:#{encoded_digest})
150
- end
151
-
152
131
  end # module Utils
153
132
  end # module Qiniu
data/lib/qiniu/version.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Qiniu
4
4
  module Version
5
5
  MAJOR = 6
6
- MINOR = 1
6
+ MINOR = 2
7
7
  PATCH = 0
8
8
  # Returns a version string by joining <tt>MAJOR</tt>, <tt>MINOR</tt>, and <tt>PATCH</tt> with <tt>'.'</tt>
9
9
  #
@@ -0,0 +1,75 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+ require 'qiniu/auth'
5
+ require 'qiniu/storage'
6
+ require 'digest/sha1'
7
+
8
+ module Qiniu
9
+ module Auth
10
+ describe Auth do
11
+
12
+ before :all do
13
+ @bucket = 'RubySDK-Test-Private'
14
+ @bucket = make_unique_bucket(@bucket)
15
+
16
+ ### 尝试创建Bucket
17
+ result = Qiniu::Storage.make_a_private_bucket(@bucket)
18
+ puts result.inspect
19
+ end
20
+
21
+ after :all do
22
+ ### 不删除Bucket以备下次使用
23
+ end
24
+
25
+ ### 测试私有资源下载
26
+ context ".download_private_file" do
27
+ it "should works" do
28
+ ### 生成Key
29
+ key = 'a_private_file'
30
+ key = make_unique_key_in_bucket(key)
31
+ puts "key=#{key}"
32
+
33
+ ### 上传测试文件
34
+ pp = Auth::PutPolicy.new(@bucket, key)
35
+ code, data, raw_headers = Qiniu::Storage.upload_with_put_policy(
36
+ pp,
37
+ __FILE__
38
+ )
39
+ code.should == 200
40
+ puts data.inspect
41
+ puts raw_headers.inspect
42
+
43
+ ### 获取下载地址
44
+ code, data = Qiniu::Storage.get(@bucket, key)
45
+ code.should == 200
46
+ puts data.inspect
47
+
48
+ url = data['url']
49
+
50
+ ### 授权下载地址(不带参数)
51
+ download_url = Qiniu::Auth.authorize_download_url(url)
52
+ puts "download_url=#{download_url}"
53
+
54
+ result = RestClient.get(download_url)
55
+ result.code.should == 200
56
+ result.body.should_not be_empty
57
+
58
+ ### 授权下载地址(带参数)
59
+ download_url = Qiniu::Auth.authorize_download_url(url + '?download/a.m3u8')
60
+ puts "download_url=#{download_url}"
61
+
62
+ result = RestClient.get(download_url)
63
+ result.code.should == 200
64
+ result.body.should_not be_empty
65
+
66
+ ### 删除文件
67
+ code, data = Qiniu::Storage.delete(@bucket, key)
68
+ code.should == 200
69
+ puts data.inspect
70
+ end
71
+ end
72
+
73
+ end
74
+ end # module Storage
75
+ end # module Qiniu
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ # vim: sw=2 ts=2
2
3
 
3
4
  require 'digest/sha1'
4
5
  require 'spec_helper'
@@ -29,15 +30,12 @@ module Qiniu
29
30
  end
30
31
 
31
32
  ### 准备数据
32
- context ".upload_with_token_2" do
33
+ context ".prepare_file" do
33
34
  it "should works" do
34
- upopts = {:scope => @bucket, :expires_in => 3600, :endUser => "why404@gmail.com"}
35
- uptoken = Qiniu.generate_upload_token(upopts)
36
-
37
- code, data, raw_headers = Qiniu::Storage.upload_with_token_2(
38
- uptoken,
39
- __FILE__,
40
- @key
35
+ pp = Auth::PutPolicy.new(@bucket, @key)
36
+ code, data, raw_headers = Qiniu::Storage.upload_with_put_policy(
37
+ pp,
38
+ __FILE__
41
39
  )
42
40
  code.should == 200
43
41
  puts data.inspect
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ # vim: sw=2 ts=2
2
3
 
3
4
  require 'spec_helper'
4
5
  require 'qiniu/auth'
@@ -126,6 +127,49 @@ module Qiniu
126
127
  end
127
128
  end
128
129
 
130
+ context ".upload_with_put_policy" do
131
+ it "should works" do
132
+ pp = Qiniu::Auth::PutPolicy.new(@bucket, @key)
133
+ pp.end_user = "why404@gmail.com"
134
+ puts 'put_policy=' + pp.to_json
135
+
136
+ code, data, raw_headers = Qiniu::Storage.upload_with_put_policy(
137
+ pp,
138
+ __FILE__,
139
+ @key + '-not-equal'
140
+ )
141
+ code.should_not == 200
142
+ puts data.inspect
143
+ puts raw_headers.inspect
144
+
145
+ code, data, raw_headers = Qiniu::Storage.upload_with_put_policy(
146
+ pp,
147
+ __FILE__,
148
+ @key
149
+ )
150
+
151
+ code.should == 200
152
+ puts data.inspect
153
+ puts raw_headers.inspect
154
+ end
155
+ end # .upload_with_put_policy
156
+
157
+ context ".stat" do
158
+ it "should exists" do
159
+ code, data = Qiniu::Storage.stat(@bucket, @key)
160
+ puts data.inspect
161
+ code.should == 200
162
+ end
163
+ end
164
+
165
+ context ".delete" do
166
+ it "should works" do
167
+ code, data = Qiniu::Storage.delete(@bucket, @key)
168
+ puts data.inspect
169
+ code.should == 200
170
+ end
171
+ end
172
+
129
173
  ### 测试断点续上传
130
174
  context ".resumable_upload_with_token" do
131
175
  it "should works" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qiniu
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.0
4
+ version: 6.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - why404
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-27 00:00:00.000000000 Z
11
+ date: 2014-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -147,6 +147,7 @@ files:
147
147
  - lib/qiniu/version.rb
148
148
  - qiniu.gemspec
149
149
  - spec/qiniu/abstract_spec.rb
150
+ - spec/qiniu/auth_spec.rb
150
151
  - spec/qiniu/image_logo_for_test.png
151
152
  - spec/qiniu/image_spec.rb
152
153
  - spec/qiniu/management_spec.rb
@@ -182,6 +183,7 @@ specification_version: 4
182
183
  summary: Qiniu Resource (Cloud) Storage SDK for Ruby
183
184
  test_files:
184
185
  - spec/qiniu/abstract_spec.rb
186
+ - spec/qiniu/auth_spec.rb
185
187
  - spec/qiniu/image_logo_for_test.png
186
188
  - spec/qiniu/image_spec.rb
187
189
  - spec/qiniu/management_spec.rb