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.
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