Deploying Express.js apps to OpenWhisk (Part 2)

Generalization

The first installment of this series shows how easy is to deploy a simple Express.js app to Apache OpenWhisk. In this tutorial, I’ll go through the steps of deploying an existing Express.js app. This time I will be using the OpenWhisk Express.js npm package instead of an ad-hoc action.

I picked the movieanalyst demo application which rank 1 in the August 2016 Node.JS top 10 articles. It is actually composed of three Express apps (two front-end clients, one backed service), secured with Auth0 (o != o). I encourage you to read the original article especially the part describing how to setup Auth0.

Let’s get started.

Step 1: adapting the original application

The original application has been put together to demonstrate how to use Auth0 and designed to run locally. Since I want to actually deploy it, I made the following changes:

  • in all server.js file, I moved app.listen(...) into bin/www. OpenWhisk listens to HTTP requests, not our application.
  • sensitive values, such as client id, client secrets and audience, and backend service endpoints are hard-coded. Instead, let’s put everything in a config file we are going to use during deployment.

The modified source code is available here.


Interlude: a little trick

I recently learn a trick that will be useful in this tutorial: it is possible ❶ to combine public and private actions using sequence action and ❷ to add the web annotation on sequence action. The general command is:

$ wsk action update private/mywebaction \
/whisk.system/utils/echo,private/action \
--sequence --web yes

Secrets can be stored in private/action since the private package does not have to be made public in order to be used by a web action. We will see how to use this feature in Step 3, but first let’s create the private actions.


Step 2: creating the private actions

Since movieanalyst is composed of three Express.js apps, the best is to create three corresponding actions. They all look identical to this code:

Notice that:

  • I implicitly use another nice OpenWhisk feature related to statelessness: the action state might still be available across invocations. In that case, app and redirect might have already been initialized, savings us some CPU cycles.
  • The OpenWhisk Express.js action introduced Part 1 has now been made available as a npm public package called openwhisk-expressjs. This action has also been generalized and now takes an optional object called express_locals which is used to extend app.locals. No more baseurl and staticbaseurl.

Let’s put this code inside a file called action.js in the root directory. We also need to update all three package.json files by setting "main" to "action.js".

Step 3: Deploying

The project is now ready to be deployed. If you haven’t done it already, it’s now time to setup Auth0 as described in this article.

The deployment script for each app looks like this:

Deployment script for each action

This script:

  • creates a zip file containing the node js action (line 3). The size of the zip file is around 1MB, well below the 48MB limit. There is still room for growth before having to rely on size optimization techniques such as minimization and code splitting.
  • updates the private action called $PACKAGE/express-website (line 6).
  • updates the sequence web action by applying the little trick we learned before (line 9). Note in this case I use the raw web annotation telling OpenWhisk not to parse query parameters.

We also need a master deployment script

Master deployment script

To deploy, first create a JSON configuration file containing the Auth0 secrets:

{
"package": "movieanalyst",
"client_id": "<website client id>",
"client_secret": "<website secret>",
"admin_client_id": "<admin client id>",
"admin_client_secret": "<admin secret>",
"auth0_domain": "<your Auth0 domain>",
"auth0_audience": "<your Auth0 audience>",
"api_host": "<API host name>"
}

and run the master script:

$ ./deploy.sh config.<yourenv>.json

In my case, I deployed it to Bluemix. The application main website has access to the movies, reviewers and publications endpoints, while the admin app has additionally access to the pending endpoint which returns movie reviews that are not ready to be publicly accessible.

Try accessing directly the backend API (https://openwhisk.ng.bluemix.net/api/v1/web/villard@us.ibm.com_dev/movieanalyst/api), you get rejected because of the missing Auth0 authorization token. This token is acquired by the main website and the admin app before making calls to the API.

Try navigating to the pending review page (https://openwhisk.ng.bluemix.net/api/v1/web/villard@us.ibm.com_dev/movieanalyst/website/pending) from the main web site (a route has been created but not made available through the UI). You should get forbidden access as the website client does not have the admin scope applied to it. I refer you to the original article for more details.

The main website

Note that for a real application the access to the admin webpage should be restricted to privileged users, for instance by using OAuth or Auth0. Nothing in OpenWhisk prevents using OAuth, it is just a matter of updating the admin app.

Wrapping up

This concludes this mini-series on Express.js deployed to Apache OpenWhisk. It shows that OpenWhisk is a viable platform for hosting web site and in particular the ones written using Express.js.

I hope it inspires you to try it on your own app and please let me know of any issues on github.

Thanks for your feedback in advance.