strong-error-handler 1.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,36 +1,37 @@
1
1
  <!--
2
- - Please ask questions at https://groups.google.com/forum/#!forum/loopbackjs or
2
+ Questions:
3
+ https://groups.google.com/forum/#!forum/loopbackjs
3
4
  https://gitter.im/strongloop/loopback
4
-
5
- - Immediate support is available through our subscription plans, see
5
+ Immediate support:
6
6
  https://strongloop.com/api-connect-faqs/
7
+ https://strongloop.com/node-js/subscription-plans/
7
8
  -->
8
9
 
9
- ### Bug or feature request
10
+ # Description/Steps to reproduce
10
11
 
11
12
  <!--
12
- Mark your choice with an "x" (eg. [x], NOT [*]).
13
+ If feature: A description of the feature
14
+ If bug: Steps to reproduce
13
15
  -->
14
16
 
15
- - [ ] Bug
16
- - [ ] Feature request
17
-
18
- ### Description of feature (or steps to reproduce if bug)
19
-
20
-
21
-
22
- ### Link to sample repo to reproduce issue (if bug)
23
-
24
-
25
-
26
- ### Expected result
17
+ # Link to reproduction sandbox
27
18
 
19
+ <!--
20
+ Link to an app sandbox for reproduction
28
21
 
22
+ Note: Failure to provide a sandbox application for reproduction purposes will result in the issue being closed.
23
+ -->
29
24
 
30
- ### Actual result (if bug)
31
-
32
-
25
+ # Expected result
33
26
 
34
- ### Additional information (Node.js version, LoopBack version, etc)
27
+ <!--
28
+ Also include actual results if bug
29
+ -->
35
30
 
31
+ # Additional information
36
32
 
33
+ <!--
34
+ Copy+paste the output of these two commands:
35
+ node -e 'console.log(process.platform, process.arch, process.versions.node)'
36
+ npm ls --prod --depth 0 | grep loopback
37
+ -->
@@ -6,17 +6,18 @@
6
6
  <!--
7
7
  Please use the following link syntaxes:
8
8
 
9
- - #49 (to reference issues in the current repository)
10
- - strongloop/loopback#49 (to reference issues in another repository)
9
+ - connect to #49 (to reference issues in the current repository)
10
+ - connect to strongloop/loopback#49 (to reference issues in another repository)
11
11
  -->
12
12
 
13
- - None
13
+ - connect to <link_to_referenced_issue>
14
14
 
15
15
  ### Checklist
16
16
 
17
17
  <!--
