Send Docs Feedback

Using Node.js to communicate with a backend data store


This example illustrates how you can use a Node.js app deployed on Edge to perform CRUD operations in back-end data store.  In this case, we use Apigee BaaS as the data store; however, you can adapt the same pattern to talk to any kind of backend data store.

About this cookbook sample

You can think of Node.js apps deployed on Edge as programmable targets. In this sample, the Node.js code orchestrates calls to the API BaaS data store, executes custom logic, and returns appropriate responses.

The Node.js app uses Express and Usergrid modules. Express is a popular Web app framework for Node.js, and Usergrid is an open-source BaaS framework that is the core of API BaaS from Apigee.

The API for this sample app lets you create and fetch data from a API BaaS data store. The APIs look like this:

1. Retrieve a list of employees:

$ curl http://org-test.apigee.net/nodejs-baas-cookbook/employees/profiles

2. Create a new employee profile in the data store:

$ curl http://wwitman-test.apigee.net/employees/profile \
-H "Content-Type: application/json" \
-d '{"id":"jdoe", "firstName":"Jane", "lastName":"Doe", "phone": "201-555-5555" }' \
-X POST

About the Edge proxy endpoints

Let's take a quick look at the proxy and target endpoint definitions. In Edge, endpoints are defined in XML files. The XML, shown below, tells us a lot about this API proxy and how the Node.js application is integrated into the flow of the proxy.

The ProxyEndpoint configuration defines the inbound (app-facing) interface for an API proxy. This endpoint's basepath is /employees, and it routes to the default target endpoint. For more on proxy endpoint definitions, see API proxy configuration reference.

<ProxyEndpoint name="default">
   <HTTPProxyConnection>
        <BasePath>/employees</BasePath>
        <VirtualHost>default</VirtualHost>
    </HTTPProxyConnection>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
    </RouteRule>
    <PreFlow name="PreFlow">
        <Request/>
        <Response/>
   </PreFlow>
</ProxyEndpoint>

The default TargetEndpoint includes a <ScriptTarget> element, which is the standard way of declaring the main Node.js file in the app. This is the file that you would call with the node command if you were to run the app from the command line. <ScriptTarget> is discussed in more detail in Adding Node.js to an existing API proxy.

<TargetEndpoint name="default">
    <ScriptTarget>
        <ResourceURL>node://server.js</ResourceURL>
    </ScriptTarget>
    <PreFlow name="PreFlow">
        <Request/>
        <Response/>
    </PreFlow>
</TargetEndpoint>

About the Node.js app

Here's the complete listing of the Node.js app. It uses the standard Express pattern to define operations for creating and fetching data records from API BaaS. The app also handles authentication and data store operations through the usergrid.client object. See also https://npmjs.org/package/usergrid

var express = require('express');
var usergrid = require('usergrid');
var config = require('./config');

var app = express();
app.use(express.bodyParser());


var client = new usergrid.client({
	'orgName' : config.organization,
	'appName' : config.application,
	'clientId' : config.clientId,
	'clientSecret' : config.clientSecret,
	'authType' : usergrid.AUTH_CLIENT_ID,
	logging : config.logging
});


var rootTemplate = {
	'employees' : {
		'href' : './employees'
	}
};

app.get('/', function(req, resp) {
	resp.jsonp(rootTemplate);
});


app.get('/profiles', function(req, res) {	
		getProfiles(req, res);
});

function getProfiles(req, res) {
	client.createCollection({
		type : 'employees'
	}, function(err, employees) {
		if (err) {
			res.jsonp(500, {
				'error' : JSON.stringify(err)
			});
			return;
		}

		var emps = [];
		while (employees.hasNextEntity()) {
			var emp = employees.getNextEntity().get();
			var e = {
				'id' : emp.id,
				'firstName' : emp.firstName,
				'lastName' : emp.lastName,
				'phone' : emp.phone
			};
			emps.push(e);
		}
		res.jsonp(emps);
	});
}


app.post('/profile', function(req, res) {
	if (!req.is('json')) {
		res.jsonp(400, {
			error : 'Bad request'
		});
		return;
	}

	var b = req.body;
	var e = {
		'id' : b.id,
		'firstName' : b.firstName,
		'lastName' : b.lastName,
		'phone' : b.phone
	};

	if ((e.id === undefined) || (e.firstName === undefined)
			|| (e.lastName === undefined) || (e.phone === undefined)) {
		res.jsonp(400, {
			error : 'Bad request'
		});
		return;
	}

	createProfile(e, req, res);
});

function createProfile(e, req, res) {
	var opts = {
		type : 'employees',
		name : e.id
	};

	client.createEntity(opts, function(err, o) {
		if (err) {
			res.jsonp(500, err);
			return;
		}
		o.set(e);
		o.save(function(err) {
			if (err) {
				res.jsonp(500, err);
				return;
			}
			res.send(201);
		});
	});
}


// Listen for requests until the server is stopped

app.listen(process.env.PORT || 9000);
console.log('The server is running!');


Note that the Node.js app is an HTTP server. When the code is deployed to Edge, this server is automatically started (remember, it's the backend target of the Edge API proxy). 

Download and try out the sample code

You can find a working version of this sample in the apigee/api-platform-samples repo on GitHub. The sample code includes the complete proxy, Node.js code, and convenience scripts for deploying and invoking the APIs. See the project README for details on how to deploy and run the sample.

Setup tasks

If you want to run the sample, you need to perform the following setup tasks. 

  1. You need an Apigee  account to use both Apigee Edge and API BaaS. Setting up an account is free and only takes a minute. See Creating an Apigee Account.
  2. In the API BaaS admin portal, create a new application called employees. For detailed information, see Creating a new application
  3. In the API BaaS admin portal, create a new data store called employees. For detailed information, see Creating Collections.

 

Configuration tasks

You'll also need to edit two config files:

  • Apigee Edge credentials in api-platform-samples/setup/setenv.sh
  • API BaaS credentials in api-platform-samples/doc-samples/nodejs-baas-cookbook/apiproxy/resources/node/config.js. You can find your clientSecret and clientId values on the Org Administration page of the API BaaS Admin Portal. For example:
    exports.organization = 'myorg'
    exports.application = 'employees'
    exports.clientId = 'b3U6gj36in4gEeOaDDwafXLGg'
    exports.clientSecret = 'b3U6JAorOoLMn0bE02uuJqgXx40p78'
    exports.tokenExpiration = 60000
    exports.logging = true
      

Deploying and running the example

To run the sample in the README file in the nodejs-baas-cookbook folder. Or, follow the brief instructions here: Using the sample API proxies.

To summarize, you can call the API as follows. Substitute myorg with your organization name:

1. Create a new employee profile in the API BaaS data store:

$ curl http://myorg-test.apigee.net/employees/profile \
-H "Content-Type: application/json" \
-d '{"id":"cjones", "firstName":"Chris", "lastName":"Jones", "phone": "201-555-5555" }' \
-X POST

2. Retrieve a list of employee profiles stored in the API BaaS data store:

$ curl http://myorg-test.apigee.net/nodejs-baas-cookbook/employees/profiles -X GET
[
  {
    "id": "cjones",
    "firstName": "Chris",
    "lastName": "Jones",
    "phone": "201-555-5555"
  }
]

Summary

This sample illustrates a pattern where a Node.js app mediates between the Apigee Edge platform and a backend data store. In this case, the backend store is API BaaS, but it could be any data store that has a JavaScript/Node.js interface.

Help or comments?