Amazon CloudFront
Do you have content that needs to be served fast and cheap, but you’re finding traditional content delivery options are far too expensive? Amazon’s new CloudFront service is a low-cost content delivery network utilizing Amazon S3, and it may be just the answer for you.
Welcome to the Cloud! I’m glad you’ve joined me here for a monthly look at the services and technologies of the intelligent Web. I’ll be looking at practical services you can use, as well as exploring trends that are transforming the way we use the Web.
I find it fitting that this inaugural edition of From the Cloud covers the Amazon CloudFront web service because, while CloudFront is not revolutionizing the Web – there are a host of similar services already – it is lowering the barriers to entry for small- and medium-sized businesses, allowing them to take advantage of a low-cost content delivery network.
What Is Amazon CloudFront?
Amazon CloudFront is Amazon’s web service for content delivery. It acts as a content delivery network (CDN) for objects stored in Amazon Simple Storage Service (S3), and can be compared to other CDNs like Akamai and Limelight Networks.
Amazon CloudFront acts like other CDNs by propagating objects (files) from an origin server (an S3 bucket) to edge locations throughout the world, where the objects are cached for twenty-four hours. This reduces the roundtrip request time from an end user to the objects by copying the object to the edge location closest to the user. Currently, CloudFront has edge locations in the US, Europe, and Asia.
Amazon CloudFront is a pay-as-you-go service, and it’s inexpensive. There are no set-up fees or minimum charges. You pay only for what you use. For example, to prepare for this column, I used a single 24 KB image in S3 and distributed it through CloudFront. The total cost of my tests was $0.06 USD.
To use CloudFront, you’ll need to register for Amazon S3, but Amazon makes this process easy, registering you for both at the same time. To sign up for the services, go to http://aws.amazon.com/. This article does not cover interaction with S3, so you’ll need to find a client that allows you to upload content to S3. I found Amazon S3 Browser for the Mac and CloudBerry Explorer for Windows (see Related Links), both of which appear to be good.
Getting Started
There are six basic ways you can interact with Amazon CloudFront through its RESTful API. You may create distributions, list your distributions, retrieve a distribution, retrieve a distribution’s configuration, update a distribution’s configuration, and delete a distribution.
I’ll show examples of both raw HTTP requests and PHP code that makes these requests for you. To use the PHP code examples, download the 0.1.0-preview release of the Amazon CloudFront library from http://awsphp.googlecode.com/ and place the library/Amazon/
folder in your include path.
The first step is to set up the Amazon_CloudFront object with your Amazon Web Services Access Key ID and Secret Access Key. I’ve identified these with the constants ACCESS_KEY
and SECRET_KEY
. All examples use the same Amazon_CloudFront object, which may be instantiated like this:
require_once 'Amazon/CloudFront.php';
$cloudfront = new Amazon_CloudFront(ACCESS_KEY, SECRET_KEY);
The Amazon_CloudFront object will take care of the proper HTTP Authorization header, so I won’t cover how to generate it. If you’re interested in how to create the authentication string, the developer documentation for CloudFront covers this in detail.
Listing Distributions
To retrieve a list of your Amazon CloudFront distributions, make a GET request to /2008-06-30/distribution
, the base request URI for the service. Listing 1 shows an example of this request.
GET /2008-06-30/distribution HTTP/1.1
Host: cloudfront.amazonaws.com
Date: Sun, 28 Dec 2008 22:39:50 GMT
x-amz-date: Sun, 28 Dec 2008 22:39:50 GMT
Authorization: [authentication string]
Connection: close
HTTP/1.1 200 OK
Content-Type: text/xml
Transfer-Encoding: chunked
Date: Sun, 28 Dec 2008 22:39:50 GMT
Server: CloudFront
<?xml version="1.0"?>
<DistributionList xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">
<Marker></Marker>
<MaxItems>100</MaxItems>
<IsTruncated>false</IsTruncated>
<DistributionSummary>
<Id>E3SNLLVFZ6ABAC</Id>
<Status>Deployed</Status>
<LastModifiedTime>2008-12-28T03:36:17.158Z</LastModifiedTime>
<DomainName>d3e7a6gmq12l7y.cloudfront.net</DomainName>
<Origin>phpawebservices.s3.amazonaws.com</Origin>
<Comment>php|architect Web Services column</Comment>
<Enabled>true</Enabled>
</DistributionSummary>
</DistributionList>
The response returned is an XML document with a root DistributionList element containing multiple DistributionSummary elements, each representing one of your distributions. If you have not yet created any distributions, then there will be no DistributionSummary elements.
To send this request using the Amazon CloudFront library, simply call the getDistributionList() method on the Amazon_CloudFront object. This will return an Amazon_Distribution_List object, which extends PHP’s ArrayObject, so it may be iterated over, as seen in this example:
$list = $cloudfront->getDistributionList();
foreach ($list as $distribution) {
echo $distribution->getId() . "\n";
echo $distribution->getConfig()->getOrigin() . "\n";
echo $distribution->getDomainName() . "\n\n";
}
You’ll also notice several other elements in the response: Marker
, MaxItems
, and IsTruncated
. CloudFront uses these for pagination of the distribution list. For example, you may pass Marker and MaxItems as query string parameters in the request. Their respective XML elements will be populated with the values passed. If there are multiple pages of results, then IsTruncated
will contain the value true
and a NextMarker
element will be set, allowing you to pass its value as the Marker parameter of the query string when retrieving the next page of results.
Creating a New Distribution
When you first set up your Amazon CloudFront account, you won’t have any distributions. To create a distribution, make a POST request to the /2008-06-30/distribution
URI and include an XML document with a root DistributionConfig
element.
POST /2008-06-30/distribution HTTP/1.1
Host: cloudfront.amazonaws.com
Date: Sun, 28 Dec 2008 22:54:11 GMT
x-amz-date: Sun, 28 Dec 2008 22:54:11 GMT
Authorization: [authentication string]
Content-Length: 326
Content-Type: application/xml
Connection: close
<?xml version="1.0"?>
<DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">
<Origin>benramsey.s3.amazonaws.com</Origin>
<CallerReference>20081228175411</CallerReference>
<CNAME>cdn.benramsey.com</CNAME>
<Comment>benramsey.com static elements</Comment>
<Enabled>false</Enabled>
</DistributionConfig>
HTTP/1.1 201 Created
ETag: EZWBJQXKK6SDH
Location: [URI of new Distribution]
Content-Type: text/xml
Transfer-Encoding: chunked
Date: Sun, 28 Dec 2008 22:54:11 GMT
Server: CloudFront
[XML document with Distribution root element]
Listing 2 shows the raw HTTP request for creating distributions. The following code shows how to create this request using the Amazon CloudFront library:
require_once 'Amazon/CloudFront/Distribution/Config.php';
$config = new Amazon_CloudFront_Distribution_Config();
$config->setOrigin('benramsey.s3.amazonaws.com');
$config->setComment('benramsey.com static elements');
$config->addCname('cdn.benramsey.com');
$distribution = $cloudfront->createDistribution($config);
Each CloudFront distribution must be associated with exactly one Amazon S3 bucket. Notice that the S3 bucket associated with this distribution is benramsey.s3.amazonaws.com
.
You may optionally set a comment, enable the distribution to accept requests, or add up to ten CNAME records to associate with the distribution.
Using a Distribution
When the response comes back from the server, it’s in the form of a Distribution
element. Two important child elements to note are Id
and DomainName
. Id
is the identifier of the distribution, and you’ll use DomainName
in your applications to reference objects in the distribution, or, more specifically, the objects stored in the origin Amazon S3 bucket for the distribution.
You can get these values from the new Amazon_CloudFront_Distribution object returned:
$id = $distribution->getId();
$domainName = $distribution->getDomainName();
The most important part of the distribution, though, is the domain name associated with it. If you have specified CNAMEs for the distribution, then you’ll need to configure your DNS with CNAME records that point to the distribution’s domain name. Otherwise, you will use the domain name directly in your applications. For example:
<img src="http://d3e7a6gmq12l7y.cloudfront.net/ramsey.jpg"/>
Now, the ramsey.jpg
object, which lives in my Amazon S3 bucket at http://phpawebservices.s3.amazonaws.com/ramsey.jpg will be served from a CloudFront edge location when users request a page containing this img
element.
Updating a Distribution
To update a distribution, send a PUT request to the distribution’s configuration URI.
These requests are similar to the POST requests to create distributions, but the request must contain an If-Match header that matches the current value of the distribution’s ETag header. This prevents sending the same request twice or overwriting changes someone else made in the mean time. The ETag header is found in the response to a standard GET request for the distribution, and the Amazon CloudFront library does all of this behind the scenes.
PUT /2008-06-30/distribution/E3480J8O5WTRE9/config HTTP/1.1
Host: cloudfront.amazonaws.com
Date: Sun, 28 Dec 2008 22:58:53 GMT
x-amz-date: Sun, 28 Dec 2008 22:58:53 GMT
Authorization: [authentication string]
Content-Length: 325
Content-Type: application/xml
If-Match: EZWBJQXKK6SDH
Connection: close
<?xml version="1.0"?>
<DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">
<Origin>benramsey.s3.amazonaws.com</Origin>
<CallerReference>20081228175411</CallerReference>
<CNAME>cdn.benramsey.com</CNAME>
<Comment>benramsey.com static elements</Comment>
<Enabled>true</Enabled>
</DistributionConfig>
HTTP/1.1 200 OK
ETag: E208AP2G1V9JYQ
Content-Type: text/xml
Transfer-Encoding: chunked
Date: Sun, 28 Dec 2008 22:58:53 GMT
Server: CloudFront
[XML document with Distribution root element]
Listing 3 shows the raw HTTP request to update a distribution, while the following shows how to make the same request using the Amazon CloudFront library:
$distribution = $cloudfront->getDistribution($id);
$distribution->getConfig()->setEnabled();
$cloudfront->updateDistribution($distribution);
When updating a distribution, you may enable/disable the distribution, add or remove CNAME values, or change the comment.
Deleting a Distribution
Finally, Amazon CloudFront provides deletion of distributions by accepting DELETE requests to the distribution URI. However, the distribution must first be disabled. So, send an update request to disable it, wait until the status is no longer “InProgress,” and then send the DELETE request. This process could take several minutes, so it’s always good to check the status of the distribution before attempting to delete it. The Amazon CloudFront library does this for you and throws an exception if trying to delete a distribution that is either enabled or in progress.
DELETE /2008-06-30/distribution/E3480J8O5WTRE9 HTTP/1.1
Host: cloudfront.amazonaws.com
Date: Sun, 28 Dec 2008 23:04:47 GMT
x-amz-date: Sun, 28 Dec 2008 23:04:47 GMT
Authorization: [authentication string]
If-Match: E2DGZ2NS4EDYEP
Connection: close
HTTP/1.1 204 No Content
Date: Sun, 28 Dec 2008 23:04:47 GMT
Server: CloudFront
Listing 4 shows a raw HTTP request to delete a distribution. To do this with the Amazon CloudFront library, pass an Amazon_CloudFront_Distribution object
to the Amazon_CloudFront::deleteDistribution()
method:
$distribution = $cloudfront->getDistribution($id);
$response = $cloudfront->deleteDistribution($distribution);
A View From the Cloud
Amazon CloudFront is just one way to work with data in the Cloud. There are many other technologies out there waiting to be explored. As the Web matures and enters its third decade of life, many services are turning to cloud-based models of data storage. End users are becoming more and more comfortable with the notion that their data lives in the ether of the Internet rather than on their personal computers. Finding that data, retrieving it, manipulating it, and using it in meaningful ways are the challenges that face the era of the intelligent Web. I hope you’ll join me each month as we explore these services and technologies From the Cloud.
Requirements and Links
- PHP: 5.2+ with OpenSSL support
- Other Software: Amazon CloudFront Library 0.1.0-preview
- Useful/Related Links:
- Amazon CloudFront library: http://awsphp.googlecode.com/
- Amazon CloudFront: http://awsphp.googlecode.com/
- Amazon S3 Browser (Mac): http://people.no-distance.net/ol/software/s3/
- CloudBerry Explorer for Amazon S3 (Win): http://www.cloudberrylab.com/