strongloop/loopback — pull request #77 by bajtos (2013-11-22 19:10:58+00:00)
Title: Unify format of REST error responses

Modify loopback.errorHandler() to call the error handler provided by
strong-remoting's RestAdapter when the client accepts json, and fall
back to connect/express handler otherwise.

This way when a LoopBack client requests a URL not mapped to any shared
method, the server returns response in the same format as is produced
in other cases.

Requires strongloop/strong-remoting#23.

/to: @raymondfeng or @ritch Please review.
/cc: @Schoonology FYI.

---

This change deserves some discussion before we go ahead and merge.

What problem I am trying to solve:

```js
var app = loopback();
app.use(loopback.rest());
app.get('/foo/bar', function() { /* ... */ });
app.use(loopback.urlNotFound());
app.use(loopback.errorHandler());

// 1. Request to an unknown URL falls through loopback.rest()
// and is handled by loopback.errorHandler()

// 2. LoopBack client accessing '/foo/bar' and expecting a remote method there
// will get error formatted by loopback.errorHandler()
// (assuming the request fails)
```

What is still not solved:

```js
var app = loopback();
app.use(loopback.rest());
// possibly missing urlNotFound handler
app.use(myCustomErrorHandlerNotAwareOfJson());

// LoopBack client requesting an unknown url
// (object/method not implemented) gets error response
// in an unexpected format (whatever the custom handler produced,
// or the default text response when urlNotFound was not installed).
```

---

Here is a radically different approach that will make this pull request unnecessary:
- Make every adapter own the whole URL subspace, do not allow developers to mix REST API routes with website routes in the same space.
- REST adapter can install `urlNotFound` and `restErrorHandler` middleware to ensure errors are handled consistently.
- Developers can still start the REST handler as a standalone application. If they want to use it as a part of a bigger app, they have to mount it at a sub-path.
- Error handler used by the root application does not affect error handling of requests for the REST endpoint

```js
// 1. The application is all about REST
var app = loopback();
app.use(loopback.rest());
// Any middleware registered below this point won't be called. Ever.

// 2. The application combines REST and website
app.use('/api', loopback.rest());
// register app middleware, e.g.
// app.use(express.router);
// Even if you don't install urlNotFound and errorHandler,
// all unknown requests starting with /api/ return expected
// json response.
```

This should also prevent hard-to-debug bugs caused by incorrect ordering of middleware registration, i.e. when the URL is handled by both loopback and some other middleware.

Thoughts?