Integrating Akamai HTTP Downloads to your Rails Application

I recently had to integrate Akamai HTTP Downloads to a Rails project. The goal is to take advantage Akamai’s large global network of edge servers to serve large file downloads over HTTP to client browsers. These edge servers are distributed and optimized to cache and serve static contents to customers. They also decrease the load on the application servers. Since these large files (i.e. apps, games, tarballs, …etc.) remain static most of the time (except when there are new releases), it would be wasteful to transmit them using the application server’s bandwidth, which is better used to transmit dynamic content that can’t be cached.

First, you need to set up your Akamai configurations at Akamai EdgeControl HTTP Downloads Configurations, and download the URL-based token generator? and put them in RAILS_ROOT/lib. I will show how to use both the Perl and C versions.

To allow easier configuration, I set up a config/akamai.yml file that looks like:

production:
  protocol: http://
  domain: cdn.example.com
  keyname: __gda__
  window: 28800
  salt: secret
  tokenizer: perl
  extensions:
    - .zip
    - .exe
    - .msi
    - .dmg
    - .gz
    - .7z

Akamai only requires a token for files that have these extensions. For images and videos, you do not need to generate a token. The akamaized method first checks the file’s extension to determine if a token needs to be generated. If it does, the method calls the token generator to get a filename with the token appended. Finally, the complete Akamai URL is built with protocol, domain, and the new filename.

def akamaized(filename)
  extension = filename[filename.rindex(/\..*$/)..-1]
  if AKAMAI['extensions'].include?(extension)
    extension_fix = "?ext=#{extension}"
    filename_with_extension_fix = "#{filename}#{extension_fix}"
    filename_with_token = `#{AKAMAI['tokenizer']} -I '#{RAILS_ROOT}/lib/UrlAuthPerl-1.1.1' '#{RAILS_ROOT}/lib/UrlAuthPerl-1.1.1/akam-edge-auth-url.pl' '#{filename_with_extension_fix}' #{AKAMAI['keyname']} #{AKAMAI['window']} #{AKAMAI['salt']}`
    akamai_filename = "#{AKAMAI['protocol']}#{AKAMAI['domain']}#{filename_with_token}"
  else
    akamai_filename = "#{AKAMAI['protocol']}#{AKAMAI['domain']}#{filename}"
  end
end

Depending on how you manage file assets in your Rails application, you may choose how to use akamaized. For example, if you use attachment_fu for file uploads, you may want to override attachment_fu’s public_filename method and enable it only for production so that your developers can still call public_filename to take advantage of Akamai HTTP Downloads. It will be transparent to them.

I showed the Perl version first because both Mac and Linux have the standard Perl interpreter installed and it is more cross-platform-friendly. If you want to use the C version if that’s a bit faster, you would have in your config/akamai.yml:

  tokenizer: lib/URLAuthC-1.1.3/genURL

and your akamaized method:

    filename_with_token = `cd #{RAILS_ROOT}/#{AKAMAI['tokenizer'][0..AKAMAI['tokenizer'].rindex('/')]} ; .#{AKAMAI['tokenizer'][AKAMAI['tokenizer'].rindex('/')..-1]} -u '#{filename_with_extension_fix}' -p #{AKAMAI['keyname']} -w #{AKAMAI['window']} -s #{AKAMAI['salt']}`

This sums up how you can take advantage of Akamai HTTP Downloads to serve large static files faster to your users and decrease the load on your application server. In my next post, I will show how to use Akamai’s Content Control Utility API to purge cached content on the Akamai edge servers, so that you can make new releases of your apps, games, tarballs, …etc. readily available to your users.