Developing a RESTful API

Let's do a little more work setting up our SPA by building out some resourceful routing as part of a RESTFul API that we can connect later to our database and our client-side code. We're lucky that Express has such a vibrant community of developers building many add-ons, and we're going to use one for resourceful routing.

Installing resourceful routing

The first thing we need to do is to install our module, which will provide us with some resourceful routing:

npm install resource-routing -save

This installs the resourceful routing plugin we're going to use, and saves a reference to the package.json file.

Next, we need to do some setup in our app.js file:

var express = require('express'); 
var path = require('path'); 
var favicon = require('serve-favicon'); 
var logger = require('morgan'); 
var cookieParser = require('cookie-parser'); 
var bodyParser = require('body-parser'); 
var isJSON = require('./utils/json'); 
var routing = require('resource-routing');
var controllers = path.resolve('./controllers'); 
 
//Database stuff 
var mongodb = require('mongodb'); 
var monk = require('monk'); 
var db = monk('localhost:27017/giftapp') 
 
var routes = require('./routes/index'); 
var users = require('./routes/users'); 
 
var app = express(); 
routing.expose_routing_table(app, { at: ""/my-routes"" }); 
 
// view engine setup 
app.set('views', path.join(__dirname, 'views')); 
app.set('view engine', 'ejs'); 
 
app.set('x-powered-by', false); 
 
app.locals.appName = ""My Gift App""; 
 
// uncomment after placing your favicon in /public 
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); 
app.use(logger('dev')); 
app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({ extended: false })); 
app.use(cookieParser()); 
app.use(express.static(path.join(__dirname, 'public'))); 
app.use(isJSON); 
 
//Database middlewear 
app.use(function(req,res,next){ 
    req.db = db; 
    next(); 
}); 
 
app.use('/', routes); 
app.use('/users', users); 
 
routing.resources(app, controllers, ""giftlist""); 
 
// catch 404 and forward to error handler 
app.use(function(req, res, next) { 
  var err = new Error('Not Found'); 
  err.status = 404; 
  next(err); 
}); 
 
// error handlers 
 
// development error handler 
// will print stacktrace 
if (app.get('env') === 'development') { 
  app.use(function(err, req, res, next) { 
    res.status(err.status || 500); 
    res.render('error', { 
      message: err.message, 
      error: err 
    }); 
  }); 
} 
 
// production error handler 
// no stacktraces leaked to user 
app.use(function(err, req, res, next) { 
  res.status(err.status || 500); 
  res.render('error', { 
    message: err.message, 
    error: {} 
  }); 
}); 
 
module.exports = app; 

We pull in the resource routing module using require() and assign it to the variable routing. Then we create a shortcut variable to a controllers directory, which we will be building next.

We add the following code, routing.expose_routing_table(app,{at:""/my-routes""}); which allows us to view our routing table at the URL my-routes. Obviously, this is not something we'd leave intact in production, but it's a useful debugging tool.

Finally, we set up our resourceful routing for giftlists with routing.resources(app,controllers,""giftlist"");. This won't do anything yet because we haven't set up our controller.

Building out giftlist controller

By default, our resourceful router will build a number of standard restful routes for us, including:

GET    /giftlist             giftlist_controller.index 
GET    /giftlist.format      giftlist_controller.index 
GET    /giftlist/new         giftlist_controller.new 
GET    /giftlist/new.format  giftlist_controller.new 
POST   /giftlist             giftlist_controller.create 
POST   /giftlist:format      giftlist_controller.create 
GET    /giftlist/:id         giftlist_controller.show 
GET    /giftlist/:id.format  giftlist_controller.show 
GET    /giftlist/:id/edit    giftlist_controller.edit 
GET    /giftlist/:id/edit.format  giftlist_controller.edit 
PUT    /giftlist/:id         giftlist_controler.update 
PUT    /giftlist/:id.format  giftlist_controller.update 
DELETE    /giftlist/:id      giftlist_controller.destroy 
DELETE    /giftlist/:id.format   giftlist_controller.destroy 

As you can see, these routes provide use with basic CRUD (create, read, update, delete) functionality.

