Add type definition and writeErrorToResponse

This commit is contained in:
shimks 2018-08-08 13:28:45 -04:00
parent 8b35494da0
commit 80ebf30cfa
5 changed files with 139 additions and 38 deletions

View File

@ -46,6 +46,29 @@ app.use(errorHandler({
app.listen(3000); app.listen(3000);
``` ```
The module also exports `writeErrorToResponse`, a non-middleware flavor of the
error handler:
```js
const http = require('http');
const writeErrorToResponse = require('strong-error-handler')
.writeErrorToResponse;
const errHandlingOptions = {debug: process.env.NODE_ENV === 'development'}
http
.createServer((req, res) => {
if (errShouldBeThrown) {
writeErrorToResponse(
new Error('something went wrong'),
req,
res,
errHandlingOptions,
);
}
})
.listen(3000);
```
In LoopBack applications, add the following entry to `server/middleware.json`: In LoopBack applications, add the following entry to `server/middleware.json`:
```json ```json

64
index.d.ts vendored Normal file
View File

@ -0,0 +1,64 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: strong-error-handler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
// Type definitions for strong-error-handler 3.x
// Project: https://github.com/strongloop/strong-error-handler
// Definitions by: Kyusung Shim <https://github.com/shimks>
// TypeScript Version: 3.0
import * as Express from 'express';
export = errorHandlerFactory;
/**
* Creates a middleware function for error-handling
* @param options Options for error handler settings
*/
declare function errorHandlerFactory(
options?: errorHandlerFactory.ErrorHandlerOptions
): errorHandlerFactory.StrongErrorHandler;
declare namespace errorHandlerFactory {
/**
* Writes thrown error to response
* @param err Error to handle
* @param req Incoming request
* @param res Response
* @param options Options for error handler settings
*/
function writeErrorToResponse(
err: Error,
req: Express.Request,
res: Express.Response,
options?: ErrorWriterOptions
): void;
/**
* Error-handling middleware function. Includes server-side logging
*/
type StrongErrorHandler = (
err: Error,
req: Express.Request,
res: Express.Response,
next: (err?: any) => void
) => void;
/**
* Options for writing errors to the response
*/
interface ErrorWriterOptions {
debug?: boolean;
safeFields?: string[];
defaultType?: string;
negotiateContentType?: boolean;
}
/**
* Options for error-handling
*/
interface ErrorHandlerOptions extends ErrorWriterOptions {
log?: boolean;
}
}

View File

@ -23,7 +23,7 @@ function noop() {
* @param {Object} options * @param {Object} options
* @returns {Function} * @returns {Function}
*/ */
exports = module.exports = function createStrongErrorHandler(options) { function createStrongErrorHandler(options) {
options = options || {}; options = options || {};
debug('Initializing with options %j', options); debug('Initializing with options %j', options);
@ -32,9 +32,23 @@ exports = module.exports = function createStrongErrorHandler(options) {
var logError = options.log !== false ? logToConsole : noop; var logError = options.log !== false ? logToConsole : noop;
return function strongErrorHandler(err, req, res, next) { return function strongErrorHandler(err, req, res, next) {
logError(req, err);
writeErrorToResponse(err, req, res, options);
};
};
/**
* Writes thrown error to response
*
* @param {Error} err
* @param {Express.Request} req
* @param {Express.Response} res
* @param {Object} options
*/
function writeErrorToResponse(err, req, res, options) {
debug('Handling %s', err.stack || err); debug('Handling %s', err.stack || err);
logError(req, err); options = options || {};
if (res._header) { if (res._header) {
debug('Response was already sent, closing the underlying connection'); debug('Response was already sent, closing the underlying connection');
@ -59,4 +73,6 @@ exports = module.exports = function createStrongErrorHandler(options) {
debug(msg); debug(msg);
} }
}; };
};
exports = module.exports = createStrongErrorHandler;
exports.writeErrorToResponse = writeErrorToResponse;

View File

@ -17,6 +17,7 @@
"posttest": "npm run lint" "posttest": "npm run lint"
}, },
"dependencies": { "dependencies": {
"@types/express": "^4.16.0",
"accepts": "^1.3.3", "accepts": "^1.3.3",
"debug": "^3.1.0", "debug": "^3.1.0",
"ejs": "^2.6.1", "ejs": "^2.6.1",

View File

@ -78,7 +78,8 @@ describe('strong-error-handler', function() {
request.get('/').expect( request.get('/').expect(
507, 507,
{error: {statusCode: 507, message: 'Insufficient Storage'}}, {error: {statusCode: 507, message: 'Insufficient Storage'}},
done); done
);
}); });
}); });
@ -145,7 +146,8 @@ describe('strong-error-handler', function() {
it('handles array argument', function(done) { it('handles array argument', function(done) {
givenErrorHandlerForError( givenErrorHandlerForError(
[new TypeError('ERR1'), new Error('ERR2')], [new TypeError('ERR1'), new Error('ERR2')],
{log: true}); {log: true}
);
request.get('/api').end(function(err) { request.get('/api').end(function(err) {
if (err) return done(err); if (err) return done(err);
@ -565,8 +567,7 @@ describe('strong-error-handler', function() {
); );
done(); done();
}); });
} });
);
it('HTML-escapes all 5xx response properties in development mode', it('HTML-escapes all 5xx response properties in development mode',
function(done) { function(done) {
@ -582,8 +583,7 @@ describe('strong-error-handler', function() {
/500(.*?)a test error message&lt;img onerror=alert\(1\) src=a&gt;/, /500(.*?)a test error message&lt;img onerror=alert\(1\) src=a&gt;/,
done done
); );
} });
);
it('contains subset of properties when status=4xx', function(done) { it('contains subset of properties when status=4xx', function(done) {
var error = new ErrorWithProps({ var error = new ErrorWithProps({
@ -750,8 +750,7 @@ describe('strong-error-handler', function() {
request.get('/') request.get('/')
.set('Accept', 'text/html') .set('Accept', 'text/html')
.expect('Content-Type', /^application\/json/, done); .expect('Content-Type', /^application\/json/, done);
} });
);
it('chooses resolved type when negotiateContentType=false + not-supported', it('chooses resolved type when negotiateContentType=false + not-supported',
function(done) { function(done) {
@ -762,8 +761,7 @@ describe('strong-error-handler', function() {
request.get('/') request.get('/')
.set('Accept', 'text/html') .set('Accept', 'text/html')
.expect('Content-Type', /^text\/html/, done); .expect('Content-Type', /^text\/html/, done);
} });
);
it('chooses default type when negotiateContentType=false + not-supported ', it('chooses default type when negotiateContentType=false + not-supported ',
function(done) { function(done) {
@ -773,8 +771,7 @@ describe('strong-error-handler', function() {
}); });
request.get('/') request.get('/')
.expect('Content-Type', /^application\/json/, done); .expect('Content-Type', /^application\/json/, done);
} });
);
it('honors order of accepted content-types of text/html', function(done) { it('honors order of accepted content-types of text/html', function(done) {
givenErrorHandlerForError(new Error('Some error'), { givenErrorHandlerForError(new Error('Some error'), {