lib/carrierwave/storage/upyun.rb in carrierwave-upyun-1.0.0 vs lib/carrierwave/storage/upyun.rb in carrierwave-upyun-1.0.1
- old
+ new
@@ -1,6 +1,7 @@
-# coding: utf-8
+# frozen_string_literal: true
+
require "faraday"
module CarrierWave
module Storage
##
@@ -13,12 +14,15 @@
# config.upyun_api_host = "http://v0.api.upyun.com"
# end
#
#
class UpYun < Abstract
- DEFAULT_API_URL = 'http://v0.api.upyun.com'
+ DEFAULT_API_URL = "http://v0.api.upyun.com"
+ class UploadError < RuntimeError; end
+ class ConcurrentUploadError < RuntimeError; end
+
class File < CarrierWave::SanitizedFile
def initialize(uploader, base, path)
@uploader = uploader
@path = path
@base = base
@@ -29,25 +33,21 @@
#
# === Returns
#
# [String] A path
#
- def path
- @path
- end
+ attr_reader :path
def escaped_path
@escaped_path ||= CGI.escape(@path)
end
def content_type
@content_type || ""
end
- def content_type=(new_content_type)
- @content_type = new_content_type
- end
+ attr_writer :content_type
##
# Reads the contents of the file from Cloud Files
#
# === Returns
@@ -62,17 +62,15 @@
##
# Remove the file from Cloud Files
#
def delete
- begin
- conn.delete(escaped_path)
- true
- rescue => e
- puts "carrierwave-upyun delete failed: #{e.inspect}"
- nil
- end
+ conn.delete(escaped_path)
+ true
+ rescue StandardError => e
+ puts "carrierwave-upyun delete failed: #{e.inspect}"
+ nil
end
##
# Returns the url on the Cloud Files CDN. Note that the parent container must be marked as
# public for this to work.
@@ -81,10 +79,11 @@
#
# [String] file's url
#
def url
return nil unless @uploader.upyun_bucket_host
+
[@uploader.upyun_bucket_host, @path].join("/")
end
def content_type
headers[:content_type]
@@ -99,38 +98,46 @@
#
# === Returns
#
# boolean
#
- def store(data, headers = {})
- res = conn.put(escaped_path, data) do |req|
- req.headers = {'Expect' => '', 'Mkdir' => 'true'}.merge(headers)
+ def store(new_file, headers = {})
+ res = conn.put(escaped_path, new_file.read) do |req|
+ req.headers = { "Expect" => "", "Mkdir" => "true" }.merge(headers)
end
+
if res.status != 200
- puts "Update failed: #{res.body}"
- return false
+ # code: 42900007 -> concurrent put or delete
+ json = JSON.parse(res.body)
+ # retry upload
+ raise ConcurrentUploadError, res.body if json["code"] == 42_900_007
+
+ raise UploadError, res.body
end
true
+ rescue ConcurrentUploadError => e
+ puts "Warning: UpYun error #{e.message}, retry again."
+ retry
end
def headers
@headers ||= begin
conn.get(@path).headers
- rescue Faraday::ClientError
- {}
+ rescue Faraday::ClientError
+ {}
end
end
def conn
- return @conn if defined?(@conn)
-
- api_host = @uploader.upyun_api_host || DEFAULT_API_URL
- @conn = Faraday.new(url: "#{api_host}/#{@uploader.upyun_bucket}") do |req|
- req.request :basic_auth, @uploader.upyun_username, @uploader.upyun_password
- req.request :url_encoded
- req.adapter Faraday.default_adapter
+ @conn ||= begin
+ api_host = @uploader.upyun_api_host || DEFAULT_API_URL
+ Faraday.new(url: "#{api_host}/#{@uploader.upyun_bucket}") do |req|
+ req.request :basic_auth, @uploader.upyun_username, @uploader.upyun_password
+ req.request :url_encoded
+ req.adapter Faraday.default_adapter
+ end
end
end
end # File
##
@@ -144,11 +151,11 @@
#
# [CarrierWave::Storage::UpYun::File] the stored file
#
def store!(file)
f = File.new(uploader, self, uploader.store_path)
- f.store(file.read, 'Content-Type' => file.content_type)
+ f.store(file, "Content-Type" => file.content_type)
f
end
# Do something to retrieve the file
#
@@ -163,22 +170,20 @@
def retrieve!(identifier)
File.new(uploader, self, uploader.store_path(identifier))
end
def cache!(file)
- f = File.new(uploader, self, uploader.store_path)
- f.store(file.read, 'Content-Type' => file.content_type)
+ f = File.new(uploader, self, uploader.cache_path)
+ f.store(file, "Content-Type" => file.content_type)
f
end
def retrieve_from_cache!(identifier)
File.new(uploader, self, uploader.cache_path(identifier))
end
- def delete_dir!(path)
- end
+ def delete_dir!(path); end
- def clean_cache!(seconds)
- end
+ def clean_cache!(seconds); end
end # CloudFiles
end # Storage
end # CarrierWave