Running a Single Page App and can’t wait for Lambda@Edge? Here’s an alternative*

* Yes, I do understand that Lambda@Edge will provide a completely different level of scale and performance, and is an industrialised managed offering. None the less, what’s described below could serve many use cases just fine. 😉

With that, on to it.

There’s no point arguing that Single Page Apps (SPAs) are in vogue. One of the approaches to SPAs is to move business logic into the client, and leverage a range of API-based services to provide needed server-side functionality. Here’s a very good argument presented on this topic: Joe Emison – 10X Product Development.

A side effect of following this pattern is your SPA code ends up on a server that only knows how to serve your static client content (html / js / css / images). This may present a problem when you try to integrate your SPA with another stand-alone application, for example, blog hosted by WordPress.

Let’s have a look in a bit more detail, followed by what can be done about it.

A bit of a background

I’m not an SEO guru, but my understanding is that your appearance in search results is better if your whole web property appears behind the same domain. For example, if your main web page is corp.com, it’s better for your web image if the URL for your company’s blog is something like corp.com/blog, as opposed to blog.corp.com, which may count as a separate web property.

When your web page is hosted on a “traditional” web server, serving your SPA contents for corp.com and your self-hosted WordPress blog from corp.com/blog is not a problem. If traffic levels for your site are moderate and high availability is not a major concern, it’s a perfectly acceptable solution.

If, however, you’d like to cater for unpredictable traffic levels of, well, any magnitude, and/or don’t want to deal with undifferentiated heavy lifting that is IT infrastructure administration of your web servers, you may be using specialised services to both host your SPA and your blog. Which brings us right back to our SEO problem.

Let’s say you used an AWS S3 Static Web Site Hosting for your corp.com SPA. You set up DNS for corp.com to point to S3, and the life is good. That is, until you want to add a /blog, but hosted by WordPress.com. The problem here is that the IP address(es) for corp.com, which happens to be the common part of both corp.com and corp.com/blog can point to either S3, where your SPA lives, or to WordPress, where your blog is.

If you try to send a request to S3 for something that isn’t there, S3 will tell you that those are not the droids you’re looking for:

There is no Blah
There is no “/blah” (click to enlarge)

This is where in-line HTTP request and response processing comes to rescue. Recognising this and several other related needs, AWS has just announced service called Lambda@Edge. This service allows you to run Node.js code at CloudFront locations that can modify your web site visitors’ HTTP requests and CloudFront / origin servers’ responses sent back to them. For example, to solve our problem above, code may look for the /blog in the request path, and redirect that request to a different origin (WordPress blog).

The service is currently in preview, and its functionality is in early days; however it will likely mature rapidly. In meanwhile, if you have a similar need to what’s described above, here is how you can do it with a Brocade vADC.

Setup

For our demo solution, I’ve grabbed a copy of AngularJS Tutorial, slightly modified it to point at my blog for the /blog integration, uploaded it into an S3 bucket, and turned on S3 Web Site Hosting on it.

I also created a domain test.11-14.net to represent our hypothetical corp.com, and got a Let’s Encrypt SSL certificate for it to demonstrate serving S3 web site content via SSL.

The last bit was to deploy a Brocade Virtual Traffic Manager Developer Edition, and create a virtual server with some TrafficScript to process HTTP requests and responses.

When all is in place, we can hit our web site and see it in action. (Um, since I’m running the vADC in my own AWS account, I’ve stopped the vADC used to record this demo to save money.) 🙂

Opening the main page shows us the SPA, sitting behind our pretty URL:

Main SPA page
Main SPA page (click to enlarge)

..while when we hit the blog..

Blog menu
Blog menu (click to enlarge)

..we’re presented with our blog, appearing integrated with the main site, and even all article links looking pretty – see the bottom of the screenshot when the mouse is pointing at the header of the post on screen:

Blog, integrated
Blog, integrated (click to enlarge)

So, how does it all work?

vADC Configuration

First, let’s set up our backend. Our page has two sources: an S3 bucket with the SPA, and the blog hosted by WordPress.com. To match this, we create two Pools:

vADC Pools
vADC Pools (click to enlarge)

The first one, unimaginatively called blog, is the WordPress site. When I put telecomoccasionally.wordpress.com:443 into the Node detail, vADC resolves the FQDN, sees it matching two IPs, and puts those IPs as the pool nodes. I chose “Full HTTPS” as the health monitor, since WordPress serves my blog over HTTPS. For HTTPS connections to this pool, vADC will terminate the client SSL session, and open a different one to the backend pool.

