qiniu_jxb_fix 6.4.2

Sign up to get free protection for your applications and to get access to all the features.
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