Last week Amazon added support for Cross-Origin Resource Sharing (CORS), allowing web and mobile applications to easily interact with resources stored on AWS S3. This is good news for mobile developers as we can now build apps which access and update data stored on S3 without needing a custom proxy server. In this post we will show an example of this technology in action by building an Android app using Nomad for Visual Studio and PhoneGap. The source and app files are included at the end.
What is CORS?
The same origin policy limits how webpages (or mobile apps) on one domain interact with content from another domain. CORS is a specification that allows you to access data stored remotely (for example on S3) from your app without the extra work of passing it through a proxy, as required by this policy. AWS’s support for CORS means you can now “implement HTML5 drag and drop uploads to Amazon S3, show upload progress, or update content” easily from within your app.
In this post we’ll be building an app which accesses a data-store on S3 and allows the user to filter and search through the data. This will be relevant to you if you have a database that your app needs to access, but also needs to be regularly updated. We’re using sample real-estate data and our app will allow the user to search through our database for a house in their city, so lets get started.
Your data and Amazon
To begin with you’ll need an AWS account. You can then upload your data to an S3 bucket. We chose to save our data as a JSON file, as this allows for easy manipulation later. We could easily have used a CSV formatted file instead. Here is a sample of our data so you can get a feel for things (before you get excited about the prices just remember this is all fake data):
[ {
“id”: “8”,
“street”: “2961 19TH AVE”,
“city”: “SACRAMENTO”,
“beds”: “3”,
“baths”: “1”,
“sq__ft”: “1177”,
“price”: “91002”,
},
{
“id”: “9”,
“street”: “11150 TRINITY RIVER DR Unit 114”,
“city”: “RANCHO CORDOVA”,
“beds”: “2”,
“baths”: “2”,
“sq__ft”: “941”,
“price”: “94905”,
} ]
The next important step is to allow CORS access to your S3 bucket, which can be done in the online console using this guide. Our CORS configuration file looks like this:
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
The key point is that all headers and origins are allowed, as indicated by the wildcards (*), this will allow your app to access the S3 bucket. For increased security you could specify custom headers, and mirror this in your AJAX call later, but because your code will be run from the local app you need to allow all origins or specify the origin as null. You will also need set the permissions for the data itself so that it is either publicly available or requires authentication, using this guide.
Building the App
Now that the data is accessible you can request it from your app, so lets have a look at that. We started from the Nomad template and removed all demonstration functions, next we requested the data using an AJAX call like this:
$.ajax({
url: ‘http://nomad-demoapp1.s3.amazonaws.com/realestatedata.json’,
dataType: ‘json’,
success: function (data) {
make_table(data);
}
});
The addition of CORS on S3 allows this request to be carried out, previously one would have had to either proxy the request through your own server or used JSONP as a workaround.
The real estate data is now safely downloaded and we can display it in our app. We chose to use DataTables , a plugin for jQuery, as this makes searching through and filtering data easy. Our basic layout looks like this:
function maketable() {
// Initialising the table & setting up some styling parameters
$(‘#dynamictable’).html(‘<table cellpadding=”0″ cellspacing=”0″ border=”0″ class=”table table-striped table-bordered” id=”housetable”></table>’);
// Filling the table with data
$(‘#housetable’).dataTable({
//Using our data file from S3
“aaData”: data,
// Defining which columns we want to use from the data
“aoColumns”: [
{ “sTitle”: “City”, “mData”: “city”},
{ “sTitle”: “Bedrooms”, “mData”: “beds” , “bSearchable”: false},
{ “sTitle”: “Bathrooms”, “mData”: “baths”, “bSearchable”: false},
{ “sTitle”: “Square Footage”, “mData”: “sq__ft” , “bSearchable”: false}
{ “sTitle”: “Price”, “mData”: “price”, “bSearchable”: false,
“mRender”: function ( data ) {
return (“$” + data.commafy());
}
}
],
// Sorting the table by the first column
“aaSorting”: [[0, “asc”]],
// Initiallizing TableTools, a styling extension
“sDom”: “<‘row'<‘span6’><‘span6’>r>t<‘row'<‘span6’i><‘span6’p>><‘bottom’f>”,
});
};
We have chosen to only display a subset of the data in the original file, but it is all available locally if we need to call it up. We were also able to modify how the data is displayed, for example the price values were converted to commafied strings which are easier to read. We only want users to be able to search using the city field, so the others have been disabled. The resulting table looks like this in the browser:
This table can be sorted by any of the columns and filtered as-you-type using the search box.
Styling
The styling for this table was done using Bootstrap which is responsive to different screen sizes so its good for mobile development. Remember to use all the “responsive” options so that your app adjusts to different form factors.