The second one, test-SPA-s3, is an HTTP node that points to the S3’s IP address. It’s HTTP, since S3 doesn’t provide HTTPS for web sites hosted on it. For client-side HTTPS connections leading to this pool, vADC will perform SSL offload.

Next, we create the Virtual Servers – one for HTTP (port 80), and one for HTTPS (port 443):

Virtual Servers
Virtual Servers (click to enlarge)

Virtual Servers are the ones listening to client connections, and serve the content from Pools accordingly.

I’ve configured both virtual servers to point at the pool test-SPA-s3, but as you’ll see below, we’ll be overriding this in our script. You can also see that there’s a green “tick” against “Rules” for both virtual servers, and this is where the TrafficScript is applied.

vADC provides ability to run three Rule scripts for each Virtual Server:

  • Request: script is run over what client sends to vADC. The result of the script processing is then sent to the backend pool.
  • Response: script is run over what the backend pool member responds with to vADC. The result of the script processing is then returned to the client.
  • Transaction Complete: relevant for the transactions, such as “when the connection is closed or when a complete HTTP, SIP, or RTSP response has been sent to the client

For our example, we’ll be using Request and Response rules, which will do the following:

  • Virtual Server will expect to see connections for the domain test.11-14.net
  • Request rule attached to the Virtual Server will check if the path in the request has string /blog in it
  • If it does not, the request will be routed to the pool test-SPA-s3, pointing at the S3 bucket hosting the SPA code
  • If it does, the request will be routed to the pool blog, pointing at our blog site on wordpress.com
  • In both cases, vADC will rewrite the Host: header accordingly, since S3 will expect it to match the S3 bucket name, and WordPress will expect it to match the blog page (telecomoccasionally.wordpress.com).

Additionally, the Response rule will look through the body of the responses from S3 and WordPress, and substitute the original S3 or WordPress URL strings with the appropriate “pretty URL” – test.11-14.net or test.11-14.net/blog accordingly.

This will ensure that for example any links on the blog appear to be “pretty”, giving an illusion of the blog being completely integrated with the main site.

Here’s what the rules look like; I think you should have no trouble figuring out what the code does:

Rules
Rules (click to enlarge)

Granted, you potentially may need to manipulate other things like other headers and cookies; but TrafficScript is there to help – you have access to all parts of requests and responses.

And there you have it – nice clean integration!

Bonus material

While the ability to make changes to the contents of requests and responses is cool, it’s not all you can do with TrafficScript. Here’s one cool use case we’ve seen – in this implementation, web site behind vADC provides a “Red Carpet” experience to the site’s visitors based on a result of an in-line API call to find out visitor’s loyalty program status. Once visitor’s eligibility is established, they are directed to a separate backend pool, and given a more preferential QoS treatment:

# Extract the Customer ID from the request:
$CustID = http.getFormParam("CID");

# Look them up to see what program level they are currently at:
$CIDLookup = http.request.get("http://cidlookup.corp.com/cidLookup.php?CID=".$CustID);

# If they have platinum status, let's roll out the Red Carpet:
if(string.containsI($CIDLookup, "platinum")) {

   # We have a dedicated pool of servers for Platinum Members:
   pool.select("pool_Platinum_Custs");

   # And apply a pair of special Bandwidth Classes so we don’t
   # slow them down when the site is under load:
   request.setBandwidthClass("BW_Platinum_CID_REQ");
   response.setBandwidthClass("BW_Platinum_CID_RES");
}

Looks good, but..

..I don’t have experience with vADC, and how to deploy and configure it!

If you’re in AWS – CloudFormation to rescue! I’ve been working on a few generations of CloudFormation templates to help smooth out deployment of vADC clusters into AWS. A good place to start is the variant that deploys two vADC nodes into a cluster across two AZs, and pushes vADC configuration to it using vADC Puppet Module. Template should cover most of your needs when it comes to vADC deployment and configuration. You can pull it apart and integrate bits into your own solution, no problem. All code is Creative Commons and is completely free for any use as a whole or in part.

You can find the template, along with a reasonable README that explains what’s going on there by clicking here.

P.S. The template above deploys a pair of vADCs as static EC2 instances. If you’d like to manage your vADC cluster by AWS Autoscaling, feel free to drop by here.

Happy ADCing! 🙂

About Dmitri Kalintsev

Some dude with a blog and opinions ;) View all posts by Dmitri Kalintsev

One response to “Running a Single Page App and can’t wait for Lambda@Edge? Here’s an alternative*

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: