qiniu_jxb 6.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.gitignore +18 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +9 -0
  4. data/CHANGELOG.md +118 -0
  5. data/Gemfile +8 -0
  6. data/Gemfile.lock +37 -0
  7. data/LICENSE +22 -0
  8. data/README.md +47 -0
  9. data/Rakefile +21 -0
  10. data/docs/README.md +790 -0
  11. data/lib/qiniu-rs.rb +2 -0
  12. data/lib/qiniu.rb +209 -0
  13. data/lib/qiniu/abstract.rb +22 -0
  14. data/lib/qiniu/adt.rb +46 -0
  15. data/lib/qiniu/auth.rb +234 -0
  16. data/lib/qiniu/config.rb +58 -0
  17. data/lib/qiniu/exceptions.rb +120 -0
  18. data/lib/qiniu/fop.rb +4 -0
  19. data/lib/qiniu/http.rb +137 -0
  20. data/lib/qiniu/image.rb +38 -0
  21. data/lib/qiniu/log.rb +15 -0
  22. data/lib/qiniu/management.rb +128 -0
  23. data/lib/qiniu/misc.rb +33 -0
  24. data/lib/qiniu/pfop.rb +124 -0
  25. data/lib/qiniu/resumable_upload.rb +319 -0
  26. data/lib/qiniu/storage.rb +5 -0
  27. data/lib/qiniu/tokens/access_token.rb +21 -0
  28. data/lib/qiniu/tokens/download_token.rb +31 -0
  29. data/lib/qiniu/tokens/qbox_token.rb +38 -0
  30. data/lib/qiniu/tokens/upload_token.rb +47 -0
  31. data/lib/qiniu/upload.rb +138 -0
  32. data/lib/qiniu/utils.rb +109 -0
  33. data/lib/qiniu/version.rb +17 -0
  34. data/qiniu.gemspec +29 -0
  35. data/spec/qiniu/abstract_spec.rb +30 -0
  36. data/spec/qiniu/auth_spec.rb +81 -0
  37. data/spec/qiniu/image_logo_for_test.png +0 -0
  38. data/spec/qiniu/image_spec.rb +89 -0
  39. data/spec/qiniu/management_spec.rb +156 -0
  40. data/spec/qiniu/misc_spec.rb +59 -0
  41. data/spec/qiniu/pfop_spec.rb +89 -0
  42. data/spec/qiniu/qiniu_spec.rb +329 -0
  43. data/spec/qiniu/tokens/qbox_token_spec.rb +29 -0
  44. data/spec/qiniu/upload_spec.rb +308 -0
  45. data/spec/qiniu/utils_spec.rb +49 -0
  46. data/spec/qiniu/version_spec.rb +10 -0
  47. data/spec/spec_helper.rb +19 -0
  48. metadata +220 -0
@@ -0,0 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'qiniu/upload'
4
+ require 'qiniu/resumable_upload'
5
+ require 'qiniu/management'
@@ -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
@@ -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
@@ -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