Route parameters, query and body
A handler gets the request object as its first argument — everything the client sent. Most often you take three things from it: route parameters, the query string (query — the part of the address after ?) and the request body (body — data the client sent with POST or PUT).
Route parameters
The part of the address with a colon ends up in request.params. Add a single-post route to src/routes/posts.js:
// src/routes/posts.js
app.get('/posts/:id', async (request) => {
const id = Number(request.params.id);
return posts.find((post) => post.id === id);
});Open http://localhost:3000/posts/2 — the second post appears. Parameters always arrive as strings, so id is converted to a number.
A route can have several parameters:
// src/routes/comments.js
export default async function commentRoutes(app) {
app.get('/posts/:id/comments/:commentId', async (request) => {
const { id, commentId } = request.params;
return { id, commentId };
});
}Do not forget to register the new file in src/app.js with app.register(commentRoutes). The address /posts/1/comments/7 returns {"id":"1","commentId":"7"}.
The query string
Fastify collects the parameters after ? into the request.query object:
// src/routes/posts.js
app.get('/posts', async (request) => {
const limit = Number(request.query.limit ?? 10);
return posts.slice(0, limit);
});The address /posts?limit=1 returns only the first post, and /posts without the parameter returns up to ten posts.
The request body
If the client sent JSON with the Content-Type: application/json header, Fastify parses it into request.body:
// src/routes/posts.js
app.post('/posts', async (request) => {
const { title, body } = request.body;
const post = { id: posts.length + 1, title, body };
posts.push(post);
return post;
});Send a new post from the terminal:
curl -X POST http://localhost:3000/posts \
-H "Content-Type: application/json" \
-d '{"title":"New post","body":"Some text"}'The server returns the post with id 3, and it shows up in the /posts list — until the server restarts.
What else request has
| Property | What it holds |
|---|---|
request.params | Route parameters |
request.query | The query string |
request.body | The parsed body |
request.headers | Headers, names in lower case |
request.ip | The client IP address |
request.log | The logger of this request |
So far the data is not checked at all: a client can send an empty title or a string instead of a number. Schema validation is added in the chapter on schemas.
Common mistake
Comparing a parameter with a number without converting it never matches:
// src/routes/posts.js
// Wrong: '2' === 2 is false.
posts.find((post) => post.id === request.params.id);Convert parameters with Number() — or set the type in a schema and Fastify does it for you.