Skip to content

Add errors when 4xx or 5xx #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
# breaking changes
## v0.6.x
# v0.9.x
## breaking changes

- if the response status is 4xx or 5xx: an error is thrown [#13](https://github.com/mapado/rest-client-js-sdk/pull/13)

## new features

- memoize token generation and refresh [#12](https://github.com/mapado/rest-client-js-sdk/pull/12)


# v0.6.x
## breaking changes

The `queryParam` argument was added where needed in the AbstractClient class:

- `findAll(queryParam = {}, pathParameters = {})`
- `create(entity, queryParam = {}, pathParameters = {})`

# new features
## v0.6.x
## new features
The `queryParam` argument was added where needed in the AbstractClient class:

- `update(entity, queryParam = {})`
- `update(entity, queryParam = {})`
5 changes: 1 addition & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
"name": "rest-client-sdk",
"version": "0.8.2",
"description": "Rest Client SDK for API",
"main": "dist/index.js",
"files": [
"dist"
],
"main": "src/index.js",
"scripts": {
"test": "mocha --compilers js:babel-core/register --require ./test/test_helper.js --recursive",
"test:watch": "npm run test -- --watch",
Expand Down
53 changes: 49 additions & 4 deletions src/Error.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,70 @@
* It's a bit tricky to extends native errors
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
*/

function HttpError(baseResponse, message) {
this.name = 'BadRequestError';
this.message = message || 'Bad request';
this.baseResponse = baseResponse;
this.stack = (new Error()).stack;
}
HttpError.prototype = Object.create(Error.prototype);
HttpError.prototype.constructor = HttpError;

// 400
function BadRequestError(baseResponse, message) {
this.name = 'BadRequestError';
this.message = message || 'Bad request';
this.baseResponse = baseResponse;
this.stack = (new Error()).stack;
}
BadRequestError.prototype = Object.create(HttpError.prototype);
BadRequestError.prototype.constructor = BadRequestError;

// 401
function AccessDeniedError(message, baseResponse) {
this.name = 'AccessDeniedError';
this.message = message;
this.message = message || 'Access denied';
this.baseResponse = baseResponse;
this.stack = (new Error()).stack;
}
AccessDeniedError.prototype = Object.create(Error.prototype);
AccessDeniedError.prototype = Object.create(BadRequestError.prototype);
AccessDeniedError.prototype.constructor = AccessDeniedError;

// 403
function ForbiddenError(message, baseResponse) {
this.name = 'ForbiddenError';
this.message = message;
this.message = message || 'Forbidden';
this.baseResponse = baseResponse;
this.stack = (new Error()).stack;
}
ForbiddenError.prototype = Object.create(Error.prototype);
ForbiddenError.prototype = Object.create(BadRequestError.prototype);
ForbiddenError.prototype.constructor = ForbiddenError;

// 404
function ResourceNotFoundError(baseResponse, message) {
this.name = 'ResourceNotFoundError';
this.message = message || 'Resource is not found';
this.baseResponse = baseResponse;
this.stack = (new Error()).stack;
}
ResourceNotFoundError.prototype = Object.create(BadRequestError.prototype);
ResourceNotFoundError.prototype.constructor = ResourceNotFoundError;

// 500
function InternalServerError(message, baseResponse) {
this.name = 'InternalServerError';
this.message = message || 'Internal server error';
this.baseResponse = baseResponse;
this.stack = (new Error()).stack;
}
InternalServerError.prototype = Object.create(HttpError.prototype);
InternalServerError.prototype.constructor = InternalServerError;

export {
AccessDeniedError,
ForbiddenError,
BadRequestError,
ResourceNotFoundError,
InternalServerError,
};
33 changes: 26 additions & 7 deletions src/client/AbstractClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import URI from 'urijs';
import {
AccessDeniedError,
ForbiddenError,
ResourceNotFoundError,
BadRequestError,
InternalServerError,
} from '../Error';

class AbstractClient {
Expand Down Expand Up @@ -154,14 +157,14 @@ class AbstractClient {
break;

default:
throw new AccessDeniedError(body.error_description, response);
throw new AccessDeniedError(response, body.error_description);
}
}

throw new AccessDeniedError('Unable to access ressource: 401 found !', response);
})
.catch(() => {
throw new AccessDeniedError('Unable to access ressource: 401 found !', response)
throw new AccessDeniedError('Unable to access ressource: 401 found !', response);
})
;
}
Expand All @@ -186,13 +189,29 @@ class AbstractClient {

return fetch(input, params)
.then(response => {
if (response.status === 401) {
return this._manageAccessDenied(response, input, params);
} else if (response.status === 403) {
throw new ForbiddenError('Forbidden acces: 403 found !', response);
if (response.status < 400) {
return response;
}

return response;
switch (true) {
case response.status === 401:
return this._manageAccessDenied(response, input, params);

case response.status === 403:
throw new ForbiddenError(response);

case response.status === 404:
throw new ResourceNotFoundError(response);

case response.status >= 400 && response.status < 500:
throw new BadRequestError(response);

case response.status >= 500 && response.status < 600:
throw new InternalServerError(response);

default:
return new Error(`Unexpected error, status code is ${response.status}`);
}
})
;
}
Expand Down
11 changes: 9 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import RestClientSdk from './RestClientSdk';
import {
AccessDeniedError,
ForbiddenError,
BadRequestError,
ResourceNotFoundError,
InternalServerError,
} from './Error';
import AbstractClient from './client/AbstractClient';
import TokenStorage from './TokenStorage';
Expand All @@ -13,11 +16,15 @@ import ProvidedTokenGenerator from './TokenGenerator/ProvidedTokenGenerator';
export default RestClientSdk;
export {
AbstractClient,
AccessDeniedError,
AbstractTokenGenerator,
ClientCredentialsGenerator,
ForbiddenError,
PasswordGenerator,
ProvidedTokenGenerator,
TokenStorage,

AccessDeniedError,
ForbiddenError,
BadRequestError,
ResourceNotFoundError,
InternalServerError,
};
27 changes: 26 additions & 1 deletion test/client/AbstractClient_specs.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* global describe, it, afterEach */
import fetchMock from 'fetch-mock';
import { expect } from 'chai';
import { expect, assert } from 'chai';
import { fromJS, List, Map } from 'immutable';
import * as errors from '../../src/Error';
import RestClientSdk, { AbstractClient } from '../../src';
import tokenStorageMock from '../mock/tokenStorage';

Expand Down Expand Up @@ -249,3 +250,27 @@ describe('Test Client', () => {
});
});
});

describe('Test errors', () => {
it('handle 401 and 403 errors', () => {
fetchMock
.mock(/400$/, 400)
.mock(/401$/, 401)
.mock(/403$/, 403)
.mock(/404$/, 404)
.mock(/410$/, 410)
.mock(/500$/, 500)
.getMock()
;

return Promise.all([
assert.isRejected(SomeSdk.test.find(400), errors.BadRequestError),
assert.isRejected(SomeSdk.test.find(401), errors.AccessDeniedError),
assert.isRejected(SomeSdk.test.find(403), errors.ForbiddenError),
assert.isRejected(SomeSdk.test.find(404), errors.ResourceNotFoundError),
assert.isRejected(SomeSdk.test.find(404), errors.BadRequestError),
assert.isRejected(SomeSdk.test.find(410), errors.BadRequestError),
assert.isRejected(SomeSdk.test.find(500), errors.InternalServerError),
]);
});
});