Skip to content

Commit

Permalink
Added error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
andreareginato committed Jan 21, 2013
1 parent c8a5361 commit fc8e70d
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 123 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,19 @@ Currently the Authorization Code and Resource Owner Password Credentials grant t
have helper strategy classes that simplify client use. They are available via the #authCode
and #password methods respectively.
```javascript
// Authorization code flow
var uri = OAuth2.AuthCode.authorizeURL({ redirect_uri: 'http://localhost:3000/callback');
var token = OAuth2.AuthCode.getToken({ code: 'authorization-code', redirectURI: 'http://localhost:3000/callback' }, callback);

// Password credentials flow
var token = OAuth2.Password.getToken({ username: 'username', 'password': 'password' }, callback);
```
If the functions fails an error object is passed as first argument to the callback.
The body response object is always the last argument.
## Errors
Exceptions are raised when a 4xx or 5xx status code is returned.
Expand Down
30 changes: 4 additions & 26 deletions lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ var exports = module.exports,

//
// Core module.

//
module.exports = function(config) {

var errors = require("./error.js")();


// High level method to call API
function api(method, path, params, callback) {
Expand Down Expand Up @@ -46,34 +48,11 @@ module.exports = function(config) {
if (error) throw new Error('Simple OAuth2: something went worng during the request');
if (process.env.DEBUG) console.log('Simple OAuth2: checking response body', body);

if (response.statusCode >= 500) body = errorResponse(response);
if (response.statusCode >= 400) return callback(new HTTPError(body), null)

if (response.statusCode >= 400) return callback(new errors.HTTPError(response.statusCode), null)
callback(error, body);
}


// 500 Error response
function errorResponse(response) {
return { "status": response.statusCode,
"request": response.request.uri.href,
"error": {
"code": "notifications.service.not_working",
"description": "Lelylan is not working correctly (we are investigating)."
}
}
}


// Personalized errror
function HTTPError(message) {
Error.call(this);
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
this.message = message;
} HTTPError.prototype.__proto__ = Error.prototype;


function isEmpty(ob){
for(var i in ob){ return false;}
return true;
Expand All @@ -84,6 +63,5 @@ module.exports = function(config) {
'call': call,
'data': data,
'api': api,
'HTTPError': HTTPError
}
};
65 changes: 65 additions & 0 deletions lib/error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// A NodeJS module to handle OAuth2 server errors.
//
module.exports = function() {

// Personalized errror
function HTTPError(status) {
Error.call(this);
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
this.message = { status: status, message: statusCodes[status] };
} HTTPError.prototype.__proto__ = Error.prototype;


// List of all 4xx and 5xx status code plus their description
var statusCodes = {
400: "Bad Request",
401: "Unauthorized",
402: "Payment Required",
403: "Forbidden",
404: "Not Found",
405: "Method Not Allowed",
406: "Not Acceptable",
407: "Proxy Authentication Required",
408: "Request Timeout",
409: "Conflict",
410: "Gone",
411: "Length Required",
412: "Precondition Failed",
413: "Request Entity Too Large",
414: "Request-URI Too Long",
415: "Unsupported Media Type",
416: "Requested Range Not Satisfiable",
417: "Expectation Failed",
420: "Enhance Your Calm",
422: "Unprocessable Entity",
423: "Locked",
424: "Failed Dependency",
425: "Unordered Collection",
426: "Upgrade Required",
428: "Precondition Required",
429: "Too Many Requests",
431: "Request Header Fields Too Large",
444: "No Response",
449: "Retry With",
499: "Client Closed Request",
500: "Internal Server Error",
501: "Not Implemented",
502: "Bad Gateway",
503: "Service Unavailable",
504: "Gateway Timeout",
505: "HTTP Version Not Supported",
506: "Variant Also Negotiates",
507: "Insufficient Storage",
508: "Loop Detected",
509: "Bandwidth Limit Exceeded",
510: "Not Extended",
511: "Network Authentication Required"
};


return {
'HTTPError': HTTPError
}
};
2 changes: 1 addition & 1 deletion lib/simple-oauth2.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ module.exports = function(config) {

return {
'AuthCode': require('./client/auth-code')(config),
'AccessToken': require('./client/access-token')(config),
'AccessToken': require('./client/access-token')(config)
}
};
2 changes: 1 addition & 1 deletion test/access_token.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ var credentials = { client: { id: 'client-id', secret: 'client-secret', site: 'h
var request, result, token, error;


describe.only('OAuth2.AccessToken',function() {
describe('OAuth2.AccessToken',function() {

beforeEach(function(done) {
var params = { 'code': 'code', 'redirect_uri': 'http://callback.com', 'grant_type': 'authorization_code' };
Expand Down
1 change: 0 additions & 1 deletion test/auth-code.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
var credentials = { client: { id: 'client-id', secret: 'client-secret', site: 'https://example.org' } },
OAuth2 = require('./../lib/simple-oauth2.js')(credentials),
qs = require('querystring'),
nock = require('nock');

var request, result, error;
Expand Down
150 changes: 56 additions & 94 deletions test/errors.js
Original file line number Diff line number Diff line change
@@ -1,96 +1,58 @@
//var Lelylan = require('./../lib/lelylan-node.js')({ 'token': '5f7fb8f11b8499b' });
//var nock = require('nock');
//var request, response, error;

//describe('Lelylan Error',function() {

//describe('with status code 500',function() {

//beforeEach(function(done) {
//request = nock('http://api.lelylan.com').get('/devices/1').reply(500, 'Internal Server Error');
//done();
//})

//beforeEach(function(done) {
//Lelylan.Device.find('1', function(e, r) {
//error = e; response = r; done();
//})
//})

//it('makes the HTTP request', function() {
//request.isDone();
//});

//it('return a json array',function() {
//error.should.be.a('object');
//});
//});

//describe('with status code 401',function() {

//beforeEach(function(done) {
//request = nock('http://api.lelylan.com').get('/devices/1').replyWithFile(401, __dirname + '/fixtures/errors/401.json');
//done();
//})

//beforeEach(function(done) {
//Lelylan.Device.find('1', function(e, r) {
//error = e; response = r; done();
//})
//})

//it('makes the HTTP request', function() {
//request.isDone();
//});

//it('return a json array',function() {
//error.should.be.a('object');
//});
//});

//describe('with status code 404',function() {

//beforeEach(function(done) {
//request = nock('http://api.lelylan.com').get('/devices/1').replyWithFile(404, __dirname + '/fixtures/errors/404.json');
//done();
//})

//beforeEach(function(done) {
//Lelylan.Device.find('1', function(e, r) {
//error = e; response = r; done();
//})
//})

//it('makes the HTTP request', function() {
//request.isDone();
//});

//it('return a json array',function() {
//error.should.be.a('object');
//});
//});

//describe('with status code 422',function() {

//beforeEach(function(done) {
//request = nock('http://api.lelylan.com').get('/devices/1').replyWithFile(422, __dirname + '/fixtures/errors/422.json');
//done();
//})

//beforeEach(function(done) {
//Lelylan.Device.find('1', function(e, r) {
//error = e; response = r; done();
//})
//})

//it('makes the HTTP request', function() {
//request.isDone();
//});

//it('return a json array',function() {
//error.should.be.a('object');
//});
//});
//})
var credentials = { client: { id: 'client-id', secret: 'client-secret', site: 'https://example.org' } },
OAuth2 = require('./../lib/simple-oauth2.js')(credentials),
nock = require('nock');

var request, result, error;

describe('Simple OAuth2 Error',function() {

describe('with status code 401',function() {

beforeEach(function(done) {
var params = { 'code': 'code', 'redirect_uri': 'http://callback.com', 'grant_type': 'authorization_code' };
request = nock('https://example.org:443').post('/oauth/token', params).reply(401, 'Unauthorized');
done();
});

beforeEach(function(done) {
var params = { 'code': 'code', 'redirect_uri': 'http://callback.com' }
OAuth2.AuthCode.getToken(params, function(e, r) {
error = e; result = r; done();
});
});

it('makes the HTTP request', function() {
request.isDone();
});

it('returns an access token',function() {
error.message.message.should.eql('Unauthorized');
});
});

describe('with status code 500',function() {

beforeEach(function(done) {
var params = { 'code': 'code', 'redirect_uri': 'http://callback.com', 'grant_type': 'authorization_code' };
request = nock('https://example.org:443').post('/oauth/token', params).reply(500, 'Server Error');
done();
});

beforeEach(function(done) {
var params = { 'code': 'code', 'redirect_uri': 'http://callback.com' }
OAuth2.AuthCode.getToken(params, function(e, r) {
error = e; result = r; done();
});
});

it('makes the HTTP request', function() {
request.isDone();
});

it('returns an access token',function() {
error.message.message.should.eql('Internal Server Error');
});
});
})


0 comments on commit fc8e70d

Please sign in to comment.