From b55b0f2e6e03cfee3ee784ce4fdf9a76c6b09d6d Mon Sep 17 00:00:00 2001 From: Dat Date: Fri, 26 Aug 2016 13:54:56 +0700 Subject: [PATCH] Add `:use_accelerate_endpoint` option when using S3 [Amazon S3 Transfer Acceleration](http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html) enables fast, easy, and secure transfers of files over long distances between your client and an S3 bucket. And [aws-sdk](https://github.com/aws/aws-sdk-ruby) has allowed us to enable this feature in version 2.3.0 (more detail is [here](https://github.com/aws/aws-sdk-ruby/pull/1163)). You can now pass a configuration option (:use_accelerate_endpoint) when config Paperclip with S3. You can enable the [Amazon S3 Transfer Acceleration](http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html) by set this option: ```:use_accelerate_endpoint => true``` [fixes #2291] --- NEWS | 2 + lib/paperclip/storage/s3.rb | 15 +++++++ spec/paperclip/storage/s3_spec.rb | 53 +++++++++++++++++++++++ spec/spec_helper.rb | 1 + spec/support/conditional_filter_helper.rb | 5 +++ 5 files changed, 76 insertions(+) create mode 100644 spec/support/conditional_filter_helper.rb diff --git a/NEWS b/NEWS index 04a846dbb..91c509f70 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,7 @@ master: +* Improvement: Added `:use_accelerate_endpoint` option when using S3 to enable + [Amazon S3 Transfer Acceleration](http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html) * Improvement: make the fingerprint digest configurable per attachment. The default remains MD5 but this will change in a future version because it is not considered secure anymore against intentional file corruption. For more diff --git a/lib/paperclip/storage/s3.rb b/lib/paperclip/storage/s3.rb index d0b1755ca..5a3fd6635 100644 --- a/lib/paperclip/storage/s3.rb +++ b/lib/paperclip/storage/s3.rb @@ -102,6 +102,8 @@ module Storage # Redundancy Storage. RRS enables customers to reduce their # costs by storing non-critical, reproducible data at lower # levels of redundancy than Amazon S3's standard storage. + # * +use_accelerate_endpoint+: Use accelerate endpoint + # http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html # # You can set storage class on a per style bases by doing the following: # :s3_storage_class => { @@ -152,6 +154,13 @@ def self.extended base @options[:url] = @options[:url].inspect if @options[:url].is_a?(Symbol) @http_proxy = @options[:http_proxy] || nil + + if @options.has_key?(:use_accelerate_endpoint) && + Gem::Version.new(Aws::VERSION) < Gem::Version.new("2.3.0") + raise LoadError, ":use_accelerate_endpoint is only available from aws-sdk version 2.3.0. Please upgrade aws-sdk to a newer version." + end + + @use_accelerate_endpoint = @options[:use_accelerate_endpoint] end Paperclip.interpolates(:s3_alias_url) do |attachment, style| @@ -232,6 +241,8 @@ def s3_interface config[:proxy_uri] = URI::HTTP.build(proxy_opts) end + config[:use_accelerate_endpoint] = use_accelerate_endpoint? + [:access_key_id, :secret_access_key, :credential_provider, :credentials].each do |opt| config[opt] = s3_credentials[opt] if s3_credentials[opt] end @@ -257,6 +268,10 @@ def s3_object style_name = default_style s3_bucket.object style_name_as_path(style_name) end + def use_accelerate_endpoint? + !!@use_accelerate_endpoint + end + def using_http_proxy? !!@http_proxy end diff --git a/spec/paperclip/storage/s3_spec.rb b/spec/paperclip/storage/s3_spec.rb index 036c98aca..55b86c216 100644 --- a/spec/paperclip/storage/s3_spec.rb +++ b/spec/paperclip/storage/s3_spec.rb @@ -282,6 +282,59 @@ class << @dummy end end + context "use_accelerate_endpoint", if: aws_accelerate_available? do + context "defaults to false" do + before do + rebuild_model( + storage: :s3, + s3_credentials: {}, + bucket: "bucket", + path: ":attachment/:basename:dotextension", + s3_host_name: "s3-ap-northeast-1.amazonaws.com", + s3_region: "ap-northeast-1", + ) + @dummy = Dummy.new + @dummy.avatar = stringy_file + @dummy.stubs(:new_record?).returns(false) + end + + it "returns a url based on an :s3_host_name path" do + assert_match %r{^//s3-ap-northeast-1.amazonaws.com/bucket/avatars/data[^\.]}, + @dummy.avatar.url + end + + it "uses the S3 client with the use_accelerate_endpoint config is false" do + expect(@dummy.avatar.s3_bucket.client.config.use_accelerate_endpoint).to be(false) + end + end + + context "set to true", if: aws_accelerate_available? do + before do + rebuild_model( + storage: :s3, + s3_credentials: {}, + bucket: "bucket", + path: ":attachment/:basename:dotextension", + s3_host_name: "s3-accelerate.amazonaws.com", + s3_region: "ap-northeast-1", + use_accelerate_endpoint: true, + ) + @dummy = Dummy.new + @dummy.avatar = stringy_file + @dummy.stubs(:new_record?).returns(false) + end + + it "returns a url based on an :s3_host_name path" do + assert_match %r{^//s3-accelerate.amazonaws.com/bucket/avatars/data[^\.]}, + @dummy.avatar.url + end + + it "uses the S3 client with the use_accelerate_endpoint config is true" do + expect(@dummy.avatar.s3_bucket.client.config.use_accelerate_endpoint).to be(true) + end + end + end + context "An attachment that uses S3 for storage and has styles that return different file types" do before do rebuild_model (aws2_add_region).merge storage: :s3, diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 92e7f431f..eed5d6313 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -38,6 +38,7 @@ config.include TestData config.include Reporting config.extend VersionHelper + config.extend ConditionalFilterHelper config.mock_framework = :mocha config.before(:all) do rebuild_model diff --git a/spec/support/conditional_filter_helper.rb b/spec/support/conditional_filter_helper.rb new file mode 100644 index 000000000..1277552e7 --- /dev/null +++ b/spec/support/conditional_filter_helper.rb @@ -0,0 +1,5 @@ +module ConditionalFilterHelper + def aws_accelerate_available? + (Gem::Version.new(Aws::VERSION) >= Gem::Version.new("2.3.0")) + end +end