Skip to content

Commit

Permalink
refactor: FORMS-1139 add db error handler (bcgov#1384)
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterMoar authored Jun 5, 2024
1 parent 1d69f80 commit 753abda
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 30 deletions.
92 changes: 62 additions & 30 deletions app/src/forms/common/middleware/errorHandler.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,77 @@
const Problem = require('api-problem');
const Objection = require('objection');

module.exports.errorHandler = async (err, _req, res, next) => {
let error;

if (err instanceof Objection.DataError) {
error = new Problem(422, {
/**
* Given a subclass of DBError will create and throw the corresponding Problem.
* If the error is of an unknown type it will not be converted.
*
* @param {DBError} error the error to convert to a Problem.
* @returns nothing
*/
const _throwObjectionProblem = (error) => {
if (error instanceof Objection.DataError) {
throw new Problem(422, {
detail: 'Sorry... the database does not like the data you provided :(',
});
} else if (err instanceof Objection.NotFoundError) {
error = new Problem(404, {
}

if (error instanceof Objection.NotFoundError) {
throw new Problem(404, {
detail: "Sorry... we still haven't found what you're looking for :(",
});
} else if (err instanceof Objection.UniqueViolationError) {
error = new Problem(422, {
detail: 'Unique Validation Error',
}

if (error instanceof Objection.ConstraintViolationError) {
throw new Problem(422, {
detail: 'Constraint Violation Error',
});
} else if (err instanceof Objection.ValidationError) {
error = new Problem(422, {
}

if (error instanceof Objection.ValidationError) {
throw new Problem(422, {
detail: 'Validation Error',
errors: err.data,
errors: error.data,
});
} else if (!(err instanceof Problem) && (err.status || err.statusCode)) {
}
};

/**
* Send an error response for all errors except 500s, which are handled by the
* code in app.js.
*
* @param {*} err the Error that occurred.
* @param {*} _req the Express object representing the HTTP request - unused.
* @param {*} res the Express object representing the HTTP response.
* @param {*} next the Express chaining function.
* @returns nothing
*/
module.exports.errorHandler = async (err, _req, res, next) => {
try {
if (err instanceof Objection.DBError || err instanceof Objection.NotFoundError || err instanceof Objection.ValidationError) {
_throwObjectionProblem(err);
}

// Express throws Errors that are not Problems, but do have an HTTP status
// code. For example, 400 is thrown when POST bodies are malformed JSON.
error = new Problem(err.status || err.statusCode, {
detail: err.message,
});
} else {
error = err;
}
if (!(err instanceof Problem) && (err.status || err.statusCode)) {
throw new Problem(err.status || err.statusCode, {
detail: err.message,
});
}

if (error instanceof Problem && error.status !== 500) {
// Handle here when not an internal error. These are mostly from buggy
// systems using API Keys, but could also be from frontend bugs. Save the
// ERROR level logs (below) for only the things that need investigation.
error.send(res);
} else {
// HTTP 500 Problems and all other exceptions should be handled by the error
// handler in app.js. It will log them at the ERROR level and include a full
// stack trace.
next(error);
// Not sure what it is, so also handle it in the catch block.
throw err;
} catch (error) {
if (error instanceof Problem && error.status !== 500) {
// Handle here when not an internal error. These are mostly from buggy
// systems using API Keys, but could also be from frontend bugs. Note that
// this does not log the error (see below).
error.send(res);
} else {
// HTTP 500 Problems and all other exceptions should be handled by the
// error handler in app.js. It will log them at the ERROR level and
// include a full stack trace.
next(error);
}
}
};
13 changes: 13 additions & 0 deletions app/tests/unit/forms/common/middleware/errorHandler.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,19 @@ describe('test error handler middleware', () => {
expect(res.end).toBeCalledWith(expect.stringContaining('429'));
});

it('should pass through unknown objection errors', () => {
const error = new Objection.DBError({
nativeError: {
message: 'This base class is never actually instantiated',
},
});
const { res, next } = getMockRes();

middleware.errorHandler(error, {}, res, next);

expect(next).toBeCalledWith(error);
});

it('should pass through any 500s', () => {
const error = new Problem(500);
const { next } = getMockRes();
Expand Down

0 comments on commit 753abda

Please sign in to comment.