Send a response using Express
By Flavio Copes
Learn how to send a response in Express using send() for strings or JSON, end() for an empty body, and status() or sendStatus() to set the HTTP status.
In Express you send a response to the client using the methods of the res object. send() handles strings, objects and buffers, json() sends JSON, end() closes the response with an empty body, and status() or sendStatus() set the HTTP status code. Let’s see each one.
Sending a body with send()
In the Hello World example we used the Response.send() method to send a simple string as a response, and to close the connection:
(req, res) => res.send('Hello World!')
If you pass in a string, it sets the Content-Type header to text/html.
if you pass in an object or an array, it sets the application/json Content-Type header, and parses that parameter into JSON.
If you pass in a Buffer, it sets the Content-Type to application/octet-stream, unless you set a different one yourself.
send() automatically sets the Content-Length HTTP response header.
send() also automatically closes the connection. You don’t call end() after it, and you don’t call it twice.
Sending JSON with json()
When your endpoint returns data, you can be explicit and use Response.json():
app.get('/api/products', (req, res) => {
res.json([{ id: 1, name: 'Keyboard' }])
})
Passing the same array to send() gives the same result, because send() calls json() internally when it receives an object or an array. I like json() in API code because it states the intent.
Use end() to send an empty response
An alternative way to send the response, without any body, it’s by using the Response.end() method:
res.end()
This is useful when the status code says everything, like a 204 No Content response.
Set the HTTP response status
Use the Response.status() method. It sets the code and returns the response object, so you can chain another call after it:
res.status(404).end()
or
res.status(404).send('File not found')
sendStatus() is a shortcut that sets the code and sends its standard message as the body:
res.sendStatus(200)
// === res.status(200).send('OK')
res.sendStatus(403)
// === res.status(403).send('Forbidden')
res.sendStatus(404)
// === res.status(404).send('Not Found')
res.sendStatus(500)
// === res.status(500).send('Internal Server Error')
Be careful with sending twice
Each request gets exactly one response. If your code calls send() after the response already went out, Node throws:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
This usually happens when you forget to return after sending an early response:
app.get('/api/orders/:id', (req, res) => {
const order = orders.find((item) => item.id === req.params.id)
if (!order) {
return res.status(404).send('Order not found')
}
res.json(order)
})
Without that return, a missing order would trigger both the 404 and the json() call below it, and the second one crashes with the error above.