qiniu_jxb_fix 6.4.2

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 (50) hide show
  1. data/.gitignore +18 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +12 -0
  4. data/CHANGELOG.md +146 -0
  5. data/Gemfile +8 -0
  6. data/Gemfile.lock +44 -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/abstract.rb +22 -0
  12. data/lib/qiniu/adt.rb +46 -0
  13. data/lib/qiniu/auth.rb +255 -0
  14. data/lib/qiniu/config.rb +60 -0
  15. data/lib/qiniu/exceptions.rb +120 -0
  16. data/lib/qiniu/fop.rb +4 -0
  17. data/lib/qiniu/http.rb +137 -0
  18. data/lib/qiniu/image.rb +38 -0
  19. data/lib/qiniu/log.rb +15 -0
  20. data/lib/qiniu/management.rb +166 -0
  21. data/lib/qiniu/misc.rb +35 -0
  22. data/lib/qiniu/pfop.rb +124 -0
  23. data/lib/qiniu/resumable_upload.rb +319 -0
  24. data/lib/qiniu/storage.rb +5 -0
  25. data/lib/qiniu/tokens/access_token.rb +23 -0
  26. data/lib/qiniu/tokens/download_token.rb +36 -0
  27. data/lib/qiniu/tokens/qbox_token.rb +38 -0
  28. data/lib/qiniu/tokens/upload_token.rb +57 -0
  29. data/lib/qiniu/upload.rb +134 -0
  30. data/lib/qiniu/utils.rb +109 -0
  31. data/lib/qiniu/version.rb +17 -0
  32. data/lib/qiniu-rs.rb +2 -0
  33. data/lib/qiniu.rb +209 -0
  34. data/qiniu.gemspec +29 -0
  35. data/rails3/Gemfile +4 -0
  36. data/rails3/qiniu.gemspec +29 -0
  37. data/spec/qiniu/abstract_spec.rb +30 -0
  38. data/spec/qiniu/auth_spec.rb +74 -0
  39. data/spec/qiniu/image_logo_for_test.png +0 -0
  40. data/spec/qiniu/image_spec.rb +80 -0
  41. data/spec/qiniu/management_spec.rb +163 -0
  42. data/spec/qiniu/misc_spec.rb +53 -0
  43. data/spec/qiniu/pfop_spec.rb +80 -0
  44. data/spec/qiniu/qiniu_spec.rb +321 -0
  45. data/spec/qiniu/tokens/qbox_token_spec.rb +29 -0
  46. data/spec/qiniu/upload_spec.rb +301 -0
  47. data/spec/qiniu/utils_spec.rb +49 -0
  48. data/spec/qiniu/version_spec.rb +10 -0
  49. data/spec/spec_helper.rb +19 -0
  50. metadata +222 -0
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Qiniu
4
+ module Abstract
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def abstract_methods(*args)
11
+ args.each do |name|
12
+ class_eval <<-END
13
+ def #{name}(*args)
14
+ errmsg = %Q(class \#{self.class.name} must implement abstract method #{self.name}##{name}().)
15
+ raise NotImplementedError.new(errmsg)
16
+ end
17
+ END
18
+ end
19
+ end
20
+ end
21
+ end # module Abstract
22
+ end # module Qiniu
data/lib/qiniu/adt.rb ADDED
@@ -0,0 +1,46 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # vim: sw=2 ts=2
3
+
4
+ require 'uri'
5
+
6
+ module Qiniu
7
+ module ADT
8
+
9
+ class ApiSpecification
10
+ public
11
+ def to_str; return ""; end
12
+ end # class ApiSpecification
13
+
14
+ module Policy
15
+ public
16
+ def to_json
17
+ args = {}
18
+
19
+ self.params.each_pair do |key, fld|
20
+ val = self.__send__(key)
21
+ if !val.nil? then
22
+ args[fld] = val
23
+ end
24
+ end
25
+
26
+ return args.to_json
27
+ end # to_json
28
+
29
+ def to_query_string
30
+ args = []
31
+
32
+ self.params.each_pair do |key, fld|
33
+ val = self.__send__(key)
34
+ if !val.nil? then
35
+ new_fld = CGI.escape(fld.to_s)
36
+ new_val = CGI.escape(val.to_s).gsub('+', '%20')
37
+ args.push("#{new_fld}=#{new_val}")
38
+ end
39
+ end
40
+
41
+ return args.join("&")
42
+ end # to_query_string
43
+ end # module Policy
44
+
45
+ end # module ADT
46
+ end # module Qiniu
data/lib/qiniu/auth.rb ADDED
@@ -0,0 +1,255 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # vim: sw=2 ts=2
3
+
4
+ require 'hmac-sha1'
5
+ require 'uri'
6
+ require 'cgi'
7
+
8
+ require 'qiniu/exceptions'
9
+ require 'qiniu/helper'
10
+
11
+ module Qiniu
12
+ module Auth
13
+ extend Qiniu::Helper
14
+ DEFAULT_AUTH_SECONDS = 3600
15
+
16
+ class << self
17
+ def calculate_deadline(expires_in, deadline = nil)
18
+ ### 授权期计算
19
+ if expires_in.is_a?(Integer) && expires_in > 0 then
20
+ # 指定相对时间,单位:秒
21
+ return get_expire_time.to_i + expires_in
22
+ elsif deadline.is_a?(Integer) then
23
+ # 指定绝对时间,常用于调试和单元测试
24
+ return deadline
25
+ end
26
+
27
+ # 默认授权期1小时
28
+ return get_expire_time.to_i + DEFAULT_AUTH_SECONDS
29
+ end # calculate_deadline
30
+ end # class << self
31
+
32
+ class PutPolicy
33
+ private
34
+ def initialize(bucket,
35
+ key = nil,
36
+ expires_in = DEFAULT_AUTH_SECONDS,
37
+ deadline = nil)
38
+ ### 设定scope参数(必填项目)
39
+ self.scope!(bucket, key)
40
+
41
+ ### 设定deadline参数(必填项目)
42
+ @expires_in = expires_in
43
+ @deadline = Auth.calculate_deadline(expires_in, deadline)
44
+ end # initialize
45
+
46
+ PARAMS = {
47
+ # 字符串类型参数
48
+ :scope => "scope" ,
49
+ :save_key => "saveKey" ,
50
+ :end_user => "endUser" ,
51
+ :return_url => "returnUrl" ,
52
+ :return_body => "returnBody" ,
53
+ :callback_url => "callbackUrl" ,
54
+ :callback_host => "callbackHost" ,
55
+ :callback_body => "callbackBody" ,
56
+ :callback_body_type => "callbackBodyType" ,
57
+ :persistent_ops => "persistentOps" ,
58
+ :persistent_notify_url => "persistentNotifyUrl" ,
59
+ :persistent_pipeline => "persistentPipeline" ,
60
+
61
+ # 数值类型参数
62
+ :deadline => "deadline" ,
63
+ :insert_only => "insertOnly" ,
64
+ :fsize_limit => "fsizeLimit" ,
65
+ :callback_fetch_key => "callbackFetchKey" ,
66
+ :detect_mime => "detectMime" ,
67
+ :mime_limit => "mimeLimit"
68
+ } # PARAMS
69
+
70
+ public
71
+ attr_reader :bucket, :key
72
+
73
+ def scope!(bucket, key = nil)
74
+ @bucket = bucket
75
+ @key = key
76
+
77
+ if key.nil? then
78
+ # 新增语义,文件已存在则失败
79
+ @scope = bucket
80
+ else
81
+ # 覆盖语义,文件已存在则直接覆盖
82
+ @scope = "#{bucket}:#{key}"
83
+ end
84
+ end # scope!
85
+
86
+ def expires_in!(seconds)
87
+ if !seconds.nil? then
88
+ return @expires_in
89
+ end
90
+
91
+ @epires_in = seconds
92
+ @deadline = Auth.calculate_deadline(seconds)
93
+
94
+ return @expires_in
95
+ end # expires_in!
96
+
97
+ def expires_in=(seconds)
98
+ return expires_in!(seconds)
99
+ end # expires_in=
100
+
101
+ def expires_in
102
+ return @expires_in
103
+ end # expires_in
104
+
105
+ def allow_mime_list! (list)
106
+ @mime_limit = list
107
+ end # allow_mime_list!
108
+
109
+ def deny_mime_list! (list)
110
+ @mime_limit = "!#{list}"
111
+ end # deny_mime_list!
112
+
113
+ def insert_only!
114
+ @insert_only = 1
115
+ end # insert_only!
116
+
117
+ def detect_mime!
118
+ @detect_mime = 1
119
+ end # detect_mime!
120
+
121
+ def to_json
122
+ args = {}
123
+
124
+ PARAMS.each_pair do |key, fld|
125
+ val = self.__send__(key)
126
+ if !val.nil? then
127
+ args[fld] = val
128
+ end
129
+ end
130
+
131
+ return args.to_json
132
+ end # to_json
133
+
134
+ PARAMS.each_pair do |key, fld|
135
+ attr_accessor key
136
+ end
137
+ end # class PutPolicy
138
+
139
+ class << self
140
+ EMPTY_ARGS = {}
141
+
142
+ ### 生成下载授权URL
143
+ def authorize_download_url(url, args = EMPTY_ARGS)
144
+ ### 提取AK/SK信息
145
+ access_key = Config.settings[:access_key]
146
+ secret_key = Config.settings[:secret_key]
147
+
148
+ download_url = url
149
+
150
+ ### URL变换:追加FOP指令
151
+ if args[:fop].is_a?(String) && args[:fop] != '' then
152
+ if download_url.index('?').is_a?(Fixnum) then
153
+ # 已有参数
154
+ download_url = "#{download_url}&#{args[:fop]}"
155
+ else
156
+ # 尚无参数
157
+ download_url = "#{download_url}?#{args[:fop]}"
158
+ end
159
+ end
160
+
161
+ ### 授权期计算
162
+ e = Auth.calculate_deadline(args[:expires_in], args[:deadline])
163
+
164
+ ### URL变换:追加授权期参数
165
+ if download_url.index('?').is_a?(Fixnum) then
166
+ # 已有参数
167
+ download_url = "#{download_url}&e=#{e}"
168
+ else
169
+ # 尚无参数
170
+ download_url = "#{download_url}?e=#{e}"
171
+ end
172
+
173
+ ### 生成数字签名
174
+ sign = HMAC::SHA1.new(secret_key).update(download_url).digest
175
+ encoded_sign = Utils.urlsafe_base64_encode(sign)
176
+
177
+ ### 生成下载授权凭证
178
+ dntoken = "#{access_key}:#{encoded_sign}"
179
+
180
+ ### 返回下载授权URL
181
+ return "#{download_url}&token=#{dntoken}"
182
+ end # authorize_download_url
183
+
184
+ ### 对包含中文或其它 utf-8 字符的 Key 做下载授权
185
+ def authorize_download_url_2(domain, key, args = EMPTY_ARGS)
186
+ url_encoded_key = CGI::escape(key)
187
+
188
+ schema = args[:schema] || "http"
189
+ port = args[:port]
190
+
191
+ if port.nil? then
192
+ download_url = "#{schema}://#{domain}/#{url_encoded_key}"
193
+ else
194
+ download_url = "#{schema}://#{domain}:#{port}/#{url_encoded_key}"
195
+ end
196
+ return authorize_download_url(download_url, args)
197
+ end # authorize_download_url_2
198
+
199
+ def generate_acctoken(url, body = '')
200
+ ### 提取AK/SK信息
201
+ access_key = Config.settings[:access_key]
202
+ secret_key = Config.settings[:secret_key]
203
+
204
+ ### 解析URL,生成待签名字符串
205
+ uri = URI.parse(url)
206
+ signing_str = uri.path
207
+
208
+ # 如有QueryString部分,则需要加上
209
+ query_string = uri.query
210
+ if query_string.is_a?(String) && !query_string.empty?
211
+ signing_str += '?' + query_string
212
+ end
213
+
214
+ # 追加换行符
215
+ signing_str += "\n"
216
+
217
+ # 如果有Body,则也加上
218
+ # (仅限于mime == "application/x-www-form-urlencoded"的情况)
219
+ if body.is_a?(String) && !body.empty?
220
+ signing_str += body
221
+ end
222
+
223
+ ### 生成数字签名
224
+ sign = HMAC::SHA1.new(secret_key).update(signing_str).digest
225
+ encoded_sign = Utils.urlsafe_base64_encode(sign)
226
+
227
+ ### 生成管理授权凭证
228
+ acctoken = "#{access_key}:#{encoded_sign}"
229
+
230
+ ### 返回管理授权凭证
231
+ return acctoken
232
+ end # generate_acctoken
233
+
234
+ def generate_uptoken(put_policy)
235
+ ### 提取AK/SK信息
236
+ access_key = Config.settings[:access_key]
237
+ secret_key = Config.settings[:secret_key]
238
+
239
+ ### 生成待签名字符串
240
+ encoded_put_policy = Utils.urlsafe_base64_encode(put_policy.to_json)
241
+
242
+ ### 生成数字签名
243
+ sign = HMAC::SHA1.new(secret_key).update(encoded_put_policy).digest
244
+ encoded_sign = Utils.urlsafe_base64_encode(sign)
245
+
246
+ ### 生成上传授权凭证
247
+ uptoken = "#{access_key}:#{encoded_sign}:#{encoded_put_policy}"
248
+
249
+ ### 返回上传授权凭证
250
+ return uptoken
251
+ end # generate_uptoken
252
+ end # class << self
253
+
254
+ end # module Auth
255
+ end # module Qiniu
@@ -0,0 +1,60 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # USAGE WAY 1:
4
+ # Qbox::Config.initialize_connect :client_id => "<ClientID>",
5
+ # :client_secret => "<ClientSecret>"
6
+ #
7
+ # USAGE WAY 2:
8
+ # Qbox::Config.load "path/to/your_project/config/qiniu.yml"
9
+ #
10
+
11
+ require 'tmpdir'
12
+
13
+ module Qiniu
14
+ module Config
15
+ class << self
16
+
17
+ DEFAULT_OPTIONS = {
18
+ :user_agent => 'QiniuRuby/' + Version.to_s + ' ('+RUBY_PLATFORM+')' + ' Ruby/'+ RUBY_VERSION,
19
+ :method => :post,
20
+ :content_type => 'application/x-www-form-urlencoded',
21
+ :auth_url => "https://acc.qbox.me/oauth2/token",
22
+ :rs_host => "http://rs.qiniu.com",
23
+ :rsf_host => "http://rsf.qbox.me",
24
+ :up_host => "http://up.qiniu.com",
25
+ :pub_host => "http://pu.qbox.me:10200",
26
+ :eu_host => "http://eu.qbox.me",
27
+ :access_key => "",
28
+ :secret_key => "",
29
+ :auto_reconnect => true,
30
+ :max_retry_times => 3,
31
+ :block_size => 1024*1024*4,
32
+ :chunk_size => 1024*256,
33
+ :enable_debug => true,
34
+ :tmpdir => Dir.tmpdir + File::SEPARATOR + 'QiniuRuby'
35
+ }
36
+
37
+ REQUIRED_OPTION_KEYS = [:access_key, :secret_key, :up_host]
38
+
39
+ attr_reader :settings, :default_params
40
+
41
+ def load config_file
42
+ if File.exist?(config_file)
43
+ config_options = YAML.load_file(config_file)
44
+ config_options.symbolize_keys!
45
+ initialize_connect(config_options)
46
+ else
47
+ raise MissingConfError, config_file
48
+ end
49
+ end
50
+
51
+ def initialize_connect options = {}
52
+ @settings = DEFAULT_OPTIONS.merge!(options)
53
+ REQUIRED_OPTION_KEYS.each do |opt|
54
+ raise MissingArgsError, [opt] unless @settings.has_key?(opt)
55
+ end
56
+ end
57
+
58
+ end
59
+ end # module Config
60
+ end # module Qiniu
@@ -0,0 +1,120 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Qiniu
4
+
5
+ class Exception < RuntimeError
6
+ end
7
+
8
+ class ResponseError < Exception
9
+ attr_reader :response
10
+
11
+ def initialize(message, response = nil)
12
+ @response = response
13
+ super(message)
14
+ end
15
+
16
+ def http_code
17
+ @response.code.to_i if @response
18
+ end
19
+
20
+ def http_body
21
+ @response.body if @response
22
+ end
23
+
24
+ def inspect
25
+ "#{message}: #{http_body}"
26
+ end
27
+ end
28
+
29
+ class RequestFailed < ResponseError
30
+ def message
31
+ "HTTP status code: #{http_code}. Response body: #{http_body}"
32
+ end
33
+
34
+ def to_s
35
+ message
36
+ end
37
+ end
38
+
39
+ class UploadFailedError < Exception
40
+ def initialize(status_code, response_data)
41
+ data_string = response_data.map { |key, value| %Q(:#{key.to_s} => #{value.to_s}) }
42
+ msg = %Q(Uploading Failed. HTTP Status Code: #{status_code}. HTTP response body: #{data_string.join(', ')}.)
43
+ super(msg)
44
+ end
45
+ end
46
+
47
+ class FileSeekReadError < Exception
48
+ def initialize(fpath, block_index, seek_pos, read_length, result_length)
49
+ msg = "Reading file: #{fpath}, "
50
+ msg += "at block index: #{block_index}. "
51
+ msg += "Expected seek_pos:#{seek_pos} and read_length:#{read_length}, "
52
+ msg += "but got result_length: #{result_length}."
53
+ super(msg)
54
+ end
55
+ end
56
+
57
+ class BlockSizeNotMathchError < Exception
58
+ def initialize(fpath, block_index, offset, restsize, block_size)
59
+ msg = "Reading file: #{fpath}, "
60
+ msg += "at block index: #{block_index}. "
61
+ msg += "Expected offset: #{offset}, restsize: #{restsize} and block_size: #{block_size}, "
62
+ msg += "but got offset+restsize=#{offset+restsize}."
63
+ super(msg)
64
+ end
65
+ end
66
+
67
+ class BlockCountNotMathchError < Exception
68
+ def initialize(fpath, block_count, checksum_count, progress_count)
69
+ msg = "Reading file: #{fpath}, "
70
+ msg += "Expected block_count, checksum_count, progress_count is: #{block_count}, "
71
+ msg += "but got checksum_count: #{checksum_count}, progress_count: #{progress_count}."
72
+ super(msg)
73
+ end
74
+ end
75
+
76
+ class MissingArgsError < Exception
77
+ def initialize(missing_keys)
78
+ key_list = missing_keys.map {|key| key.to_s}.join(' and the ')
79
+ super("You did not provide both required args. Please provide the #{key_list}.")
80
+ end
81
+ end
82
+
83
+ class MissingAccessToken < MissingArgsError
84
+ def initialize
85
+ super([:access_token])
86
+ end
87
+ end
88
+
89
+ class MissingRefreshToken < MissingArgsError
90
+ def initialize
91
+ super([:refresh_token])
92
+ end
93
+ end
94
+
95
+ class MissingUsernameOrPassword < MissingArgsError
96
+ def initialize
97
+ super([:username, :password])
98
+ end
99
+ end
100
+
101
+ class InvalidArgsError < Exception
102
+ def initialize(invalid_keys)
103
+ key_list = invalid_keys.map {|key| key.to_s}.join(' and the ')
104
+ super("#{key_list} should not be empty.")
105
+ end
106
+ end
107
+
108
+ class MissingConfError < Exception
109
+ def initialize(missing_conf_file)
110
+ super("Error, missing #{missing_conf_file}. You must have #{missing_conf_file} to configure your client id and secret.")
111
+ end
112
+ end
113
+
114
+ class NoSuchFileError < Exception
115
+ def initialize(missing_file)
116
+ super("Error, no such file #{missing_file}.")
117
+ end
118
+ end
119
+
120
+ end # module Qiniu
data/lib/qiniu/fop.rb ADDED
@@ -0,0 +1,4 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'qiniu/image'
4
+ require 'qiniu/pfop'
data/lib/qiniu/http.rb ADDED
@@ -0,0 +1,137 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # vim: sw=2 ts=2
3
+
4
+ module Qiniu
5
+ module HTTP
6
+
7
+ class << self
8
+ public
9
+ def is_response_ok?(http_code)
10
+ return 200 <= http_code && http_code <= 299
11
+ end # is_response_ok?
12
+
13
+ def generate_query_string(params)
14
+ if params.is_a?(Hash)
15
+ total_param = params.map { |key, value| %Q(#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s).gsub('+', '%20')}) }
16
+ return total_param.join("&")
17
+ end
18
+
19
+ return params
20
+ end # generate_query_string
21
+
22
+ def get (url, opts = {})
23
+ ### 配置请求Header
24
+ req_headers = {
25
+ :connection => 'close',
26
+ :accept => '*/*',
27
+ :user_agent => Config.settings[:user_agent]
28
+ }
29
+
30
+ # 优先使用外部Header,覆盖任何特定Header
31
+ if opts[:headers].is_a?(Hash) then
32
+ req_headers.merge!(opts[:headers])
33
+ end
34
+
35
+ ### 发送请求
36
+ response = RestClient.get(url, req_headers)
37
+ return response.code.to_i, response.body, response.raw_headers
38
+ rescue => e
39
+ Log.logger.warn "#{e.message} => Qiniu::HTTP.get('#{url}')"
40
+ if e.respond_to?(:response) && e.response.respond_to?(:code) then
41
+ return e.response.code, e.response.body, e.response.raw_headers
42
+ end
43
+ return nil, nil, nil
44
+ end # get
45
+
46
+ API_RESULT_MIMETYPE = 'application/json'
47
+
48
+ def api_get (url, opts = {})
49
+ ### 配置请求Header
50
+ headers = {
51
+ :accept => API_RESULT_MIMETYPE
52
+ }
53
+
54
+ # 将特定Header混入外部Header中
55
+ if opts[:headers].is_a?(Hash) then
56
+ opts[:headers] = opts[:headers].dup.merge!(headers)
57
+ else
58
+ opts[:headers] = headers
59
+ end
60
+
61
+ ### 发送请求,然后转换返回值
62
+ resp_code, resp_body, resp_headers = get(url, opts)
63
+ if resp_code.nil? then
64
+ return 0, {}, {}
65
+ end
66
+
67
+ content_type = resp_headers["content-type"][0]
68
+ if !content_type.nil? && content_type == API_RESULT_MIMETYPE then
69
+ # 如果是JSON格式,则反序列化
70
+ resp_body = Utils.safe_json_parse(resp_body)
71
+ end
72
+
73
+ return resp_code, resp_body, resp_headers
74
+ end # api_get
75
+
76
+ def post (url, req_body = nil, opts = {})
77
+ ### 配置请求Header
78
+ req_headers = {
79
+ :connection => 'close',
80
+ :accept => '*/*',
81
+ :user_agent => Config.settings[:user_agent]
82
+ }
83
+
84
+ # 优先使用外部Header,覆盖任何特定Header
85
+ if opts[:headers].is_a?(Hash) then
86
+ req_headers.merge!(opts[:headers])
87
+ end
88
+
89
+ ### 发送请求
90
+ response = RestClient.post(url, req_body, req_headers)
91
+ return response.code.to_i, response.body, response.raw_headers
92
+ rescue => e
93
+ Log.logger.warn "#{e.message} => Qiniu::HTTP.post('#{url}')"
94
+ if e.respond_to?(:response) && e.response.respond_to?(:code) then
95
+ return e.response.code, e.response.body, e.response.raw_headers
96
+ end
97
+ return nil, nil, nil
98
+ end # post
99
+
100
+ def api_post (url, req_body = nil, opts = {})
101
+ ### 配置请求Header
102
+ headers = {
103
+ :accept => API_RESULT_MIMETYPE
104
+ }
105
+
106
+ # 将特定Header混入外部Header中
107
+ if opts[:headers].is_a?(Hash) then
108
+ opts[:headers] = opts[:headers].dup.merge!(headers)
109
+ else
110
+ opts[:headers] = headers
111
+ end
112
+
113
+ ### 发送请求,然后转换返回值
114
+ resp_code, resp_body, resp_headers = post(url, req_body, opts)
115
+ if resp_code.nil? then
116
+ return 0, {}, {}
117
+ end
118
+
119
+ content_type = resp_headers["content-type"][0]
120
+ if !content_type.nil? && content_type == API_RESULT_MIMETYPE then
121
+ # 如果是JSON格式,则反序列化
122
+ resp_body = Utils.safe_json_parse(resp_body)
123
+ end
124
+
125
+ return resp_code, resp_body, resp_headers
126
+ end # api_post
127
+
128
+ def management_post (url, body = '')
129
+ ### 授权并执行管理操作
130
+ return HTTP.api_post(url, body, {
131
+ :headers => { 'Authorization' => 'QBox ' + Auth.generate_acctoken(url, body) }
132
+ })
133
+ end # management_post
134
+ end # class << self
135
+
136
+ end # module HTTP
137
+ end # module Qiniu
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Qiniu
4
+ module Fop
5
+ module Image
6
+ class << self
7
+ include Utils
8
+
9
+ def info(url)
10
+ return HTTP.api_get(url + '?imageInfo')
11
+ end # info
12
+
13
+ def exif(url)
14
+ return HTTP.api_get(url + '?exif')
15
+ end # exif
16
+
17
+ def mogrify_preview_url(source_image_url, options)
18
+ source_image_url + '?' + generate_mogrify_params_string(options)
19
+ end
20
+
21
+ def generate_mogrify_params_string(options = {})
22
+ opts = {}
23
+ options.each do |k, v|
24
+ opts[k.to_s] = v
25
+ end
26
+ params_string = ""
27
+ keys = ["thumbnail", "gravity", "crop", "quality", "rotate", "format"]
28
+ keys.each do |key|
29
+ params_string += %Q(/#{key}/#{opts[key]}) unless opts[key].nil?
30
+ end
31
+ params_string += '/auto-orient' unless opts["auto_orient"].nil?
32
+ 'imageMogr' + URI.escape(params_string)
33
+ end
34
+
35
+ end
36
+ end # module Image
37
+ end # module Fop
38
+ end # module Qiniu
data/lib/qiniu/log.rb ADDED
@@ -0,0 +1,15 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'logger'
4
+
5
+ module Qiniu
6
+ module Log
7
+ class << self
8
+ attr_accessor :logger
9
+
10
+ def logger
11
+ @logger ||= Logger.new(STDERR)
12
+ end
13
+ end
14
+ end # module Log
15
+ end # module Qiniu