Express Resource adds RESTful resource routing on top of the Express framework for Node.js. It includes a nice feature called “Auto-Loading” that allows you to define a single load
method that will automatically be used to load your resource object from a URL id parameter and set it in the request object to be accessed by your conventional RESTful methods that need it. Another great feature of Express Resource is what they call “Content-Negotiation”. URLs with format extensions like .xml
or .json
automatically set an indicator of the format in the request so your actions can respond accordingly.
However, a problem arises when you use the recommended method for handling and reporting errors from within your load
method: You get no control over how the errors are handled, and the default mechanism is ignorant of the requested format. This makes it tough to return nice JSON errors, for example, from a REST API that uses this technique.
The Problem
The canonical example in the Express Resource documentation describes implementing a load
method on your resource that calls a callback with an error and/or the loaded object, like so:
1 2 3 4 5 |
|
This is great, except there are a few problems:
You can’t override what Express Resource does with this error. The way Express Resource works here is to use a param callback. If you pass an error, its param callback simply passes the error to the next method in the chain via
next(err)
, which ends up invoking the default error handling before any of your methods orapp.error()
handlers are called. This means that a RESTful API call expecting a JSON response won’t get a JSON response. If you want your JSON API 404s to return JSON data in the payload, you are out of luck.There is no response object passed to your auto-load function. This makes it difficult to bypass Express Resource’s intended error handling and issue a response directly on your own.
The content-negotiation hasn’t happened yet at this point in the chain. This means, even if you could respond directly from your
load
function, you wouldn’t be able to use the conventional Express Resource mechanism of testingreq.format
to know whether or not to response with JSON, HTML, XML, whatever.
The Solution
It turns out there are some simple solutions to these problems. Let’s tackle them in reverse order.
Even though Express Resource has not parsed the route’s format yet, and set
req.format
for you, the core routing framework has already done this as params matching. Instead ofreq.format
, for this method you need to usereq.params.format
.Even though Express Resource does not pass the
res
object into yourload
function, node.js has conveniently linked the two together for us. In this method, instead of usingres
, you need to usereq.res
. This may be a little dangerous since it relies on the internal structure of the request object, but this linkage seems relatively stable.Don’t have your
load
function call the given callback if there is an error. Only call it in the success case. If there is an error, render the response yourself using the tactics described above for #1 and #2.
Putting it all together
Here is an example of what all that might look like for your load
function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|