2016-05-11 07:29:31 +00:00
# strong-error-handler
2017-01-09 20:09:47 +00:00
This package is an error handler for use in both development (debug) and production environments.
2016-05-11 11:53:28 +00:00
2017-01-09 20:09:47 +00:00
In production mode, `strong-error-handler` omits details from error responses to prevent leaking sensitive information:
2016-05-11 11:53:28 +00:00
2016-08-16 19:59:59 +00:00
- For 5xx errors, the output contains only the status code and the status name from the HTTP specification.
- For 4xx errors, the output contains the full error message (`error.message`) and the contents of the `details`
2017-01-09 20:09:47 +00:00
property (`error.details`) that `ValidationError` typically uses to provide machine-readable details
2017-01-30 10:44:35 +00:00
about validation problems. It also includes `error.code` to allow a machine-readable error code to be passed
through which could be used, for example, for translation.
2016-08-16 19:59:59 +00:00
2017-01-09 20:09:47 +00:00
In debug mode, `strong-error-handler` returns full error stack traces and internal details of any error objects to the client in the HTTP responses.
2016-08-16 19:59:59 +00:00
2018-06-07 16:26:52 +00:00
## Supported versions
2020-10-12 08:06:57 +00:00
This module adopts the [Module Long Term Support (LTS) ](http://github.com/CloudNativeJS/ModuleLTS ) policy, with the following End Of Life (EOL) dates:
2018-06-07 16:26:52 +00:00
2020-10-12 08:06:57 +00:00
| Version | Status | Published | EOL |
| ---------- | --------------- | --------- | -------------------- |
| 4.x | Current | Oct 2020 | Apr 2023 _(minimum)_ |
| 3.x | Active LTS | Jun 2018 | Dec 2022 |
| 2.x | End-of-life | Mar 2017 | Oct 2020 |
Learn more about our LTS plan in the [LoopBack documentation ](http://loopback.io/doc/en/contrib/Long-term-support.html ).
2018-06-07 16:26:52 +00:00
2017-01-09 20:09:47 +00:00
## Installation
2016-05-11 07:29:31 +00:00
```bash
2017-01-09 20:09:47 +00:00
$ npm install --save strong-error-handler
2016-05-11 07:29:31 +00:00
```
2016-05-11 11:53:28 +00:00
2017-01-09 20:09:47 +00:00
## Use
2016-05-11 11:53:28 +00:00
2017-01-09 20:09:47 +00:00
In an Express-based application:
2016-05-11 11:53:28 +00:00
```js
var express = require('express');
var errorHandler = require('strong-error-handler');
var app = express();
// setup your routes
2016-08-16 19:59:59 +00:00
// `options` are set to default values. For more info, see `options` below.
// app.use(errorHandler({ /* options, see below */ }));
2016-10-17 13:57:16 +00:00
app.use(errorHandler({
debug: app.get('env') === 'development',
log: true,
}));
2016-05-11 11:53:28 +00:00
app.listen(3000);
```
2018-08-08 17:28:45 +00:00
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);
```
2017-01-09 20:09:47 +00:00
In LoopBack applications, add the following entry to `server/middleware.json` :
2016-05-11 11:53:28 +00:00
```json
{
"final:after": {
"strong-error-handler": {
"params": {
2016-10-17 13:57:16 +00:00
"debug": false,
2017-01-09 20:09:47 +00:00
"log": true
2016-05-11 11:53:28 +00:00
}
}
}
}
```
2017-01-09 20:09:47 +00:00
In general, `strong-error-handler` must be the last middleware function registered.
2016-05-27 15:04:20 +00:00
2017-01-09 20:09:47 +00:00
The above configuration will log errors to the server console, but not return stack traces in HTTP responses.
For details on configuration options, see below.
2016-05-27 15:04:20 +00:00
2017-01-09 20:09:47 +00:00
### Response format and content type
2016-05-27 15:04:20 +00:00
2017-02-01 15:47:23 +00:00
The `strong-error-handler` package supports JSON, HTML and XML responses:
2016-05-11 11:53:28 +00:00
2017-01-09 20:09:47 +00:00
- When the object is a standard Error object, it returns the string provided by the stack property in HTML/text
responses.
- When the object is a non-Error object, it returns the result of `util.inspect` in HTML/text responses.
- For JSON responses, the result is an object with all enumerable properties from the object in the response.
2016-05-11 11:53:28 +00:00
2017-01-09 20:09:47 +00:00
The content type of the response depends on the request's `Accepts` header.
2016-05-11 11:53:28 +00:00
2017-01-09 20:09:47 +00:00
- For Accepts header `json` or `application/json` , the response content type is JSON.
- For Accepts header `html` or `text/html` , the response content type is HTML.
2017-02-01 15:47:23 +00:00
- For Accepts header `xml` or `text/xml` , the response content type is XML.
2016-08-16 19:59:59 +00:00
2017-02-01 15:47:23 +00:00
*There are plans to support other formats such as Plain-text.*
2016-05-11 11:53:28 +00:00
2017-01-09 20:09:47 +00:00
## Options
2016-05-11 11:53:28 +00:00
2020-05-20 21:33:11 +00:00
| Option | Type | Default | Description |
| -------------------- | ------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| debug | Boolean | `false` | If `true` , HTTP responses include all error properties, including sensitive data such as file paths, URLs and stack traces. See [Example output ](#example ) below. |
| log | Boolean | `true` | If `true` , all errors are printed via `console.error` , including an array of fields (custom error properties) that are safe to include in response messages (both 4xx and 5xx). < br /> If `false` , sends only the error back in the response. |
| safeFields | [String] | `[]` | Specifies property names on errors that are allowed to be passed through in 4xx and 5xx responses. See [Safe error fields ](#safe-error-fields ) below. |
| defaultType | String | `"json"` | Specifies the default response content type to use when the client does not provide any Accepts header. |
| rootProperty | String or false | `"error"` | Specifies the root property name for json or xml. If the value is set to `false` , no wrapper will be added to the json object. The false value is ignored by XML as a root element is always required. |
| negotiateContentType | Boolean | true | Negotiate the response content type via Accepts request header. When disabled, strong-error-handler will always use the default content type when producing responses. Disabling content type negotiation is useful if you want to see JSON-formatted error responses in browsers, because browsers usually prefer HTML and XML over other content types. |
2016-05-11 11:53:28 +00:00
2017-01-09 20:09:47 +00:00
### Customizing log format
2016-08-16 19:59:59 +00:00
2020-05-20 21:33:11 +00:00
**Express**
2016-05-11 11:53:28 +00:00
2020-05-20 21:33:11 +00:00
To use a different log format, add your own custom error-handling middleware then disable `errorHandler.log` .
2017-01-09 20:09:47 +00:00
For example, in an Express application:
2016-05-11 11:53:28 +00:00
```js
app.use(myErrorLogger());
2020-05-20 21:33:11 +00:00
app.use(errorHandler({log: false}));
2016-05-11 11:53:28 +00:00
```
2016-08-16 19:59:59 +00:00
2017-01-09 20:09:47 +00:00
In general, add `strong-error-handler` as the last middleware function, just before calling `app.listen()` .
2016-08-16 19:59:59 +00:00
2017-01-09 20:09:47 +00:00
**LoopBack**
2016-08-16 19:59:59 +00:00
2017-01-09 20:09:47 +00:00
For LoopBack applications, put custom error-logging middleware in a separate file; for example, `server/middleware/error-logger.js` :
2016-08-16 19:59:59 +00:00
2017-01-09 20:09:47 +00:00
```
module.exports = function(options) {
return function logError(err, req, res, next) {
console.log('unhandled error' ,err);
next(err);
};
};
```
Then in `server/middleware.json` , specify your custom error logging function as follows:
```
{
// ...
2016-08-16 19:59:59 +00:00
"final:after": {
2017-01-09 20:09:47 +00:00
"./middleware/error-logger": {},
"strong-error-handler": {
"params": {
2017-08-02 08:51:49 +00:00
"log": false
2017-01-09 20:09:47 +00:00
}
}
}
```
The default `middleware.development.json` file explicitly enables logging in strong-error-handler params, so you will need to change that file too.
2017-01-30 22:15:25 +00:00
### Safe error fields
By default, `strong-error-handler` will only pass through the `name` , `message` and `details` properties of an error. Additional error
properties may be allowed through on 4xx and 5xx status code errors using the `safeFields` option to pass in an array of safe field names:
```
{
"final:after": {
"strong-error-handler": {
"params": {
"safeFields": ["errorCode"]
}
}
}
```
Using the above configuration, an error containing an `errorCode` property will produce the following response:
```
{
"error": {
"statusCode": 500,
"message": "Internal Server Error",
"errorCode": "INTERNAL_SERVER_ERROR"
}
}
```
2017-01-09 20:09:47 +00:00
## Migration from old LoopBack error handler
2016-08-18 15:47:21 +00:00
2017-01-09 20:09:47 +00:00
NOTE: This is only required for applications scaffolded with old versions of the `slc loopback` tool.
To migrate a LoopBack 2.x application to use `strong-error-handler` :
1. In `package.json` dependencies, remove `"errorhandler": "^x.x.x”,`
1. Install the new error handler by entering the command:
< pre > npm install --save strong-error-handler< / pre >
1. In `server/config.json` , remove:
< pre >
"remoting": {
...
"errorHandler": {
"disableStackTrace": false
}< / pre >
2017-03-22 08:49:22 +00:00
and replace it with:
< pre >
"remoting": {
...,
"rest": {
"handleErrors": false
}< / pre >
2017-01-09 20:09:47 +00:00
1. In `server/middleware.json` , remove:
< pre >
"final:after": {
"loopback#errorHandler": {}
}< / pre >
2017-03-22 08:49:22 +00:00
and replace it with:
2017-01-09 20:09:47 +00:00
< pre >
"final:after": {
"strong-error-handler": {}
}< / pre >
1. Delete `server/middleware.production.json` .
1. Create `server/middleware.development.json` containing:
2017-03-22 08:49:22 +00:00
< pre >
"final:after": {
"strong-error-handler": {
"params": {
"debug": true,
"log": true
}
2016-08-16 19:59:59 +00:00
}
}
2017-01-09 20:09:47 +00:00
< / pre >
2020-05-20 21:33:11 +00:00
For more information, see
2017-01-09 20:09:47 +00:00
[Migrating apps to LoopBack 3.0 ](http://loopback.io/doc/en/lb3/Migrating-to-3.0.html#update-use-of-rest-error-handler ).
2016-08-16 19:59:59 +00:00
2017-01-09 20:09:47 +00:00
## Example
2016-08-16 19:59:59 +00:00
2017-01-30 10:44:35 +00:00
5xx error generated when `debug: false` :
2016-08-16 19:59:59 +00:00
```
{ error: { statusCode: 500, message: 'Internal Server Error' } }
```
2017-01-30 10:44:35 +00:00
The same error generated when `debug: true` :
2016-08-16 19:59:59 +00:00
```
{ error:
{ statusCode: 500,
name: 'Error',
message: 'a test error message',
2020-05-20 21:33:11 +00:00
stack: 'Error: a test error message
at Context.< anonymous > (User/strong-error-handler/test/handler.test.js:220:21)
at callFnAsync (User/strong-error-handler/node_modules/mocha/lib/runnable.js:349:8)
at Test.Runnable.run (User/strong-error-handler/node_modules/mocha/lib/runnable.js:301:7)
at Runner.runTest (User/strong-error-handler/node_modules/mocha/lib/runner.js:422:10)
at User/strong-error-handler/node_modules/mocha/lib/runner.js:528:12
at next (User/strong-error-handler/node_modules/mocha/lib/runner.js:342:14)
at User/strong-error-handler/node_modules/mocha/lib/runner.js:352:7
at next (User/strong-error-handler/node_modules/mocha/lib/runner.js:284:14)
at Immediate._onImmediate (User/strong-error-handler/node_modules/mocha/lib/runner.js:320:5)
at tryOnImmediate (timers.js:543:15)
2017-01-09 20:09:47 +00:00
at processImmediate [as _immediateCallback] (timers.js:523:5)' }}
2016-08-16 19:59:59 +00:00
```
2017-01-30 10:44:35 +00:00
4xx error generated when `debug: false` :
```
{ error:
{ statusCode: 422,
name: 'Unprocessable Entity',
message: 'Missing required fields',
code: 'MISSING_REQUIRED_FIELDS' }}
```