However, these routes will only be created if the controller and routes actually exist, so we need to build them. Create a controllers directory in your giftapp folder with a file called giftlist_controller.js. Our plugin will add the _controller part when it goes to load our controller, so be sure to name it correctly. For now, we are going to stub out our routes to make sure they are working:

exports.index = function(req, res){ 
    res.send('giftlist index'); 
}; 
 
exports.new = function(req, res){ 
    res.send('new giftlist'); 
}; 
 
exports.create = function(req, res){ 
    res.send('create giftlist'); 
}; 
 
exports.show = function(req, res){ 
    res.send('show giftlist'+ req.params.id); 
}; 
 
exports.edit = function(req, res){ 
    res.send('edit giftlist'); 
}; 
 
exports.update = function(req, res){ 
    res.send('update giftlist'); 
}; 
 
exports.destroy = function(req, res){ 
    res.send('destroy giftlist'); 
}; 

As you can see, each of our route handlers is a function that receives the request and response objects.

Restart your server and navigate to localhost:3000/giftlist/17, where you should see:

show giftlist 17 

Responding with different data formats

Our resourceful routes can also support different data formats, so let's stub those out as well, and we'll also use our isJSON property in our giftlist_controller.js:

exports.index = function(req, res){ 
    if(req.params.format == ""json"" || req.isJSON){ 
        res.json({""title"":""giftlist index""}) 
    }else{ 
        res.send('<h1>giftlist index</h1>'); 
    } 
 
}; 
 
exports.new = function(req, res){ 
    exports.index = function(req, res){ 
        if(req.params.format == ""json"" || req.isJSON){ 
            res.json({""title"":""new giftlist""}) 
        }else{ 
            res.send('<h1>new giftlist</h1>'); 
        } 
 
    }; 
 
}; 
 
exports.create = function(req, res){ 
    exports.index = function(req, res){ 
        if(req.params.format == ""json"" || req.isJSON){ 
            res.json({""title"":""create giftlist""}) 
        }else{ 
            res.send('<h1>create giftlist</h1>'); 
        } 
 
    }; 
 
}; 
 
exports.show = function(req, res){ 
    exports.index = function(req, res){ 
        if(req.params.format == ""json"" || req.isJSON){ 
            res.json({ ""title"":""show giftlist"", ""giftlist"":req.params.id }) 
        }else{ 
            res.send('<h1>show giftlist' + req.params.id + '</h1>'); 
        } 
 
    }; 
 
}; 
 
exports.edit = function(req, res){ 
    exports.index = function(req, res){ 
        if(req.params.format == ""json"" || req.isJSON){ 
            res.json({ ""title"":""edit giftlist"", ""giftlist"":req.params.id }) 
        }else{ 
            res.send('<h1>edit giftlist' + req.params.id + '</h1>'); 
        } 
 
    }; 
 
}; 
 
exports.update = function(req, res){ 
    exports.index = function(req, res){ 
        if(req.params.format == ""json"" || req.isJSON){ 
            res.json({ ""title"":""update giftlist"", ""giftlist"":req.params.id }) 
        }else{ 
            res.send('<h1>update giftlist' + req.params.id + '</h1>'); 
        } 
 
    }; 
 
}; 
 
exports.destroy = function(req, res){ 
    exports.index = function(req, res){ 
        if(req.params.format == ""json"" || req.isJSON){ 
            res.json({ ""title"":""delete giftlist"", ""giftlist"":req.params.id }) 
        }else{ 
            res.send('<h1>delete giftlist' + req.params.id + '</h1>'); 
        } 
 
    }; 
 
}; 

Here, we added tests to each of our routes to see if the client is requesting JSON data. If they are, we return JSON. Otherwise, we return HTML.

We check to see if the client is expecting JSON in two ways.

First, we look to see if the req.params.format is json. Using this resourceful routing middleware, appending a .:format to the URL adds that format to the req.params object as the value of the format. In other words, entering the URL localhost:3000/giftlist.json triggers the giftlist_controller.index route, setting the format parameter to json.

The second method is to rely on the req.isJSON parameter set by our middleware.

In the next chapter, we will connect these resourceful routes to CRUD operations on our database, and start to render data to a page as we flesh out our SPA.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.94.190