diff --git a/3.0-RELEASE-NOTES.md b/3.0-RELEASE-NOTES.md
index f3fad7ad..ea854b18 100644
--- a/3.0-RELEASE-NOTES.md
+++ b/3.0-RELEASE-NOTES.md
@@ -127,3 +127,29 @@ removed properties together with the middleware module name to use instead:
We have also removed `loopback.mime`, which was always set to `undefined`.
See [loopback#2349](https://github.com/strongloop/loopback/pull/2394).
+
+## Remove `loopback#errorhandler`
+
+We have removed `loopback#errorhandler` middleware, users should use `strong-error-handler` directly.
+
+```js
+// server/middleware.json
+{
+ // ...
+ "final:after": {
+ "strong-error-handler": {}
+ }
+}
+
+// server/middleware.development.json
+{
+ "final:after": {
+ "strong-error-handler": {
+ "params": {
+ "debug": true
+ }
+ }
+}
+```
+
+See also strong-error-handler's [options](https://github.com/strongloop/strong-error-handler#options) and the [related code change](https://github.com/strongloop/loopback/pull/2411).
diff --git a/package.json b/package.json
index 51b074bc..bd97d8c8 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,6 @@
"debug": "^2.1.2",
"depd": "^1.0.0",
"ejs": "^2.3.1",
- "errorhandler": "^1.3.4",
"express": "^4.12.2",
"inflection": "^1.6.0",
"loopback-connector-remote": "^1.0.3",
@@ -59,6 +58,7 @@
"underscore.string": "^3.0.3"
},
"devDependencies": {
+ "strong-error-handler": "^1.0.1",
"browserify": "^10.0.0",
"chai": "^2.1.1",
"cookie-parser": "^1.3.4",
diff --git a/server/middleware/error-handler.js b/server/middleware/error-handler.js
index 7ca8d761..237355fc 100644
--- a/server/middleware/error-handler.js
+++ b/server/middleware/error-handler.js
@@ -3,19 +3,7 @@
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
-var expressErrorHandler = require('errorhandler');
-expressErrorHandler.title = 'Loopback';
-
-module.exports = errorHandler;
-
-function errorHandler(options) {
- if (!options || options.includeStack !== false) {
- return expressErrorHandler(options);
- } else {
- var baseHandler = expressErrorHandler(options);
- return function errorHandler(err, req, res, next) {
- delete err.stack;
- return baseHandler(err, req, res, next);
- };
- }
-}
+module.exports = function(options) {
+ throw new Error('loopback.errorHandler is no longer available.' +
+ ' Please use the module "strong-error-handler" instead.');
+};
diff --git a/test/error-handler.test.js b/test/error-handler.test.js
index e1d9a790..00419d27 100644
--- a/test/error-handler.test.js
+++ b/test/error-handler.test.js
@@ -7,61 +7,19 @@ var loopback = require('../');
var app;
var assert = require('assert');
var request = require('supertest');
+var expect = require('chai').expect;
describe('loopback.errorHandler(options)', function() {
- it('should return default middleware when options object is not present', function(done) {
- //arrange
- var app = loopback();
- app.use(loopback.urlNotFound());
- app.use(loopback.errorHandler({ log: false }));
-
- //act/assert
- request(app)
- .get('/url-does-not-exist')
- .end(function(err, res) {
- assert.ok(res.error.text.match(/
- at raiseUrlNotFoundError/));
-
- done();
- });
- });
-
- it('should delete stack when options.includeStack is false', function(done) {
- //arrange
- var app = loopback();
- app.use(loopback.urlNotFound());
- app.use(loopback.errorHandler({ includeStack: false, log: false }));
-
- //act/assert
- request(app)
- .get('/url-does-not-exist')
- .end(function(err, res) {
- assert.ok(res.error.text.match(/
<\/ul>/));
-
- done();
- });
- });
-
- it('should pass options on to error handler module', function(done) {
- //arrange
- var app = loopback();
- app.use(loopback.urlNotFound());
-
- var errorLogged;
- app.use(loopback.errorHandler({
- includeStack: false,
- log: function customLogger(err, str, req) {
- errorLogged = err;
- },
- }));
-
- //act
- request(app).get('/url-does-not-exist').end(function(err) {
- if (err) return done(err);
- //assert
- expect(errorLogged)
- .to.have.property('message', 'Cannot GET /url-does-not-exist');
-
+ it('should throw a descriptive error', function(done) {
+ try {
+ //arrange
+ var app = loopback();
+ app.use(loopback.urlNotFound());
+ app.use(loopback.errorHandler({ log: false }));
+ } catch (e) {
+ expect(function() { loopback.errorHandler(); })
+ .to.throw(/no longer available.*strong-error-handler/);
done();
- });
+ }
});
});
diff --git a/test/fixtures/access-control/server/server.js b/test/fixtures/access-control/server/server.js
index be73ed5b..2518378d 100644
--- a/test/fixtures/access-control/server/server.js
+++ b/test/fixtures/access-control/server/server.js
@@ -6,7 +6,7 @@
var loopback = require('../../../..');
var boot = require('loopback-boot');
var app = module.exports = loopback();
-
+var errorHandler = require('strong-error-handler');
boot(app, __dirname);
var apiPath = '/api';
@@ -14,5 +14,5 @@ app.use(loopback.token({ model: app.models.accessToken }));
app.use(apiPath, loopback.rest());
app.use(loopback.urlNotFound());
-app.use(loopback.errorHandler());
+app.use(errorHandler());
app.enableAuth();
diff --git a/test/fixtures/simple-integration-app/server/server.js b/test/fixtures/simple-integration-app/server/server.js
index e6e379c0..f9cc267a 100644
--- a/test/fixtures/simple-integration-app/server/server.js
+++ b/test/fixtures/simple-integration-app/server/server.js
@@ -6,9 +6,10 @@
var loopback = require('../../../../index');
var boot = require('loopback-boot');
var app = module.exports = loopback();
+var errorHandler = require('strong-error-handler');
boot(app, __dirname);
var apiPath = '/api';
app.use(apiPath, loopback.rest());
app.use(loopback.urlNotFound());
-app.use(loopback.errorHandler());
+app.use(errorHandler());
diff --git a/test/fixtures/user-integration-app/server/server.js b/test/fixtures/user-integration-app/server/server.js
index a28bbaf6..584640ac 100644
--- a/test/fixtures/user-integration-app/server/server.js
+++ b/test/fixtures/user-integration-app/server/server.js
@@ -6,10 +6,11 @@
var loopback = require('../../../../index');
var boot = require('loopback-boot');
var app = module.exports = loopback();
+var errorHandler = require('strong-error-handler');
app.enableAuth();
boot(app, __dirname);
app.use(loopback.token({ model: app.models.AccessToken }));
var apiPath = '/api';
app.use(apiPath, loopback.rest());
app.use(loopback.urlNotFound());
-app.use(loopback.errorHandler());
+app.use(errorHandler());