Building a simple node API « »
March 12, 2016
Some quick examples
With Node and http module
var http = require('http');
http.createServer(function (req,res) {
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end('Hello World\n');
}).listen(3000,'127.0.0.1');
console.log('Server running at http://localhost:3000/');
var http = require('http');
http.createServer(function (req,res) {
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end('{"id":1,"name": "Pere Pages"}');
}).listen(3000,'127.0.0.1');
console.log('Server running at http://localhost:3000/');
With Express
var express = require('express');
var app = express();
app
.get('/', function (req,res) {
res.send('Hello World!');
})
.get('/json', function (req,res) {
res.json({"hello":"world"});
});
var server = app.listen(3000, function () {
console.log('Server running at http://127.0.0.1:3000/');
});
Tools
Nodemon
Node monitor
sudo npm install -g nodemon
lodash
Utility class, before everybody was using underscore.
npm install --save lodash
var _ = require('lodash');
body-parser
This module helps dealing with cookies and bodies.
The bodyParser object exposes various factories to create middlewares. All middlewares will populate the req.body property with the parsed body, or an empty object ({}) if there was no body to parse (or an error was returned).
npm install --save body-parser
Creating a npm script
{
"scripts": {
"start":"nodemon index.js"
}
}
Dummy API
index.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
// middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var cats = require('./cat.js')(app);
var server = app.listen(3000, function() {
console.log('Server running at http://127.0.0.1:3000/');
});
cat.js
var _ = require('lodash');
module.exports = function(app) {
_cats = [];
/* Create */
app.post('/cat', function(req, res) {
_cats.push(req.body);
res.json({ info: 'cat created successfully' });
});
/* Read */
app.get('/cat', function(req, res) {
res.send(_cats);
});
app.get('/cat/:id', function(req, res) {
res.send(_.find(_cats, { name: req.params.id }));
});
/* Update */
app.put('/cat/:id', function(req,res) {
var index = _.findIndex(_cats, {name:req.params.id});
_.merge(_cats[index], req.body);
res.json({info: 'cat updated successfully'});
});
/* Delete */
app.delete('/cat/:id', function (req,res) {
_.remove(_cats, function (cat) {
return cat.name === req.params.id;
});
res.json({info: 'cat removed successfully'});
});
};
Using Mongo
Adding Mongo
Installing Mongoose
npm install --save mongoose
index.js, include mongoose
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
// HERE!!!!!!!!!!!!
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/cats');
// middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var cats = require('./cat.js')(app);
var server = app.listen(3000, function() {
console.log('Server running at http://127.0.0.1:3000/');
});
Mongoose Model Example
cat_model.js
var mongoose = require('mongoose');
var catSchema = mongoose.Schema({
name: String,
age: Number,
type: String
});
module.exports = mongoose.model('Cat', catSchema);
cat_routes.js
var _ = require('lodash');
var Cat = require('./cat_model.js');
module.exports = function(app) {
/* Create */
app.post('/cat', function(req, res) {
var newCat = new Cat(req.body);
newCat.save(function(err) {
if(err) {
res.json({info: 'error during cat create', error: err});
} else {
res.json({info: 'cat created successfully'});
}
});
});
/* Read */
app.get('/cat', function(req, res) {
Cat.find(function(err, cats) {
if (err) {
res.json({info: 'error during finding cats', error: err});
} else {
res.json({info: 'cats found successfully', data: cats});
}
});
});
app.get('/cat/:id', function(req, res) {
Cat.findById(req.params.id, function(err,cat) {
if (err) {
res.json({info: 'error during finding cat', error: err});
} else {
if (cat) {
res.json({info: 'cat found successfully', data: cat});
} else {
res.json({info: 'cat not found'});
}
}
});
});
/* Update */
app.put('/cat/:id', function(req,res) {
Cat.findById(req.params.id, function(err,cat) {
if (err) {
res.json({info: 'error during finding cat', error: err});
} else {
if (cat) {
_.merge(cat,req.body);
cat.save(function (err) {
if(err) {
res.json({info: 'error during cat update', error: err});
} else {
res.json({info: 'cat updated successfully'});
}
});
} else {
res.json({info: 'cat not found'});
}
}
});
});
/* Delete */
app.delete('/cat/:id', function (req,res) {
Cat.findByIdAndRemove(req.params.id, function (err) {
if (err) {
res.json({info: 'error during remove cat', error: err});
} else {
res.json({info: 'cat removed successfully'});
}
});
});
};
Working with Mongo
RoboMongo
Native and cross-platform MongoDB manager
Examples
show dbs
use cats
show collections
db.cats.find(); // find all
db.cats.find({"name":"Pere"}); // find cats with name 'Pere'
Nodejs Shines At
NodeJs works very well as a middleware, a “traffic controller”.
Adding Additional Servers
Run servers in the background
npm install -g forever
forever list
“Request” Module
Let us do requests from one server to another. “Think of it as a node version of Postman”.
npm install --save request
Check for open ports
sudo lsof -i -n -P | grep LISTEN
Using npm for scripts
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "forever start ./servers/cat.js | forever start ./servers/dog.js | nodemon ./servers/pet.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.15.0",
"express": "^4.13.4",
"lodash": "^4.5.1",
"mongoose": "^4.4.6",
"request": "^2.69.0"
}
}
Working Asynchronously
Processing the requests Asynchronously
Async it is similar to $q in angular but for the backend side.
npm install --save async
Adding a Cache
Implementing a Redis Cache
Redis is an open source (BSD licensed), in-memory data structure store, used as database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries.
Installing Redis on Windows
# Installing Chocolatey
@powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin
choco install redis-64
npm install --save redis
Usage
var r = require('request').defaults({ json: true });
var async = require('async');
var redis = require('redis');
var client = redis.createClient(6379, '127.0.0.1');
module.exports = function(app) {
app.get('/ping', function (req, res) {
res.json({pong: Date.now()});
});
/* Read */
app.get('/pets', function(req, res) {
async.parallel({
cat: function (callback) {
r({ uri: 'http://localhost:3000/cat' }, function (error, response, body) {
if (error) {
callback({ service: 'cat', error: error });
return;
}
if (!error && response.statusCode === 200) {
callback(null, body);
} else {
callback(response.statusCode);
}
});
},
dog: function (callback) {
client.get('http://localhost:3001/dog', function (error,dog) {
if (error) {throw error;}
if (dog) {
callback(null, JSON.parse(dog));
} else {
r({uri: 'http://localhost:3001/dog'}, function (error,response,body) {
if (error) {
callback({service: 'dog', error: error});
return;
}
if (!error && response.statusCode === 200) {
callback(null,body);
//client.set('http://localhost:3001/dog', JSON.stringify(body.data), function (error) {
client.setex('http://localhost:3001/dog', 10, JSON.stringify(body.data), function (error) {
if (error) { throw error;}
});
} else {
callback(response.statusCode);
}
});
}
})
}
},
function (error,results) {
res.json({
error: error,
results: results
});
});
});
};