98 lines
2.4 KiB
Ruby

require "remote_storage/rest_provider"
require "digest"
require "base64"
require "cgi"
require "openssl"
module RemoteStorage
class S3
include RestProvider
private
def s3_signer
signer ||= Aws::Sigv4::Signer.new(
service: 's3',
region: settings.s3["region"],
access_key_id: settings.s3["access_key_id"].to_s,
secret_access_key: settings.s3["secret_key_id"].to_s
)
end
# S3 already wraps the ETag with quotes
def format_etag(etag)
etag
end
def do_put_request(url, data, content_type)
deal_with_unauthorized_requests do
headers = { "Content-Type" => content_type }
auth_headers = auth_headers_for("PUT", url, headers, data)
res = RestClient.put(url, data, headers.merge(auth_headers))
return [
res.headers[:etag].delete('"'),
timestamp_for(res.headers[:date]) # S3 does not return a Last-Modified response header on PUTs
]
end
end
def do_get_request(url, &block)
deal_with_unauthorized_requests do
headers = {}
headers["Range"] = server.env["HTTP_RANGE"] if server.env["HTTP_RANGE"]
auth_headers = auth_headers_for("GET", url, headers)
RestClient.get(url, headers.merge(auth_headers), &block)
end
end
def do_head_request(url, &block)
deal_with_unauthorized_requests do
auth_headers = auth_headers_for("HEAD", url)
RestClient.head(url, auth_headers, &block)
end
end
def do_delete_request(url)
deal_with_unauthorized_requests do
auth_headers = auth_headers_for("DELETE", url)
RestClient.delete(url, auth_headers)
end
end
def try_to_delete(url)
found = true
begin
do_head_request(url)
rescue RestClient::ResourceNotFound
found = false
end
do_delete_request(url) if found
return found
end
def auth_headers_for(http_method, url, headers = {}, data = nil)
signature = s3_signer.sign_request(
http_method: http_method, url: url, headers: headers, body: data
)
signature.headers
end
def uri_escape(s)
CGI.escape(s).gsub('%5B', '[').gsub('%5D', ']')
end
def base_url
@base_url ||= settings.s3["endpoint"]
end
def container_url_for(user)
"#{base_url}/#{settings.s3["bucket"]}/#{user}"
end
end
end