Production Ready SproutCore With Apache

December 16, 2011
blog author

jmacinnes

Director of Technology

SproutCore is an exciting new framework for building html5 applications. In essence, SproutCore provides an MVC type framework that sits almost entirely on the client side in Javascript. This is great for building very dynamic web based applications that work almost like a real desktop application. However, SproutCore applications are very different than classic MVC applications that typically run entirely server side. A key difference is data storage. Server side applications can usually depend on a local database system or a near proximity database cluster to store or query large amounts of data. As SproutCore is typically run client side and often times within a browser, large data stores are usually not available. Further complicating this fact is the limited ability that a SproutCore application has to connect to a remote database. Since it depends on client side javascript, it must deal with all the security issues present in XHR requests, in particular it can only make HTTP requests and only to the same location that is within the address bar (multi-origin security). This blog will provide an example of a SproutCore application that retrieves content from a public web service and shows how such an application can be deployed in a production like manner using Apache. The source code for this example can be found at the following github repository: https://github.com/jimmacinnes/Apache-SproutCore

1. Multi-Origin and sc-server

The example code above is a very simple SproutCore application that makes a request to the following public weather service: http://ws.geonames.org/findNearByWeatherJSON?lat=49.2167&lng=-123.1 This site returns JSON providing current weather information for the parametrized coordinates. Within the sample code you can see where this is being called within the main.js file. Now start up sc-server within the sproutcore root folder:

cd apache_demo sc-server

and use your browser to go to: http://127.0.0.1:4020/apache_demo

You should now see the current weather conditions for Vancouver. But what is going on here exactly with that web service request? When SproutCore loads into the browser, it will make a request for the current weather condition, but will make that request back to the origin site, which is "http://127.0.0.1:4020" and not the actual site at "http://ws.geonames.org". Since we are running within the browser, the sproutcore application is not allowed to connect directly to the site "ws.geonames.org" but only back to its original website. SproutCore's sc-server however, provides functionality for dealing with these kinds of issues. Within the "Buildfile", you can specify "proxy" commands that will allow you to proxy a request to a remote server through sc-server and on to your SC application in the browser. Here is what the proxy command looks like:

proxy "/findNearByWeatherJSON", :to => "ws.geonames.org:80"

This essentially says that sc-server should proxy any requests that start with "/findNearByWeatherJSON" to "http://ws.geonames.org:80/findNearByWeatherJSON" and to tack on any extra information (like the actual coordinates) onto the end of the URL. This proxy functionality is great for dealing with and resolving the multi-origin issue with SproutCore applications. However, sc-server is really just meant to be used as a development server, and isn't intended to be used in production. Below I will provide the necessary steps needed to take this kind of configuration live using Apache.

2. Moving to Apache

Apache is a very stable and production ready web server used by thousands of websites. Unlike sc-server, Apache can be run in large scale environments. These instructions assume a Ubuntu/Debian flavour of Linux. The first thing you will need to do is get your apache root directory ready. This can be done using the "sc-build" command. I have provided a script within the "apache_demo" directory that will handle this for you, simply type:

# ./sc_build_web.sh

This will create a sub-directory called "www" within the current directory. Here is what is within that script file:

#! /bin/bash sc-build apache_demo --languages=en --build=current --buildroot=www mv www/static/apache_demo/en/current/index.html www cp -f apache/.htaccess www

This script first calls "sc-build" on our "apache_demo" project and specifies the output folder to be "www". It then moves the "index.html" file which is generated within the "www/static/apache_demo/en/current" directory up to the root of the folder. It then copies an apache ".htaccess" file into the root folder (more on that later). This "www" directory will then become your DocumentRoot within apache. Now install apache: sudo apt-get install apache2 and edit the file: /etc/apache2/sites-enabled/000-default and under the "/" Directory directive change "AllowOverride" to All (this will ensure that our .htaccess file is recognized by Apache).

Example:

Options FollowSymLinks AllowOverride All

Within the same file change the location of the “DocumentRoot” to the location of your “www” directory, for example:

DocumentRoot /home/apache_demo/www and change the root directory location and "AllowOverride" to All: Options Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny allow from all

There are a few apache modules that need to be enabled that are not enabled by default. These are used for doing the rewrite and proxy manipulations.

# cd /etc/apache2/mods-enabled # ln -s ../mods-available/*proxy* . # ln -s ../mods-available/*ssl* . # ln -s ../mods-available/*rewrite* .

You should now restart apache: # /etc/init.d/apache2 restart Once apache restarts, you will be able to access the html5 application via port 80 like this: http://127.0.0.1/ You should now see the weather in Vancouver the same way you did with sc-server. But now instead of using sc-server to proxy, we are using Apache to proxy. To see how this is happening take a look at the file "www/.htaccess", here is what is in there:

RewriteEngine On RewriteRule ^findNearByWeatherJSON(.*)$ http://ws.geonames.org/findNearByWeatherJSON$1 [P]

This essentially tells apache to turn on the Rewrite engine and proxy any commands that start with findNearByWeatherJSON to http://ws.geonames.org/findNearByWeatherJSON. The "$1" at the end of the command will insert anything that is found by the wildcard that is in the rewrite search string (the '(.*)') on to the end of the destination url. The '[P]' command informs apache that you want to proxy the request, not redirect it. So that's it. Now we have a production ready version of our application running under apache that can be easily and reliably scaled.