143 lines
3.8 KiB
JavaScript
143 lines
3.8 KiB
JavaScript
/**
|
|
* Support utilities for using Promises, particularls Kris Kowal's Q:
|
|
* @see {@link https://github.com/kriskowal/q}
|
|
*
|
|
* In particular, these utilities help with sending error responses through
|
|
* a promise chain. The first time an error is received, the error handler
|
|
* should call `return returnChainedError()`. Later handlers should then check
|
|
* if there is a previous error (`hasChainedError()`), and if so just send it
|
|
* on (`return resendChainedError()`). The final error handler can then return
|
|
* the chained error.
|
|
*/
|
|
'use strict';
|
|
|
|
var Q = require('q');
|
|
var httpStatus = require('http-status-codes');
|
|
var _ = require('lodash');
|
|
var debug = require('debug')('webconsole-api:utils:promises');
|
|
|
|
const ERR_KEY = 'cmcrdErrResponse';
|
|
|
|
module.exports = {
|
|
ERR_KEY: ERR_KEY,
|
|
ErrorResponse: ErrorResponse,
|
|
|
|
sendErrorResponse: sendErrorResponse,
|
|
|
|
returnChainedError: returnChainedError,
|
|
resendChainedError: resendChainedError,
|
|
hasChainedError: hasChainedError,
|
|
getChainedError: getChainedError
|
|
};
|
|
|
|
/**
|
|
* Constructs a new ErrorResponse that is used for passing errors through a
|
|
* promise chain.
|
|
*
|
|
* @class
|
|
* @param {integer} httpcode - the http status code to respond with
|
|
* @param {integer} code - the Bridge error code
|
|
* @param {String} info - the further information string
|
|
*/
|
|
function ErrorResponse(httpcode, code, info) {
|
|
//
|
|
// Assign the values
|
|
//
|
|
this.httpcode = httpcode;
|
|
this.errorInfo = {
|
|
code: code,
|
|
info: info
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Returns an error in an appropriate way for chaining through a promise
|
|
* chain.
|
|
*
|
|
* @param {Object} err - the existing error for manipulating
|
|
* @param {integer} httpcode - the http status code to respond with
|
|
* @param {integer} code - the Bridge error code
|
|
* @param {String} info - the further information string
|
|
*
|
|
* return {Promise} - rejected promise with the error info added
|
|
*/
|
|
function returnChainedError(err, httpcode, code, info) {
|
|
var response = new ErrorResponse(httpcode, code, info);
|
|
|
|
//
|
|
// If err isn't already an object, turn it into one
|
|
//
|
|
if (!_.isObject(err)) {
|
|
var original = err;
|
|
err = {
|
|
originalErr: err
|
|
};
|
|
}
|
|
err[ERR_KEY] = response;
|
|
|
|
return resendChainedError(err);
|
|
}
|
|
|
|
/**
|
|
* Sends on an error again as a rejected promise
|
|
*
|
|
* @param {Object} err - the existing error for manipulating
|
|
*
|
|
* return {Promise} - rejected promise with the error info added
|
|
*/
|
|
function resendChainedError(err) {
|
|
var deferred = Q.defer();
|
|
deferred.reject(err);
|
|
return deferred.promise;
|
|
}
|
|
|
|
/**
|
|
* Checks if there is already a chained error in this error object
|
|
*
|
|
* @param {Object} err - the err reason object
|
|
*/
|
|
function hasChainedError(err) {
|
|
return err.hasOwnProperty(ERR_KEY);
|
|
}
|
|
|
|
/**
|
|
* Gets the chained error information
|
|
*
|
|
* @param {Object} err - the error object
|
|
*
|
|
* @return {?ErrorResponse} - the error response info (if any)
|
|
*/
|
|
function getChainedError(err) {
|
|
if (!hasChainedError(err)) {
|
|
return null;
|
|
} else {
|
|
return err[ERR_KEY];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns an error back to the client. This is either the error that has
|
|
* been passed through the promise chain, or a default unknown error is
|
|
* returned.
|
|
*
|
|
* @param {Object} res - Express response object
|
|
* @param {Object} err - the error object
|
|
*/
|
|
function sendErrorResponse(res, err) {
|
|
var response = getChainedError(err);
|
|
if (!response) {
|
|
response = new ErrorResponse(
|
|
httpStatus.INTERNAL_SERVER_ERROR,
|
|
-1,
|
|
'Unknown error'
|
|
);
|
|
}
|
|
|
|
debug(' - send error: [%s] - {%d, %s}',
|
|
response.httpcode,
|
|
response.errorInfo.code,
|
|
response.errorInfo.info
|
|
);
|
|
res.status(response.httpcode).json(response.errorInfo);
|
|
}
|