'How to default to returning errors as JSON instead of HTML with express?

Express by default returns errors as HTML pages. As I'm developing a REST api, I want all my errors to be in JSON format. How can i configure express for this?

I expect the response to look something like this

{
  "statusCode": 404,
  "error": "Not Found"
}

but instead I get

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Error</title>
</head>
<body>
    <pre>Cannot DELETE /object/</pre>
</body>
</html>

This is my basic app

export const app = express();
app.use(express.json());

app.get("/objects", listObjects);
app.get("/object/:id", getObject);
app.post("/object", createObject);
app.put("/object/:id", updateObject);
app.delete("/object/:id", deleteObject);

UPDATE: To clarify, it is not the errors from my handlers I want to handle as json. Doing that is pretty straight forward.

What I'm after is for express to stop returning html errors for unregistered handlers, like doing DELETE on /assessments, or GET on /anUnknownRoute



Solution 1:[1]

You add custom error handling middleware - which is regular middleware but with 4 arguments instead of 3 - to the middleware stack. In this error handler you use res.status(code).send(jsonResponse) to send the json error.

A simple quick example that will always send status 500 JSON errors:

const bodyParser = require('body-parser')
const express = require('express')

const jsonErrorHandler = (err, req, res, next) => {
  res.status(500).send({ error: err });
}

const app = express()
// The other middleware
app.use(bodyParser.json())
// Your handler
app.use(jsonErrorHandler)

Solution 2:[2]

You may simply add 'Content-Type: application/json' to your response headers and write basically anything you want in JSON format, e.g.

function(err, req, res, next){
    res.setHeader('Content-Type', 'application/json');
    res.status(500);
    res.send(JSON.stringify(error));
});

Or you can use res.json instead. Please, see official doc for more detailed information: https://expressjs.com/en/api.html#res.json

If you want to return errors in JSON by default, then you may be interested in using default express error-handling mechanism: https://expressjs.com/en/guide/error-handling.html

Just pass an error to the next callback to go straight to the error-handler (skipping everything else in the queue in between) and add an error-handling middleware to the end of your middleware queue. This should do the trick.

P.S. From express.js FAQ:

In Express, 404 responses are not the result of an error, so the error-handler middleware will not capture them. This behavior is because a 404 response simply indicates the absence of additional work to do; in other words, Express has executed all middleware functions and routes, and found that none of them responded. All you need to do is add a middleware function at the very bottom of the stack (below all other functions) to handle a 404 response:

app.use(function (req, res, next) {
    res.status(404).send("Sorry can't find that!")
})

Obviously, you may send a response in JSON format...

Solution 3:[3]

all you have to do for getting JSON response for errors is to add another argument in the route handler that will be a middle-ware function responsible for errors.

Ex: you have to modify this

app.get('/objects', listObjects); 

to be like that:

app.get('/objects', listObjects, (err, req, res, next) => {
    res.status(404).send({error: err.message})
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Abanoub Fathy