Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Replies: reply

The second handler argument is the reply object, the server's response. Through it you set the status code (a number such as 200 or 404 that tells the client the result), headers and the body.

Status code

By default Fastify answers with 200. A created resource is usually returned with 201:

// src/routes/posts.js
app.post('/posts', async (request, reply) => {
  const post = { id: posts.length + 1, ...request.body };
  posts.push(post);
  reply.code(201);
  return post;
});

reply.code(201) only changes the code; the body still comes from return. curl with the -i flag shows the first response line HTTP/1.1 201 Created.

reply.send

Instead of return you can send the reply explicitly. reply methods return reply itself, so they are chained:

// src/routes/posts.js
app.get('/posts/:id', async (request, reply) => {
  const post = posts.find((item) => item.id === Number(request.params.id));
  if (!post) {
    return reply.code(404).send({ error: 'Post not found' });
  }
  return post;
});

The address /posts/99 returns code 404 and {"error":"Post not found"}, while /posts/1 returns the post.

An empty reply

After a delete there is nothing to return. Code 204 "No Content" is for exactly that:

// src/routes/posts.js
app.delete('/posts/:id', async (request, reply) => {
  const index = posts.findIndex((post) => post.id === Number(request.params.id));
  if (index !== -1) {
    posts.splice(index, 1);
  }
  return reply.code(204).send();
});

The command curl -i -X DELETE http://localhost:3000/posts/1 shows 204 No Content with no body.

Headers and type

MethodWhat it does
reply.code(404)Status code
reply.header('cache-control', 'no-store')One header
reply.headers({ ... })Several headers as an object
reply.type('text/plain')The Content-Type header
reply.redirect('/posts')A redirect

Fastify sends a string as text/plain, and an object or array as application/json.

Redirect

// src/routes/posts.js
app.get('/articles', async (request, reply) => {
  return reply.redirect('/posts', 301);
});

Open http://localhost:3000/articles — the browser moves to /posts. The second argument is the code: 301 means "moved permanently"; without it 302 is used.

Common mistake

Do not call reply.send() and return a value at the same time: the reply would be sent twice, and the log shows a "Reply was already sent" warning. In an async handler choose one — return data or return reply.send(data).

Thanks for reading!

Donate to the site — we work hard for you.