将HTTP事务相关的代码提取到独立的类中。

This commit is contained in:
Liang Tao
2014-04-03 00:38:00 +08:00
parent 3f4c79b78f
commit efe6b50c50
8 changed files with 214 additions and 66 deletions
+2 -2
View File
@@ -64,7 +64,7 @@ module Qiniu
opts[:enable_resumable_upload] = true unless opts.has_key?(:enable_resumable_upload)
if opts[:enable_resumable_upload] && File::size(source_file) > Config.settings[:block_size]
code, data = Storage.upload_with_token(opts[:uptoken],
code, data, raw_headers = Storage.upload_with_token(opts[:uptoken],
opts[:file],
opts[:bucket],
opts[:key],
@@ -74,7 +74,7 @@ module Qiniu
opts[:callback_params],
opts[:rotate])
else
code, data = Storage.upload_with_token(opts[:uptoken],
code, data, raw_headers = Storage.upload_with_token(opts[:uptoken],
opts[:file],
opts[:bucket],
opts[:key],
-16
View File
@@ -132,22 +132,6 @@ module Qiniu
end # class PutPolicy
class << self
include Utils
def call_with_signature(url, data, retry_times = 0, options = {})
return Utils.http_request(
url,
data,
options.merge({:qbox_signature_token => generate_acctoken(url, data)})
)
end # call_with_signature
def request(url, data = nil, options = {})
code, data, raw_headers = Auth.call_with_signature(url, data, 0, options)
[code, data, raw_headers]
end # request
EMPTY_ARGS = {}
### 生成下载授权URL
+137
View File
@@ -0,0 +1,137 @@
# -*- encoding: utf-8 -*-
# vim: sw=2 ts=2
require 'json'
module Qiniu
module HTTP
class << self
public
def is_response_ok?(http_code)
return 200 <= http_code && http_code <= 299
end # is_response_ok?
def safe_json_parse(data)
JSON.parse(data)
rescue JSON::ParserError
{}
end # safe_json_parse
def generate_query_string(params)
if params.is_a?(Hash)
total_param = params.map { |key, value| %Q(#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s).gsub('+', '%20')}) }
return total_param.join("&")
end
return params
end # generate_query_string
def get (url, opts = {})
### 配置请求Header
req_headers = {
:accept => '*/*',
:user_agent => Config.settings[:user_agent]
}
# 优先使用外部Header,覆盖任何特定Header
if opts[:headers].is_a?(Hash) then
req_headers.merge!(opts[:headers])
end
### 发送请求
response = RestClient.get(url, req_headers)
return response.code.to_i, response.body, response.raw_headers
rescue => e
Log.logger.warn "#{e.message} => Qiniu::HTTP.get('#{url}')"
return nil, nil, nil
end # get
API_RESULT_MIMETYPE = 'application/json'
def api_get (url, opts = {})
### 配置请求Header
headers = {
:accept => API_RESULT_MIMETYPE
}
# 将特定Header混入外部Header中
if opts[:headers].is_a?(Hash) then
opts[:headers] = opts[:headers].dup.merge!(headers)
else
opts[:headers] = headers
end
### 发送请求,然后转换返回值
resp_code, resp_body, resp_headers = get(url, opts)
if resp_code.nil? then
return 0, {}, {}
end
content_type = resp_headers["content-type"][0]
if !content_type.nil? && content_type == API_RESULT_MIMETYPE then
# 如果是JSON格式,则反序列化
resp_body = safe_json_parse(resp_body)
end
return resp_code, resp_body, resp_headers
end # api_get
def post (url, req_body = nil, opts = {})
### 配置请求Header
req_headers = {
:accept => '*/*',
:user_agent => Config.settings[:user_agent]
}
# 优先使用外部Header,覆盖任何特定Header
if opts[:headers].is_a?(Hash) then
req_headers.merge!(opts[:headers])
end
### 发送请求
response = RestClient.post(url, req_body, req_headers)
return response.code.to_i, response.body, response.raw_headers
rescue => e
Log.logger.warn "#{e.message} => Qiniu::HTTP.post('#{url}')"
return nil, nil, nil
end # post
def api_post (url, req_body = nil, opts = {})
### 配置请求Header
headers = {
:accept => API_RESULT_MIMETYPE
}
# 将特定Header混入外部Header中
if opts[:headers].is_a?(Hash) then
opts[:headers] = opts[:headers].dup.merge!(headers)
else
opts[:headers] = headers
end
### 发送请求,然后转换返回值
resp_code, resp_body, resp_headers = post(url, req_body, opts)
if resp_code.nil? then
return 0, {}, {}
end
content_type = resp_headers["content-type"][0]
if !content_type.nil? && content_type == API_RESULT_MIMETYPE then
# 如果是JSON格式,则反序列化
resp_body = safe_json_parse(resp_body)
end
return resp_code, resp_body, resp_headers
end # api_post
def management_post (url, body = '')
### 授权并执行管理操作
return HTTP.api_post(url, body, {
:headers => { 'Authorization' => 'QBox ' + Auth.generate_acctoken(url, body) }
})
end # management_post
end # class << self
end # module HTTP
end # module Qiniu
+2 -2
View File
@@ -7,11 +7,11 @@ module Qiniu
include Utils
def info(url)
Utils.http_request url + '?imageInfo', nil, {:method => :get}
return HTTP.api_get(url + '?imageInfo')
end # info
def exif(url)
Utils.http_request url + '?exif', nil, {:method => :get}
return HTTP.api_get(url + '?exif')
end # exif
def mogrify_preview_url(source_image_url, options)
+30 -15
View File
@@ -1,31 +1,38 @@
# -*- encoding: utf-8 -*-
# vim: sw=2 ts=2
require 'qiniu/http'
module Qiniu
module Storage
class << self
include Utils
public
def buckets
Auth.request Config.settings[:rs_host] + '/buckets'
url = Config.settings[:rs_host] + '/buckets'
return HTTP.management_post(url)
end # buckets
PRIVATE_BUCKET = 0
PUBLIC_BUCKET = 1
def mkbucket(bucket_name, is_public = PUBLIC_BUCKET)
Auth.request Config.settings[:rs_host] + '/mkbucket2/' + bucket_name + '/public/' + is_public.to_s
url = Config.settings[:rs_host] + '/mkbucket2/' + bucket_name + '/public/' + is_public.to_s
return HTTP.management_post(url)
end # mkbucket
def make_a_private_bucket(bucket_name)
return mkbucket(bucket_name, PRIVATE_BUCKET)
return mkbucket(bucket_name, PRIVATE_BUCKET)
end # make_a_private_bucket
def make_a_public_bucket(bucket_name)
return mkbucket(bucket_name, PUBLIC_BUCKET)
return mkbucket(bucket_name, PUBLIC_BUCKET)
end # make_a_public_bucket
def stat(bucket, key)
Auth.request Config.settings[:rs_host] + '/stat/' + encode_entry_uri(bucket, key)
url = Config.settings[:rs_host] + '/stat/' + encode_entry_uri(bucket, key)
return HTTP.management_post(url)
end # stat
def get(bucket, key, save_as = nil, expires_in = nil, version = nil)
@@ -33,35 +40,41 @@ module Qiniu
url += '/base/' + version unless version.nil?
url += '/attName/' + Utils.urlsafe_base64_encode(save_as) unless save_as.nil?
url += '/expires/' + expires_in.to_s if !expires_in.nil? && expires_in > 0
Auth.request url
return HTTP.management_post(url)
end # get
def copy(source_bucket, source_key, target_bucket, target_key)
uri = _generate_cp_or_mv_opstr('copy', source_bucket, source_key, target_bucket, target_key)
Auth.request Config.settings[:rs_host] + uri
url = Config.settings[:rs_host] + uri
return HTTP.management_post(url)
end # copy
def move(source_bucket, source_key, target_bucket, target_key)
uri = _generate_cp_or_mv_opstr('move', source_bucket, source_key, target_bucket, target_key)
Auth.request Config.settings[:rs_host] + uri
url = Config.settings[:rs_host] + uri
return HTTP.management_post(url)
end # move
def delete(bucket, key)
Auth.request Config.settings[:rs_host] + '/delete/' + encode_entry_uri(bucket, key)
url = Config.settings[:rs_host] + '/delete/' + encode_entry_uri(bucket, key)
return HTTP.management_post(url)
end # delete
def publish(domain, bucket)
encoded_domain = Utils.urlsafe_base64_encode(domain)
Auth.request Config.settings[:rs_host] + "/publish/#{encoded_domain}/from/#{bucket}"
url = Config.settings[:rs_host] + "/publish/#{encoded_domain}/from/#{bucket}"
return HTTP.management_post(url)
end # publish
def unpublish(domain)
encoded_domain = Utils.urlsafe_base64_encode(domain)
Auth.request Config.settings[:rs_host] + "/unpublish/#{encoded_domain}"
url = Config.settings[:rs_host] + "/unpublish/#{encoded_domain}"
return HTTP.management_post(url)
end # unpublish
def drop(bucket)
Auth.request Config.settings[:rs_host] + "/drop/#{bucket}"
url = Config.settings[:rs_host] + "/drop/#{bucket}"
return HTTP.management_post(url)
end # drop
def batch(command, bucket, keys)
@@ -70,7 +83,8 @@ module Qiniu
encoded_uri = encode_entry_uri(bucket, key)
execs << "op=/#{command}/#{encoded_uri}"
end
Auth.request Config.settings[:rs_host] + "/batch", execs.join("&"), {:mime => "application/x-www-form-urlencoded" }
url = Config.settings[:rs_host] + "/batch"
return HTTP.management_post(url, execs.join("&"))
end # batch
def batch_get(bucket, keys)
@@ -97,7 +111,7 @@ module Qiniu
encoded_uri = encode_entry_uri(bucket, key)
save_as_string = '/save-as/' + encoded_uri
new_url = source_url + '?' + op_params_string + save_as_string
Auth.request new_url
return HTTP.management_post(new_url)
end # save_as
def image_mogrify_save_as(bucket, key, source_image_url, options)
@@ -118,7 +132,8 @@ module Qiniu
op_args.each do |e|
execs << 'op=' + _generate_cp_or_mv_opstr(command, e[0], e[1], e[2], e[3]) if e.size == 4
end
Auth.request Config.settings[:rs_host] + "/batch", execs.join("&"), {:mime => "application/x-www-form-urlencoded" }
url = Config.settings[:rs_host] + "/batch"
return HTTP.management_post(url, execs.join("&"))
end # _batch_cp_or_mv
end
end # module Storage
+13 -15
View File
@@ -3,33 +3,31 @@
module Qiniu
module Misc
class << self
include Utils
def set_protected(bucket, protected_mode)
host = Config.settings[:pub_host]
Auth.request %Q(#{host}/accessMode/#{bucket}/mode/#{protected_mode})
end
url = Config.settings[:pub_host] + %Q(/accessMode/#{bucket}/mode/#{protected_mode})
return HTTP.management_post(url)
end # set_protected
def set_separator(bucket, separator)
host = Config.settings[:pub_host]
encoded_separator = Utils.urlsafe_base64_encode(separator)
Auth.request %Q(#{host}/separator/#{bucket}/sep/#{encoded_separator})
end
url = Config.settings[:pub_host] + %Q(/separator/#{bucket}/sep/#{encoded_separator})
return HTTP.management_post(url)
end # set_separator
def set_style(bucket, name, style)
host = Config.settings[:pub_host]
encoded_name = Utils.urlsafe_base64_encode(name)
encoded_style = Utils.urlsafe_base64_encode(style)
Auth.request %Q(#{host}/style/#{bucket}/name/#{encoded_name}/style/#{encoded_style})
end
url = Config.settings[:pub_host] + %Q(/style/#{bucket}/name/#{encoded_name}/style/#{encoded_style})
return HTTP.management_post(url)
end # set_style
def unset_style(bucket, name)
host = Config.settings[:pub_host]
encoded_name = Utils.urlsafe_base64_encode(name)
Auth.request %Q(#{host}/unstyle/#{bucket}/name/#{encoded_name})
end
url = Config.settings[:pub_host] + %Q(/unstyle/#{bucket}/name/#{encoded_name})
return HTTP.management_post(url)
end # unset_style
end # class << self
end
end # module Misc
end # module Qiniu
+16 -12
View File
@@ -97,13 +97,17 @@ module Qiniu
def _call_binary_with_token(uptoken, url, data, content_type = nil, retry_times = 0)
options = {
:method => :post,
:content_type => 'application/octet-stream',
:upload_signature_token => uptoken
:headers => {
:content_type => 'application/octet-stream',
'Authorization' => 'UpToken ' + uptoken
}
}
options[:content_type] = content_type if !content_type.nil? && !content_type.empty?
code, data = http_request url, data, options
unless Utils.is_response_ok?(code)
if !content_type.nil? && !content_type.empty? then
options[:headers][:content_type] = content_type
end
code, data = HTTP.api_post(url, data, options)
unless HTTP.is_response_ok?(code)
retry_times += 1
if Config.settings[:auto_reconnect] && retry_times < Config.settings[:max_retry_times]
return _call_binary_with_token(uptoken, url, data, options[:content_type], retry_times)
@@ -148,7 +152,7 @@ module Qiniu
end
code, data = _mkblock(uptoken, block_size, body)
body_crc32 = Zlib.crc32(body)
if Utils.is_response_ok?(code) && data["crc32"] == body_crc32
if HTTP.is_response_ok?(code) && data["crc32"] == body_crc32
progress[:ctx] = data["ctx"]
progress[:offset] = body_length
progress[:restsize] = block_size - body_length
@@ -179,7 +183,7 @@ module Qiniu
end
code, data = _putblock(progress[:host], uptoken, progress[:ctx], progress[:offset], body)
body_crc32 = Zlib.crc32(body)
if Utils.is_response_ok?(code) && data["crc32"] == body_crc32
if HTTP.is_response_ok?(code) && data["crc32"] == body_crc32
progress[:ctx] = data["ctx"]
progress[:offset] += body_length
progress[:restsize] -= body_length
@@ -228,7 +232,7 @@ module Qiniu
#code, data = _resumable_put_block(uptoken, fh, block_index, block_size, Config.settings[:chunk_size], progresses[block_index], Config.settings[:max_retry_times], chunk_notifier)
# Put the whole block as a chunk
code, data = _resumable_put_block(uptoken, fh, block_index, block_size, block_size, progresses[block_index], Config.settings[:max_retry_times], chunk_notifier)
if Utils.is_response_ok?(code)
if HTTP.is_response_ok?(code)
#checksums[block_index] = data["checksum"]
checksums[block_index] = data["ctx"]
if !block_notifier.nil? && block_notifier.respond_to?("notify")
@@ -254,7 +258,7 @@ module Qiniu
path += '/mimeType/' + Utils.urlsafe_base64_encode(mime_type) if !mime_type.nil? && !mime_type.empty?
path += '/meta/' + Utils.urlsafe_base64_encode(custom_meta) if !custom_meta.nil? && !custom_meta.empty?
path += '/customer/' + customer if !customer.nil? && !customer.empty?
callback_query_string = Utils.generate_query_string(callback_params) if !callback_params.nil? && !callback_params.empty?
callback_query_string = HTTP.generate_query_string(callback_params) if !callback_params.nil? && !callback_params.empty?
path += '/params/' + Utils.urlsafe_base64_encode(callback_query_string) if !callback_query_string.nil? && !callback_query_string.empty?
path += '/rotate/' + rotate if !rotate.nil? && rotate.to_i >= 0
url = uphost + path
@@ -289,13 +293,13 @@ module Qiniu
code, data = _resumable_put(uptoken, fh, checksums, progresses, block_notifier, chunk_notifier)
if Utils.is_response_ok?(code)
if HTTP.is_response_ok?(code)
uphost = data["host"]
entry_uri = bucket + ':' + key
code, data = _mkfile(uphost, uptoken, entry_uri, fsize, checksums, mime_type, custom_meta, customer, callback_params, rotate)
end
if Utils.is_response_ok?(code)
if HTTP.is_response_ok?(code)
Utils.debug "File #{fh.path} {size: #{fsize}} successfully uploaded."
end
+14 -4
View File
@@ -28,10 +28,20 @@ module Qiniu
if callback_params.nil?
callback_params = {:bucket => bucket, :key => key, :mime_type => mime_type}
end
callback_query_string = Utils.generate_query_string(callback_params)
url = Config.settings[:up_host] + '/upload'
callback_query_string = HTTP.generate_query_string(callback_params)
Utils.upload_multipart_data(url, local_file, action_params, callback_query_string, uptoken)
url = Config.settings[:up_host] + '/upload'
post_data = {
:params => callback_query_string,
:action => action_params,
:file => File.new(local_file, 'rb'),
:multipart => true
}
if !uptoken.nil? then
post_data[:auth] = uptoken unless uptoken.nil?
end
return HTTP.api_post(url, post_data)
end # upload_with_token
def upload_with_token_2(uptoken,
@@ -59,7 +69,7 @@ module Qiniu
end
### 发送请求
Utils.http_request url, post_data
HTTP.api_post(url, post_data)
end # upload_with_token_2
### 授权举例