Skip to content

Commit

Permalink
Added ability to use custom render functions to send JSON, HTML, and …
Browse files Browse the repository at this point in the history
…XML responses.
  • Loading branch information
charlie-s committed Feb 28, 2017
1 parent afeedcc commit c2335b3
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 19 deletions.
59 changes: 45 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,15 @@ The content type of the response depends on the request's `Accepts` header.
| 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. |
| jsonRenderer | String | 'send-json' | Operation function to render JSON with signature `fn(res, data)`. Defaults to `./send-json` (`lib/send-json.js`). |
| htmlRenderer | String | 'send-html' | Operation function to render HTML with signature `fn(res, data)`. Defaults to `./send-html` (`lib/send-html.js`). |
| xmlRenderer | String | 'send-xml' | Operation function to render XML with signature `fn(res, data)`. Defaults to `./send-xml` (`lib/send-xml.js`). |

### Customizing log format

**Express**
**Express**

To use a different log format, add your own custom error-handling middleware then disable `errorHandler.log`.
To use a different log format, add your own custom error-handling middleware then disable `errorHandler.log`.
For example, in an Express application:

```js
Expand Down Expand Up @@ -155,6 +158,34 @@ Using the above configuration, an error containing an `errorCode` property will
}
```

### Custom Renderer Functions

You can switch out the default renderers for HTML, JSON, and XML responses with custom renderers:

```
{
// ...
"final:after": {
"strong-error-handler": {
"params": {
"htmlRenderer": "$!./lib/send-html"
}
}
}
```

The `$!` characters indicate that the path is relative to the location of `middleware.json`.

*./lib/send-html.js:*

```
module.exports = function(res, data) {
res.send("Hello.");
}
```

Using the above configuration, a request with `Content-type: text/html` that is handled by strong-error-handler will return a `Content-type: text/html` and a response body of `Hello.`.

## Migration from old LoopBack error handler

NOTE: This is only required for applications scaffolded with old versions of the `slc loopback` tool.
Expand Down Expand Up @@ -201,7 +232,7 @@ To migrate a LoopBack 2.x application to use `strong-error-handler`:
}
</pre>

For more information, see
For more information, see
[Migrating apps to LoopBack 3.0](http://loopback.io/doc/en/lb3/Migrating-to-3.0.html#update-use-of-rest-error-handler).

## Example
Expand All @@ -219,17 +250,17 @@ The same error generated when `debug: true` :
{ statusCode: 500,
name: 'Error',
message: 'a test error message',
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)
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)
at processImmediate [as _immediateCallback] (timers.js:523:5)' }}
```

Expand Down
30 changes: 25 additions & 5 deletions lib/content-negotiation.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
'use strict';
var accepts = require('accepts');
var debug = require('debug')('strong-error-handler:http-response');
var sendJson = require('./send-json');
var sendHtml = require('./send-html');
var sendXml = require('./send-xml');
var util = require('util');

var sendJson;
var sendHtml;
var sendXml;

module.exports = negotiateContentProducer;

/**
Expand All @@ -20,9 +21,9 @@ module.exports = negotiateContentProducer;
* @param req request object
* @param {Object} options options of strong-error-handler
* @param {Function} logWarning a logger function for reporting warnings
* @returns {Function} Opeartion function with signature `fn(res, data)`
* @returns {Function} Operation function with signature `fn(res, data)`
*/
function negotiateContentProducer(req, logWarning, options) {
function negotiateContentProducer(req, options, logWarning) {
var SUPPORTED_TYPES = [
'application/json', 'json',
'text/html', 'html',
Expand All @@ -43,6 +44,25 @@ function negotiateContentProducer(req, logWarning, options) {
}
}

// resolve renderer functions
if (!('jsonRenderer' in options)) {
options.jsonRenderer = './send-json';
}

sendJson = require(options.jsonRenderer);

if (!('htmlRenderer' in options)) {
options.htmlRenderer = './send-html';
}

sendHtml = require(options.htmlRenderer);

if (!('xmlRenderer' in options)) {
options.xmlRenderer = './send-xml';
}

sendXml = require(options.xmlRenderer);

// decide to use resolvedType or defaultType
// Please note that accepts assumes the order of content-type is provided
// in the priority returned
Expand Down

0 comments on commit c2335b3

Please sign in to comment.