In this lab you will add more functionality to the server side scripts. This lab will introduce you to the following: - define a web API for your service - separate routing out into a routing script - do more advanced routing based on the HTTP verb - test your solution with a suitable Rest Client
We will use the 'routing' technique covered in the last lab to map the above HTTP verb and paths
npm init
command. npm install express --save
. (the --save
adds Express dependency to your package.json)npm install body-parser --save
var express = require('express');
var bodyParser = require('body-parser');
//create an express app
var app = express();
//configure the express app to parse JSON-formatted body
app.use(bodyParser.json());
//add route for the root
app.get('/',function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("We're up and running!!!");
});
// Listen on port 8000, IP defaults to 127.0.0.1
app.listen(8000)
// Put a friendly message on the terminal
console.log("Server running at http://127.0.0.1:8000/");
node app.js
and then check if the Express app is listening on port 8000. This time, however, we will use a "Rest client" to manually test the service. If you are using the Chrome browser, you can use the 'Advanced Rest Client' which is available as a Chrome app. See here for instructions on how to install the app. In the last lab we created one simple route:
//add route for /greeting
app.get('/greeting',function (request, response) {
...
});
In this lab, the following list of actions are required for the Contacts API.
We will now map these action to a set of HTTP operations on resources.
HTTP Verb & Path | Operation Description |
---|---|
GET: /api/contacts | return a list of contacts |
POST: /api/contacts | add a new contact |
PUT: /api/contacts/:id | update a contact |
DELETE: /api/contacts/:id | delete a contact |
We will now use the same approach but use the 'require' functionality to separate out the routing logic from the main app script. |
//create routing object
var contact = require('./api/contacts/index');
//Add routes for contacts api
app.get('/api/contacts',contact.index);
app.post('/api/contacts',contact.create);
{id: 'hwX6aOr7', name: "Ellen Bliggs", address: "2 River Road", phone_number: "051-123457"}
We will need to generate a unique id each time a new contact is added. To do this, install the ShortId Module by running the following in the lab7 folder:
npm install shortid --save
- api
|- contacts
To mimic a real database, we'll use a script that exports a hard coded contacts data as a JSON array. Create a new file called datastore.js in the contacts folder and add the following:
exports.contacts = [
{id: 'a4vhAoFG', name: "Joe Bloggs", address: "1 Bank Lane", phone_number: "051-123456 "},
{id: 'hwX6aOr7', name: "Ellen Bliggs", address: "2 River Road", phone_number: "051-123457"}
]
var datastore = require('./datastore');
var shortId = require('shortid');
// Get list of contacts
exports.index = function(req, res) {
return res.json(200, datastore.contacts);
} ;
// Creates a new contact in datastore.
exports.create = function(req, res) {
var contact = {
id: shortId.generate(),
name: req.body.name,
address: req.body.address,
phone_number: req.body.phone_number
};
datastore.contacts.push(contact)
return res.json(201, contact);
};
In the above code, we require the datastore script that exports the JSON array of contacts. The index
function just returns all the contacts(i.e. the array). The create
function creates a new new contact from the JSON contained in the HTTP body. Run the app again and, using your Rest client, test that it returns the contacts for a HTTP GET on localhost:8000/api/contact:
{"name":"Bob Hope","address":"123 Bob Lane","phone_number":"051-3423456 "}
See the screenshot below for guidance...
We now want to add routes for updating and deleting contacts from our contact list. * Add the following two routes to your app script
app.put('/api/contacts/:id',contact.update);
app.delete('/api/contacts/:id',contact.delete);
The :id
part of the path allows that portion of the path (i.e. the customer id) to be accessed in the router function as a request parameter. This is shown in the following update and delete functions...
*
Add the corresponding functions in the index.js:
// Update an existing contact in datastore.
exports.update = function(req, res) {
var index = datastore.contacts.map(function(x) {return x.id; }).indexOf(req.params.id);
if (index != -1) {
var contact = datastore.contacts[index]
contact.name = req.body.name
contact.address = req.body.address
contact.phone_number = req.body.phone_number
return res.send(200, contact)
} else {
return res.send(404)
}
};
// delete an existing contact in datastore.
exports.delete = function(req, res) {
var index = datastore.contacts.map(function(x) {return x.id; }).indexOf(req.params.id);
if (index != -1) {
var contact = datastore.contacts.splice(index,1);
return res.send(200, contact)
} else {
return res.send(404)
}
};
Notice in these functions you are just manipulating an array. Using the contact id, we find the array index of the contact in order to update/delete. The id of the contact to update/delete is accessed from the request object using the req.params.id property. This is then used to find the array index of the element using the map function of the contacts array in first line of the function: var index = datastore.contacts.map( ... )
*
Now test the update and delete using your Rest client. For the update, you will need to provide a document to update the existing resource (i.e. has same contact id of an exising contact).