Skip to content

Commit

Permalink
Parse API error responses.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaredhanson committed Aug 15, 2013
1 parent ad252b2 commit 89bec95
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 5 deletions.
29 changes: 29 additions & 0 deletions lib/errors/liveconnectapierror.js
@@ -0,0 +1,29 @@
/**
* `LiveConnectAPIError` error.
*
* References:
* - http://msdn.microsoft.com/en-us/library/live/hh243648.aspx#error
*
* @constructor
* @param {String} [message]
* @param {String} [code]
* @api public
*/
function LiveConnectAPIError(message, code) {
Error.call(this);
Error.captureStackTrace(this, arguments.callee);
this.name = 'LiveConnectAPIError';
this.message = message;
this.code = code;
}

/**
* Inherit from `Error`.
*/
LiveConnectAPIError.prototype.__proto__ = Error.prototype;


/**
* Expose `LiveConnectAPIError`.
*/
module.exports = LiveConnectAPIError;
21 changes: 16 additions & 5 deletions lib/strategy.js
@@ -1,10 +1,11 @@
/**
* Module dependencies.
*/
var util = require('util')
var parse = require('./profile').parse
, util = require('util')
, OAuth2Strategy = require('passport-oauth2')
, InternalOAuthError = require('passport-oauth2').InternalOAuthError
, parse = require('./profile').parse;
, LiveConnectAPIError = require('./errors/liveconnectapierror');


/**
Expand Down Expand Up @@ -72,7 +73,17 @@ util.inherits(Strategy, OAuth2Strategy);
*/
Strategy.prototype.userProfile = function(accessToken, done) {
this._oauth2.get(this._userProfileURL, accessToken, function (err, body, res) {
if (err) { return done(new InternalOAuthError('Failed to fetch user profile', err)); }
if (err) {
if (err.data) {
try {
var json = JSON.parse(err.data);
if (json.error) {
return done(new LiveConnectAPIError(json.error.message, json.error.code));
}
} catch (_) {}
}
return done(new InternalOAuthError('Failed to fetch user profile', err));
}

try {
var json = JSON.parse(body);
Expand All @@ -83,8 +94,8 @@ Strategy.prototype.userProfile = function(accessToken, done) {
profile._json = json;

done(null, profile);
} catch(e) {
done(e);
} catch (ex) {
done(ex);
}
});
}
Expand Down
50 changes: 50 additions & 0 deletions test/strategy.profile.error.test.js
@@ -0,0 +1,50 @@
var WindowsLiveStrategy = require('../lib/strategy');


describe('Strategy#userProfile', function() {

var strategy = new WindowsLiveStrategy({
clientID: 'ABC123',
clientSecret: 'secret'
},
function() {});

// mock
strategy._oauth2.get = function(url, accessToken, callback) {
if (url != 'https://apis.live.net/v5.0/me') { return callback(new Error('wrong url argument')); }
if (accessToken != 'token') { return callback(new Error('wrong token argument')); }

var body = '{ \
"error": { \
"code": "request_token_expired", \
"message": "The provided access token has expired." \
} \
}';

callback({ statusCode: 401, data: body });
}

describe('encountering an API error', function() {
var err, profile;

before(function(done) {
strategy.userProfile('token', function(e, p) {
err = e;
profile = p;
done();
});
});

it('should error', function() {
expect(err).to.be.an.instanceOf(Error);
expect(err.constructor.name).to.equal('LiveConnectAPIError');
expect(err.message).to.equal('The provided access token has expired.');
expect(err.code).to.equal('request_token_expired');
});

it('should not load profile', function() {
expect(profile).to.be.undefined;
});
});

});

0 comments on commit 89bec95

Please sign in to comment.