copyright | lastupdated | ||
---|---|---|---|
|
2017-10-27 |
{:shortdesc: .shortdesc} {:new_window: target="_blank"} {:codeblock: .codeblock} {:screen: .screen} {:tip: .tip} {:pre: .pre}
In this tutorial, you will create a serverless web application by hosting static website content on GitHub Pages and implementing the application backend using Functions on IBM Cloud.
The application shown in this tutorial is a simple guestbook website where users can post messages.
- Deploy a serverless backend and database
- Expose a REST API
- Host a static website
- Optional: Use a custom domain for the REST API
This tutorial uses the following products:
- The user access the application hosted in GitHub Pages.
- The web application calls a backend API.
- The backend API is defined in API Gateway.
- API Gateway forwards the request to Cloud Functions.
- The Cloud Functions actions use Cloudant to store and retrieve guestbook entries.
{: #prereqs}
This guide uses GitHub Pages to host the static website. Make sure you have a public GitHub account.
Let's start by creating a Cloudant NoSQL Database. Cloudant NoSQL DB is a fully managed data layer designed for modern web and mobile applications that leverages a flexible JSON schema. Cloudant is built upon and compatible with Apache CouchDB and accessible through a secure HTTPS API, which scales as your application grows.
- In the Catalog, under Data & Analytics, select Cloudant NoSQL DB.
- Set the service name to guestbook-db and click Create.
- Under Service Credentials, create New credential and click Add.
- Click on Manage on the left and then Launch the Cloudant service console.
- Create a database named guestbook.
In this section, you will create serverless actions (commonly termed as Functions). IBM Cloud Functions (based on Apache OpenWhisk) is a Function-as-a-Service (FaaS) platform which executes functions in response to incoming events and costs nothing when not in use.
You will create a sequence which is a chain of actions where output of one action acts as an input to the following action and so on. The first sequence you will create is used to persist a guest message. Provided a name, an emailID and a comment, the sequence will:
- Create a document to be persisted.
- Store the document in the Cloudant NoSQL database.
Start by creating the first action, adding the action to a sequence and then adding the second action to the sequence.
- Switch to Functions on IBM Cloud.
- On the left pane, click on Actions and then Create.
- Create Action with name
prepare-entry-for-save
and select Node.js 6 as the Runtime. - Replace the existing code with the code snippet below and Save
{: codeblock}
/** * Prepare the guestbook entry to be persisted */ function main(params) { if (!params.name || !params.comment) { return Promise.reject({ error: 'no name or comment'}); } return { doc: { createdAt: new Date(), name: params.name, email: params.email, comment: params.comment } }; }
- Click on Enclosing Sequences and then Add To Sequence.
- For Action name, enter
save-guestbook-entry-sequence
and then click Create and Add. - Click on save-guestbook-entry-sequence and then click Add.
- Select Use Public, Cloudant and then choose create-document under Actions
- Create New Binding and set name to
binding-for-guestbook
. - Select the guestbook-db Cloudant instance and the guestbook database and Add and then Save.
- To test it, click on Change Input and enter the JSON below
{: codeblock}
{ "name": "John Smith", "email": "[email protected]", "comment": "this is my comment" }
- Apply and then Invoke.
The second sequence is used to retrieve the existing guestbook entries. This sequence will:
- List all documents from the database.
- Format the documents and returning them.
- Under Functions, Create a new Node.js action and name it set-read-input.
- Replace the existing code with the code snippet below. This action passes the appropriate parameters to the next action.
{: codeblock}
function main(params) { return { params: { include_docs: true } }; }
- Click on Enclosing Sequences, Add to Sequence and Create New
- Enter
read-guestbook-entries-sequence
for the Action Name and click Create and Add. - Click on read-guestbook-entries-sequence sequence and then click Add to create and add the second action to get documents from Cloudant.
- Under Use Public, choose Cloudant and then list-documents
- Choose binding-for-guestbook and Add to create and add this public action to your sequence.
- Click Add again to create and add the third action which will format the documents from Cloudant.
- Under Create New enter
format-entries
for name and then click Create and Add. - Click on format-entries and replace the code with below and Save
const md5 = require('spark-md5');
function main(params) {
return {
entries: params.rows.map((row) => { return {
name: row.doc.name,
email: row.doc.email,
comment: row.doc.comment,
createdAt: row.doc.createdAt,
icon: (row.doc.email ? `https://secure.gravatar.com/avatar/${md5.hash(row.doc.email.trim().toLowerCase())}?s=64` : null)
}})
};
}
{: codeblock} 11. Choose the sequence by clicking on Actions and then read-guestbook-entries-sequence. 12. Click on **Save and then Invoke. The output should look like the following:
- Go to Actions https://console.bluemix.net/openwhisk/manage/actions.
- Select the read-guestbook-entries-sequence sequence. Under Additional details, check Enable Web Action.
- Do the same for the save-guestbook-entry-sequence sequence.
- Go to APIs https://console.bluemix.net/openwhisk/apimanagement and Create Managed API
- Set name to guestbook and base path to /guestbook
- Create an operation to retrieve guestbook entries:
- Set path to /entries
- Set verb to GET
- Select the read-guestbook-entries-sequence action
- Create an operation to persist a guestbook entry:
- Set path to /entries
- Set verb to PUT
- Select the save-guestbook-entry-sequence action
- Save and expose the API.
- Fork the Guestbook user interface repository https://github.com/IBM-Cloud/serverless-guestbook to your public GitHub.
- Modify docs/guestbook.js and replace the value of apiUrl with the route given by API Connect.
- Commit the modified file to your forked repository.
- In the Settings page of your repository, scroll to GitHub Pages, change the source to master branch /docs folder and Save.
- Access the public page for your repository.
- You should see the "test" guestbook entry created earlier.
- Add new entries.
-
Create your domain under your organization https://console.bluemix.net/docs/admin/manageorg.html#managedomains.
-
Upload a SSL certificate for your domain and the subdomain you will use for the API.
-
Go to the Cloud Functions dashboard, select APIs and the Guestbook API.
-
Switch to Definition.
-
Set the Domain for API to the domain you added to your organization.
-
Set the Subdomain for API to guestbook-api
-
At this stage, you need to configure your DNS to create a CNAME mapping this subdomain to the IBM Cloud servers. Create a CNAME record for the domain targeting one of the following secure endpoints depending on which region hosts the target API:
- US South: secure.us-south.bluemix.net.
- United Kingdom: secure.eu-gb.bluemix.net.
- Frankfurt: secure.eu-de.bluemix.net.
- Sydney: secure.au-syd.bluemix.net.
Refer to https://console.bluemix.net/docs/apis/management/manage_apis.html#custom_domains for additional information
-
Save the API.
-
Wait for DNS to propagate and you will be able to access your guestbook api at https://guestbook-api.mydomain.com/guestbook.
-
Edit docs/guestbook.js and update the value of apiUrl with https://guestbook-api.mydomain.com/guestbook
-
Commit the modified file.
-
Your application now access the API through your custom domain.