Verifing form input by making http request in Node

I have a form whose submit button calls

exports.postUpdateProfile = function(req, res, next) {
  User.findById(req.user.id, function(err, user) {
    if (err) return next(err);
    user.email = req.body.email || '';
    user.profile.name = req.body.name || '';
    //check req.body.rescueTimeKey by making http request,
    //and parsing response to ensure the key is good
    user.profile.rescueTimeKey = req.body.rescueTimeKey;

    user.save(function(err) {
      if (err) return next(err);
      req.flash('success', { msg: 'Profile information updated.' });
      res.redirect('/account');
    });
  });
};

I want to make sure the req.body.rescueTimeKey is valid before saving the profile, I’ve tried to create a module to perform that check…

//rescue-time.js module

var request = require('request');
exports.validKey = function(key){
var options = {
    url: 'https://www.rescuetime.com/anapi/data?key=' + key,
    json: true
};

var cb = function callback(error, response, body){  
    if(error || body.error){
        //Key is bad, flash message and don't allow save
    }
    //key is good, save profile
};
request(options, cb);
}

As you might imagine I am not fully grasping the node style of using callbacks when making async calls, any help to re-organize this code is greatly appreciated.

Answer

What you will want to do is add an extra argument to your validKey function to accept a callback which is what we will use after the request.

So your rescue-time.js will look something like this:

// rescue-time.js
var request = require('request');

exports.validKey = function(key, cb) {
  var options = {
    url: 'https://www.rescuetime.com/anapi/data?key=' + key,
    json: true
  };

  request(options, function (error, response, body) {
    if(error || body.error){
        cb(false)
    }
    else {
      cb(true);
    }
  });
};``

We’re returning a boolean result of true or false if the key is valid.

Inside your controller you will want something like the following:

var rescueTime = require('./path/to/rescue-time.js');

exports.postUpdateProfile = function(req, res, next) {
  User.findById(req.user.id, function(err, user) {
    if (err) return next(err);
    user.email = req.body.email || '';
    user.profile.name = req.body.name || '';
    //check req.body.rescueTimeKey by making http request,
    //and parsing response to ensure the key is good
    user.profile.rescueTimeKey = req.body.rescueTimeKey;

    // We're sending in a callback function that will have a "valid" result as a second arg
    rescueTime.validKey(user.profile.rescueTimeKey, function(valid) {
      // check if valid returned true or false and act accordingly 
      if (!valid) {
        req.flash('error', 'invalid rescueTime key');
        res.redirect('/account');
      }
      else {
        user.save(function(err) {
          if (err) return next(err);
          req.flash('success', { msg: 'Profile information updated.' });
          res.redirect('/account');
        });
      }    
    });
  });
}; 

Keep in mind this code wasn’t tested at all, but more of an example on what you need to do to obtain your desired results.

Leave a Reply

Your email address will not be published. Required fields are marked *