Permalink
Browse files

Updated attachment_fu to add CloudFront support.

  • Loading branch information...
1 parent ab1e4f7 commit 48639bfdf142eefe2a32b54a09a039b924fcc3e7 Micah Wedemeyer committed Mar 15, 2009
Showing with 57 additions and 1 deletion.
  1. +3 −0 amazon_s3.yml.tpl
  2. +3 −0 lib/technoweenie/attachment_fu.rb
  3. +51 −1 lib/technoweenie/attachment_fu/backends/s3_backend.rb
View
@@ -2,13 +2,16 @@ development:
bucket_name: appname_development
access_key_id:
secret_access_key:
+ distribution_domain: XXXX.cloudfront.net
test:
bucket_name: appname_test
access_key_id:
secret_access_key:
+ distribution_domain: XXXX.cloudfront.net
production:
bucket_name: appname
access_key_id:
secret_access_key:
+ distribution_domain: XXXX.cloudfront.net
@@ -52,6 +52,8 @@ module ActMethods
# for the S3 backend. Setting this sets the :storage to :file_system.
# * <tt>:storage</tt> - Use :file_system to specify the attachment data is stored with the file system. Defaults to :db_system.
+ # * <tt>:cloundfront</tt> - Set to true if you are using S3 storage and want to serve the files through CloudFront. You will need to
+ # set a distribution domain in the amazon_s3.yml config file. Defaults to false
# * <tt>:bucket_key</tt> - Use this to specify a different bucket key other than :bucket_name in the amazon_s3.yml file. This allows you to use
# different buckets for different models. An example setting would be :image_bucket and the you would need to define the name of the corresponding
# bucket in the amazon_s3.yml file.
@@ -80,6 +82,7 @@ def has_attachment(options = {})
options[:thumbnails] ||= {}
options[:thumbnail_class] ||= self
options[:s3_access] ||= :public_read
+ options[:cloudfront] ||= false
options[:content_type] = [options[:content_type]].flatten.collect! { |t| t == :image ? Technoweenie::AttachmentFu.content_types : t }.flatten unless options[:content_type].nil?
unless options[:thumbnails].is_a?(Hash)
@@ -17,22 +17,28 @@ module Backends
# If you don't already have your access keys, all you need to sign up for the S3 service is an account at Amazon.
# You can sign up for S3 and get access keys by visiting http://aws.amazon.com/s3.
#
+ # If you wish to use Amazon CloudFront to serve the files, you can also specify a distibution domain for the bucket.
+ # To read more about CloudFront, visit http://aws.amazon.com/cloudfront
+ #
# Example configuration (RAILS_ROOT/config/amazon_s3.yml)
#
# development:
# bucket_name: appname_development
# access_key_id: <your key>
# secret_access_key: <your key>
+ # distribution_domain: XXXX.cloudfront.net
#
# test:
# bucket_name: appname_test
# access_key_id: <your key>
# secret_access_key: <your key>
+ # distribution_domain: XXXX.cloudfront.net
#
# production:
# bucket_name: appname
# access_key_id: <your key>
# secret_access_key: <your key>
+ # distribution_domain: XXXX.cloudfront.net
#
# You can change the location of the config path by passing a full path to the :s3_config_path option.
#
@@ -59,6 +65,8 @@ module Backends
# * <tt>:server</tt> - The server to make requests to. Defaults to <tt>s3.amazonaws.com</tt>.
# * <tt>:port</tt> - The port to the requests should be made on. Defaults to 80 or 443 if <tt>:use_ssl</tt> is set.
# * <tt>:use_ssl</tt> - If set to true, <tt>:port</tt> will be implicitly set to 443, unless specified otherwise. Defaults to false.
+ # * <tt>:distribution_domain</tt> - The CloudFront distribution domain for the bucket. This can either be the assigned
+ # distribution domain (ie. XXX.cloudfront.net) or a chosen domain using a CNAME. See CloudFront for more details.
#
# == Usage
#
@@ -150,6 +158,16 @@ module Backends
#
# Niether <tt>base_path</tt> or <tt>full_filename</tt> include the bucket name as part of the path.
# You can retrieve the bucket name using the <tt>bucket_name</tt> method.
+ #
+ # === Accessing CloudFront URLs
+ #
+ # You can get an object's CloudFront URL using the cloudfront_url accessor. Using the example from above:
+ # @postcard.cloudfront_url # => http://XXXX.cloudfront.net/photos/1/mexico.jpg
+ #
+ # The resulting url is in the form: http://:distribution_domain/:table_name/:id/:file
+ #
+ # If you set :cloudfront to true in your model, the public_filename will be the CloudFront
+ # URL, not the S3 URL.
module S3Backend
class RequiredLibraryNotFoundError < StandardError; end
class ConfigFileNotFoundError < StandardError; end
@@ -198,6 +216,10 @@ def self.hostname
def self.port_string
@port_string ||= (s3_config[:port].nil? || s3_config[:port] == (s3_config[:use_ssl] ? 443 : 80)) ? '' : ":#{s3_config[:port]}"
end
+
+ def self.distribution_domain
+ @distribution_domain = s3_config[:distribution_domain]
+ end
module ClassMethods
def s3_protocol
@@ -211,6 +233,10 @@ def s3_hostname
def s3_port_string
Technoweenie::AttachmentFu::Backends::S3Backend.port_string
end
+
+ def cloudfront_distribution_domain
+ Technoweenie::AttachmentFu::Backends::S3Backend.distribution_domain
+ end
end
# Overwrites the base filename writer in order to store the old filename
@@ -249,7 +275,27 @@ def full_filename(thumbnail = nil)
def s3_url(thumbnail = nil)
File.join(s3_protocol + s3_hostname + s3_port_string, bucket_name, full_filename(thumbnail))
end
- alias :public_filename :s3_url
+
+ # All public objects are accessible via a GET request to CloudFront. You can generate a
+ # url for an object using the cloudfront_url method.
+ #
+ # @photo.cloudfront_url
+ #
+ # The resulting url is in the form: <tt>http://:distribution_domain/:table_name/:id/:file</tt> using
+ # the <tt>:distribution_domain</tt> variable set in the configuration parameters in <tt>RAILS_ROOT/config/amazon_s3.yml</tt>.
+ #
+ # The optional thumbnail argument will output the thumbnail's filename (if any).
+ def cloudfront_url(thumbnail = nil)
+ "http://" + cloudfront_distribution_domain + "/" + full_filename(thumbnail)
+ end
+
+ def public_filename(*args)
+ if attachment_options[:cloudfront]
+ cloudfront_url(args)
+ else
+ s3_url(args)
+ end
+ end
# All private objects are accessible via an authenticated GET request to the S3 servers. You can generate an
# authenticated url for an object like this:
@@ -301,6 +347,10 @@ def s3_hostname
def s3_port_string
Technoweenie::AttachmentFu::Backends::S3Backend.port_string
end
+
+ def cloudfront_distribution_domain
+ Technoweenie::AttachmentFu::Backends::S3Backend.distribution_domain
+ end
protected
# Called in the after_destroy callback

0 comments on commit 48639bf

Please sign in to comment.