18
- Please mark your choice with an "x" (i.e. [x], see
18
+ - Please mark your choice with an "x" (i.e. [x], see
19
19
  https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments)
20
+ - PR's without test coverage will be closed.
20
21
  -->
21
22
 
22
23
  - [ ] New tests added or existing tests modified to cover all changes
package/CHANGES.md CHANGED
@@ -1,3 +1,47 @@
1
+ 2017-10-13, Version 2.3.0
2
+ =========================
3
+
4
+ * update strong-globalize to 3.1.0 (shimks)
5
+
6
+ * CODEOWNERS: add zbarbuto (Miroslav Bajtoš)
7
+
8
+ * Update Issue and PR Templates (#59) (Sakib Hasan)
9
+
10
+ * fixed json typo of server/middleware.json (karanssj4)
11
+
12
+ * Add CODEOWNER file (Diana Lau)
13
+
14
+
15
+ 2017-07-20, Version 2.2.0
16
+ =========================
17
+
18
+ * Add new option: negotiateContentType (Raj)
19
+
20
+
21
+ 2017-04-18, Version 2.1.0
22
+ =========================
23
+
24
+ * Bump js2xmlparser dependency to version 3.0.0 (Matthew O'Donoghue)
25
+
26
+
27
+ 2017-03-22, Version 2.0.0
28
+ =========================
29
+
30
+ * Fix markdown formatting in README (Miroslav Bajtoš)
31
+
32
+ * Fix the order of arguments in the jsdoc comment. (Charlie Schliesser)
33
+
34
+ * Update readme with added XML support (David Cheung)
35
+
36
+ * Add a machine-readable "code" property (Zak Barbuto)
37
+
38
+ * Upgrade dependencies to their latest versions (Miroslav Bajtoš)
39
+
40
+ * Describe "safeFields" option in README (Zak Barbuto)
41
+
42
+ * Drop support for Node v0.10/v0.12 (Miroslav Bajtoš)
43
+
44
+
1
45
  2017-01-30, Version 1.2.1
2
46
  =========================
3
47
 
package/CODEOWNERS ADDED
@@ -0,0 +1,5 @@
1
+ # Lines starting with '#' are comments.
2
+ # Each line is a file pattern followed by one or more owners,
3
+ # the last matching pattern has the most precendence.
4
+
5
+ * @bajtos @zbarbuto
package/README.md CHANGED
@@ -7,7 +7,8 @@ In production mode, `strong-error-handler` omits details from error responses to
7
7
  - For 5xx errors, the output contains only the status code and the status name from the HTTP specification.
8
8
  - For 4xx errors, the output contains the full error message (`error.message`) and the contents of the `details`
9
9
  property (`error.details`) that `ValidationError` typically uses to provide machine-readable details
10
- about validation problems.
10
+ about validation problems. It also includes `error.code` to allow a machine-readable error code to be passed
11
+ through which could be used, for example, for translation.
11
12
 
12
13
  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.
13
14
 
@@ -59,7 +60,7 @@ For details on configuration options, see below.
59
60
 
60
61
  ### Response format and content type
61
62
 
62
- The `strong-error-handler` package supports HTML and JSON responses:
63
+ The `strong-error-handler` package supports JSON, HTML and XML responses:
63
64
 
64
65
  - When the object is a standard Error object, it returns the string provided by the stack property in HTML/text
65
66
  responses.
@@ -70,8 +71,9 @@ The content type of the response depends on the request's `Accepts` header.
70
71
 
71
72
  - For Accepts header `json` or `application/json`, the response content type is JSON.
72
73
  - For Accepts header `html` or `text/html`, the response content type is HTML.
74
+ - For Accepts header `xml` or `text/xml`, the response content type is XML.
73
75
 
74
- *There are plans to support other formats such as Text and XML.*
76
+ *There are plans to support other formats such as Plain-text.*
75
77
 
76
78
  ## Options
77
79
 
@@ -79,6 +81,9 @@ The content type of the response depends on the request's `Accepts` header.
79
81
  | ---- | ---- | ---- | ---- |
80
82
  | debug | Boolean&nbsp;&nbsp;&nbsp; | `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. |
81
83
  | 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. |
84
+ | 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. |
85
+ | defaultType | String | `"json"` | Specify the default response content type to use when the client does not provide any Accepts header.
86
+ | 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.
82
87
 
83
88
  ### Customizing log format
84
89
 
@@ -116,7 +121,7 @@ Then in `server/middleware.json`, specify your custom error logging function as
116
121
  "./middleware/error-logger": {},
117
122
  "strong-error-handler": {
118
123
  "params": {
119
- log: false
124
+ "log": false
120
125
  }
121
126
  }
122
127
  }
@@ -124,6 +129,34 @@ Then in `server/middleware.json`, specify your custom error logging function as
124
129
 
125
130
  The default `middleware.development.json` file explicitly enables logging in strong-error-handler params, so you will need to change that file too.
126
131
 
132
+ ### Safe error fields
133
+
134
+ By default, `strong-error-handler` will only pass through the `name`, `message` and `details` properties of an error. Additional error
135
+ 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:
136
+
137
+ ```
138
+ {
139
+ "final:after": {
140
+ "strong-error-handler": {
141
+ "params": {
142
+ "safeFields": ["errorCode"]
143
+ }
144
+ }
145
+ }
146
+ ```
147
+
148
+ Using the above configuration, an error containing an `errorCode` property will produce the following response:
149
+
150
+ ```
151
+ {
152
+ "error": {
153
+ "statusCode": 500,
154
+ "message": "Internal Server Error",
155
+ "errorCode": "INTERNAL_SERVER_ERROR"
156
+ }
157
+ }
158
+ ```
159
+
127
160
  ## Migration from old LoopBack error handler
128
161
 
129
162
  NOTE: This is only required for applications scaffolded with old versions of the `slc loopback` tool.
@@ -140,34 +173,34 @@ To migrate a LoopBack 2.x application to use `strong-error-handler`:
140
173
  "errorHandler": {
141
174
  "disableStackTrace": false
142
175
  }</pre>
143
- and replace it with:
144
- <pre>
145
- "remoting": {
146
- ...,
147
- "rest": {
148
- "handleErrors": false
149
- }</pre>
176
+ and replace it with:
177
+ <pre>
178
+ "remoting": {
179
+ ...,
180
+ "rest": {
181
+ "handleErrors": false
182
+ }</pre>
150
183
  1. In `server/middleware.json`, remove:
151
184
  <pre>
152
185
  "final:after": {
153
186
  "loopback#errorHandler": {}
154
187
  }</pre>
155
- and replace it with:
188
+ and replace it with:
156
189
  <pre>
157
190
  "final:after": {
158
191
  "strong-error-handler": {}
159
192
  }</pre>
160
193
  1. Delete `server/middleware.production.json`.
161
194
  1. Create `server/middleware.development.json` containing:
162
- <pre>
163
- "final:after": {
164
- "strong-error-handler": {
165
- "params": {
166
- "debug": true,
167
- "log": true
195
+ <pre>
196
+ "final:after": {
197
+ "strong-error-handler": {
198
+ "params": {
199
+ "debug": true,
200
+ "log": true
201
+ }
168
202
  }
169
203
  }
170
- }
171
204
  </pre>
172
205
 
173
206
  For more information, see
@@ -175,13 +208,13 @@ For more information, see
175
208
 
176
209
  ## Example
177
210
 
178
- Error generated when `debug: false` :
211
+ 5xx error generated when `debug: false` :
179
212
 
180
213
  ```
181
214
  { error: { statusCode: 500, message: 'Internal Server Error' } }
182
215
  ```
183
216
 
184
- Error generated when `debug: true` :
217
+ The same error generated when `debug: true` :
185
218
 
186
219
  ```
187
220
  { error:
@@ -201,3 +234,13 @@ Error generated when `debug: true` :
201
234
  at tryOnImmediate (timers.js:543:15)
202
235
  at processImmediate [as _immediateCallback] (timers.js:523:5)' }}
203
236
  ```
237
+
238
+ 4xx error generated when `debug: false` :
239
+
240
+ ```
241
+ { error:
242
+ { statusCode: 422,
243
+ name: 'Unprocessable Entity',
244
+ message: 'Missing required fields',
245
+ code: 'MISSING_REQUIRED_FIELDS' }}
246
+ ```
@@ -18,10 +18,11 @@ module.exports = negotiateContentProducer;
18
18
  * to resolve the correct operation
19
19
  *
20
20
  * @param req request object
21
+ * @param {Function} logWarning a logger function for reporting warnings
21
22
  * @param {Object} options options of strong-error-handler
22
- * @returns {Function} Opeartion function with signature `fn(res, data)`
23
+ * @returns {Function} Operation function with signature `fn(res, data)`
23
24
  */
24
- function negotiateContentProducer(req, options) {
25
+ function negotiateContentProducer(req, logWarning, options) {
25
26
  var SUPPORTED_TYPES = [
26
27
  'application/json', 'json',
27
28
  'text/html', 'html',
@@ -55,6 +56,18 @@ function negotiateContentProducer(req, options) {
55
56
  debug('Resolved content-type', resolvedContentType);
56
57
  var contentType = resolvedContentType || defaultType;
57
58
 
59
+ if (options.negotiateContentType === false) {
60
+ if (SUPPORTED_TYPES.indexOf(options.defaultType) > -1) {
61
+ debug('Forcing options.defaultType `%s`',
62
+ options.defaultType);
63
+ contentType = options.defaultType;
64
+ } else {
65
+ debug('contentType: `%s` is not supported, ' +
66
+ 'falling back to contentType: `%s`',
67
+ options.defaultType, contentType);
68
+ }
69
+ }
70
+
58
71
  // to receive _format from user's url param to overide the content type
59
72
  // req.query (eg /api/Users/1?_format=json will overide content negotiation
60
73
  // https://github.com/strongloop/strong-remoting/blob/ac3093dcfbb787977ca0229b0f672703859e52e1/lib/http-context.js#L643-L645
@@ -66,8 +79,7 @@ function negotiateContentProducer(req, options) {
66
79
  // format passed through query but not supported
67
80
  var msg = util.format('Response _format "%s" is not supported' +
68
81
  'used "%s" instead"', query._format, defaultType);
69
- res.header('X-Warning', msg);
70
- debug(msg);
82
+ logWarning(msg);
71
83
  }
72
84
  }
73
85
 
@@ -77,6 +77,7 @@ function fillDebugData(data, err) {
77
77
  function fillBadRequestError(data, err) {
78
78
  data.name = err.name;
79
79
  data.message = err.message;
80
+ data.code = err.code;
80
81
  data.details = err.details;
81
82
  }
82
83
 
package/lib/handler.js CHANGED
@@ -51,7 +51,12 @@ exports = module.exports = function createStrongErrorHandler(options) {
51
51
  res.setHeader('X-Content-Type-Options', 'nosniff');
52
52
  res.statusCode = data.statusCode;
53
53
 
54
- var sendResponse = negotiateContentProducer(req, options);
54
+ var sendResponse = negotiateContentProducer(req, warn, options);
55
55
  sendResponse(res, data);
56
+
57
+ function warn(msg) {
58
+ res.header('X-Warning', msg);
59
+ debug(msg);
60
+ }
56
61
  };
57
62
  };
package/package.json CHANGED
@@ -2,7 +2,10 @@
2
2
  "name": "strong-error-handler",
3
3
  "description": "Error handler for use in development and production environments.",
4
4
  "license": "MIT",
5
- "version": "1.2.1",
5
+ "version": "2.3.0",
6
+ "engines": {
7
+ "node": ">=4"
8
+ },
6
9
  "repository": {
7
10
  "type": "git",
8
11
  "url": "https://github.com/strongloop/strong-error-handler.git"
@@ -17,17 +20,17 @@
17
20
  "accepts": "^1.3.3",
18
21
  "debug": "^2.2.0",
19
22
  "ejs": "^2.4.2",
20
- "http-status": "^0.2.2",
21
- "js2xmlparser": "^2.0.2",
22
- "strong-globalize": "^2.6.7"
23
+ "http-status": "^1.0.0",
24
+ "js2xmlparser": "^3.0.0",
25
+ "strong-globalize": "^3.1.0"
23
26
  },
24
27
  "devDependencies": {
25
- "chai": "^2.1.1",
26
- "eslint": "^2.13.1",
27
- "eslint-config-loopback": "^4.0.0",
28
+ "chai": "^3.5.0",
29
+ "eslint": "^3.14.1",
30
+ "eslint-config-loopback": "^8.0.0",
28
31
  "express": "^4.13.4",
29
- "mocha": "^2.1.0",
30
- "supertest": "^1.1.0"
32
+ "mocha": "^3.2.0",
33
+ "supertest": "^3.0.0"
31
34
  },
32
35
  "browser": {
33
36
  "strong-error-handler": false
package/.npmignore DELETED
@@ -1,35 +0,0 @@
1
- # Logs
2
- logs
3
- *.log
4
- npm-debug.log*
5
-
6
- # Runtime data
7
- pids
8
- *.pid
9
- *.seed
10
-
11
- # Directory for instrumented libs generated by jscoverage/JSCover
12
- lib-cov
13
-
14
- # Coverage directory used by tools like istanbul
15
- coverage
16
-
17
- # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
18
- .grunt
19
-
20
- # node-waf configuration
21
- .lock-wscript
22
-
23
- # Compiled binary addons (http://nodejs.org/api/addons.html)
24
- build/Release
25
-
26
- # Dependency directory
27
- node_modules
28
-
29
- # Optional npm cache directory
30
- .npm
31
-
32
- # Optional REPL history
33
- .node_repl_history
34
- test
35
- .travis.yml