qiniu 6.0.1

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,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 = Utils.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,114 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Qiniu
4
+ module Storage
5
+ class << self
6
+ include Utils
7
+
8
+ def put_file(local_file,
9
+ bucket,
10
+ key = nil,
11
+ mime_type = nil,
12
+ custom_meta = nil,
13
+ enable_crc32_check = false)
14
+ action_params = _generate_action_params(
15
+ local_file,
16
+ bucket,
17
+ key,
18
+ mime_type,
19
+ custom_meta,
20
+ enable_crc32_check
21
+ )
22
+
23
+ url = Config.settings[:io_host] + action_params
24
+ options = {:content_type => 'application/octet-stream'}
25
+
26
+ Auth.request url, ::IO.read(local_file), options
27
+ end # put_file
28
+
29
+ def upload_with_token(uptoken,
30
+ local_file,
31
+ bucket,
32
+ key = nil,
33
+ mime_type = nil,
34
+ custom_meta = nil,
35
+ callback_params = nil,
36
+ enable_crc32_check = false,
37
+ rotate = nil)
38
+ action_params = _generate_action_params(
39
+ local_file,
40
+ bucket,
41
+ key,
42
+ mime_type,
43
+ custom_meta,
44
+ enable_crc32_check,
45
+ rotate
46
+ )
47
+
48
+ if callback_params.nil?
49
+ callback_params = {:bucket => bucket, :key => key, :mime_type => mime_type}
50
+ end
51
+ callback_query_string = Utils.generate_query_string(callback_params)
52
+ url = Config.settings[:up_host] + '/upload'
53
+
54
+ Utils.upload_multipart_data(url, local_file, action_params, callback_query_string, uptoken)
55
+ end # upload_with_token
56
+
57
+ def upload_with_token_2(uptoken,
58
+ local_file,
59
+ key = nil,
60
+ x_vars = nil)
61
+ ### 构造URL
62
+ url = Config.settings[:up_host]
63
+ url[/\/*$/] = ''
64
+ url += '/'
65
+
66
+ ### 构造HTTP Body
67
+ post_data = {
68
+ :file => File.new(local_file, 'rb'),
69
+ :multipart => true,
70
+ }
71
+ if not uptoken.nil?
72
+ post_data[:token] = uptoken
73
+ end
74
+ if not key.nil?
75
+ post_data[:key] = key
76
+ end
77
+ if x_vars.is_a?(Hash)
78
+ post_data.merge!(x_vars)
79
+ end
80
+
81
+ ### 发送请求
82
+ Utils.http_request url, post_data
83
+ end # upload_with_token_2
84
+
85
+ private
86
+ def _generate_action_params(local_file,
87
+ bucket,
88
+ key = nil,
89
+ mime_type = nil,
90
+ custom_meta = nil,
91
+ enable_crc32_check = false,
92
+ rotate = nil)
93
+ raise NoSuchFileError, local_file unless File.exist?(local_file)
94
+
95
+ if key.nil?
96
+ key = Digest::SHA1.hexdigest(local_file + Time.now.to_s)
97
+ end
98
+
99
+ entry_uri = bucket + ':' + key
100
+ if mime_type.nil? || mime_type.empty?
101
+ mime = MIME::Types.type_for local_file
102
+ mime_type = mime.empty? ? 'application/octet-stream' : mime[0].content_type
103
+ end
104
+
105
+ action_params = '/rs-put/' + Utils.urlsafe_base64_encode(entry_uri) + '/mimeType/' + Utils.urlsafe_base64_encode(mime_type)
106
+ action_params += '/meta/' + Utils.urlsafe_base64_encode(custom_meta) unless custom_meta.nil?
107
+ action_params += '/crc32/' + Utils.crc32checksum(local_file).to_s if enable_crc32_check
108
+ action_params += '/rotate/' + rotate if !rotate.nil? && rotate.to_i >= 0
109
+ action_params
110
+ end # _generate_action_params
111
+
112
+ end # class << self
113
+ end # module Storage
114
+ end # module Qiniu
@@ -0,0 +1,151 @@
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 is_response_ok?(status_code)
35
+ status_code/100 == 2
36
+ end
37
+
38
+ def response_error(status_code, errmsg)
39
+ [status_code, {"error" => errmsg}]
40
+ end
41
+
42
+ def debug(msg)
43
+ if Config.settings[:enable_debug]
44
+ Log.logger.debug(msg)
45
+ end
46
+ end
47
+
48
+ def send_request_with url, data = nil, options = {}
49
+ options[:method] = Config.settings[:method] unless options[:method]
50
+ options[:content_type] = Config.settings[:content_type] unless options[:content_type]
51
+ header_options = {
52
+ :accept => :json,
53
+ :user_agent => Config.settings[:user_agent]
54
+ }
55
+ auth_token = nil
56
+ if !options[:qbox_signature_token].nil? && !options[:qbox_signature_token].empty?
57
+ auth_token = 'QBox ' + options[:qbox_signature_token]
58
+ elsif !options[:upload_signature_token].nil? && !options[:upload_signature_token].empty?
59
+ auth_token = 'UpToken ' + options[:upload_signature_token]
60
+ elsif options[:access_token]
61
+ auth_token = 'Bearer ' + options[:access_token]
62
+ end
63
+ header_options.merge!('Authorization' => auth_token) unless auth_token.nil?
64
+ case options[:method]
65
+ when :get
66
+ response = RestClient.get(url, header_options)
67
+ when :post
68
+ header_options.merge!(:content_type => options[:content_type])
69
+ response = RestClient.post(url, data, header_options)
70
+ end
71
+ code = response.respond_to?(:code) ? response.code.to_i : 0
72
+ unless is_response_ok?(code)
73
+ raise RequestFailed.new("Request Failed", response)
74
+ else
75
+ data = {}
76
+ body = response.respond_to?(:body) ? response.body : {}
77
+ data = safe_json_parse(body) unless body.empty?
78
+ end
79
+ [code, data]
80
+ end
81
+
82
+ def http_request url, data = nil, options = {}
83
+ retry_times = 0
84
+ begin
85
+ retry_times += 1
86
+ send_request_with url, data, options
87
+ rescue Errno::ECONNRESET => err
88
+ if Config.settings[:auto_reconnect] && retry_times < Config.settings[:max_retry_times]
89
+ retry
90
+ else
91
+ Log.logger.error err
92
+ end
93
+ rescue => e
94
+ Log.logger.warn "#{e.message} => Utils.http_request('#{url}')"
95
+ code = 0
96
+ data = {}
97
+ body = {}
98
+ if e.respond_to? :response
99
+ res = e.response
100
+ code = res.code.to_i if res.respond_to? :code
101
+ body = res.respond_to?(:body) ? res.body : ""
102
+ data = safe_json_parse(body) unless body.empty?
103
+ end
104
+ [code, data]
105
+ end
106
+ end
107
+
108
+ def upload_multipart_data(url, filepath, action_string, callback_query_string = '', uptoken = nil)
109
+ post_data = {
110
+ :params => callback_query_string,
111
+ :action => action_string,
112
+ :file => File.new(filepath, 'rb'),
113
+ :multipart => true
114
+ }
115
+ post_data[:auth] = uptoken unless uptoken.nil?
116
+ http_request url, post_data
117
+ end
118
+
119
+ def generate_query_string(params)
120
+ return params if params.is_a?(String)
121
+ total_param = params.map { |key, value| %Q(#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s).gsub('+', '%20')}) }
122
+ total_param.join("&")
123
+ end
124
+
125
+ def crc32checksum(filepath)
126
+ File.open(filepath, "rb") { |f| Zlib.crc32 f.read }
127
+ end
128
+
129
+ def generate_qbox_signature(url, params, mime = nil)
130
+ access_key = Config.settings[:access_key]
131
+ secret_key = Config.settings[:secret_key]
132
+ uri = URI.parse(url)
133
+ signature = uri.path
134
+ query_string = uri.query
135
+ signature += '?' + query_string if !query_string.nil? && !query_string.empty?
136
+ signature += "\n"
137
+ if params.is_a?(Hash)
138
+ params_string = generate_query_string(params)
139
+ signature += params_string
140
+ end
141
+ if mime.is_a?(String) && mime == "application/x-www-form-urlencoded" && params.is_a?(String)
142
+ signature += params
143
+ end
144
+ hmac = HMAC::SHA1.new(secret_key)
145
+ hmac.update(signature)
146
+ encoded_digest = urlsafe_base64_encode(hmac.digest)
147
+ %Q(#{access_key}:#{encoded_digest})
148
+ end
149
+
150
+ end # module Utils
151
+ end # module Qiniu
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Qiniu
4
+ module Version
5
+ MAJOR = 6
6
+ MINOR = 0
7
+ PATCH = 1
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
@@ -0,0 +1,28 @@
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"]
7
+ gem.email = ["why404@gmail.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"
16
+ gem.require_paths = ["lib"]
17
+ gem.version = Qiniu::Version.to_s
18
+
19
+ # specify any dependencies here; for example:
20
+ gem.add_development_dependency "rake", ">= 0.9"
21
+ gem.add_development_dependency "rspec", ">= 2.11"
22
+ gem.add_development_dependency "fakeweb", "~> 1.3"
23
+ gem.add_runtime_dependency "json", "~> 1.7"
24
+ gem.add_runtime_dependency "rest-client", "~> 1.6"
25
+ gem.add_runtime_dependency "mime-types", "~> 1.19"
26
+ gem.add_runtime_dependency "ruby-hmac", "~> 0.4"
27
+ gem.add_runtime_dependency "jruby-openssl", "~> 0.7" if RUBY_PLATFORM == "java"
28
+ end