ウェブエンジニア問題集
第3章

Fastifyのルーティング — GET・POST・パスパラメータを定義する

4
この章の目次開く

ルーティングとは、どのHTTPメソッドとURLに、どの処理を対応させるかを決めることです。Fastifyでは、fastify.get()fastify.post() などのショートハンドメソッドを使うのが基本です。

fastify.get('/todos', async () => {
  return [{ id: 1, title: 'Fastifyを学ぶ', completed: false }];
});
js

ルート定義の構文

構文: fastify.METHOD(path, options, handler)

引数説明
pathstringURLのパス。:id のようにパスパラメータを定義できる
optionsobjectschema、hooks、ログ設定など。省略できる
handlerfunctionリクエストを処理する関数

戻り値: Fastifyインスタンス。通常は戻り値を意識せず、登録処理として使います。

options を使わない場合は、第2引数にhandlerを書けます。

fastify.get('/health', async () => {
  return { ok: true };
});
js

schema などを指定する場合は、第2引数にoptions、第3引数にhandlerを書きます。

fastify.get('/todos', {
  schema: {
    response: {
      200: {
        type: 'array',
        items: {
          type: 'object',
          properties: {
            id: { type: 'number' },
            title: { type: 'string' },
            completed: { type: 'boolean' },
          },
        },
      },
    },
  },
}, async () => {
  return todos;
});
js

HTTPメソッドごとに処理を分ける

Todo APIの入り口を作ってみます。

const todos = [
  { id: 1, title: 'Fastifyを学ぶ', completed: false },
];
 
fastify.get('/todos', async () => {
  return todos;
});
 
fastify.post('/todos', async (request, reply) => {
  const todo = {
    id: todos.length + 1,
    title: request.body.title,
    completed: false,
  };
 
  todos.push(todo);
 
  return reply.code(201).send(todo);
});
js
メソッド主な用途
GET取得Todo一覧を返す
POST作成Todoを追加する
PUT全体更新Todo全体を置き換える
PATCH部分更新completed だけ変更する
DELETE削除Todoを削除する

パスパラメータ

URLの一部を変数として受け取るには、:id のように書きます。

fastify.get('/todos/:id', async (request, reply) => {
  const id = Number(request.params.id);
  const todo = todos.find((item) => item.id === id);
 
  if (!todo) {
    return reply.code(404).send({ error: 'TODO_NOT_FOUND' });
  }
 
  return todo;
});
js

GET /todos/1 にアクセスすると、request.params.id'1' になります。

request.paramsrequest.query の値は基本的に文字列として入ってくるため、数値として使う前に変換と検証が必要です。

クエリ文字列

GET /todos?completed=true のような値は、request.query から取り出します。

fastify.get('/todos', async (request) => {
  const completed = request.query.completed;
 
  if (completed === 'true') {
    return todos.filter((todo) => todo.completed);
  }
 
  if (completed === 'false') {
    return todos.filter((todo) => !todo.completed);
  }
 
  return todos;
});
js

このままだと completed=yes のような値も素通りします。Fastifyでは、次章以降で扱う schema を使うと、クエリやボディの形をルート単位で検証できます。

学習者学習者

じゃあ毎回 Number()if で検証を書くんですか?

先生先生

小さい例ではそれでも動きますが、実務では抜け漏れが出ます。Fastifyではschemaをルートに付けて、入口でまとめて検証するのが基本です。

参考リンク

次章では、handlerに渡ってくる requestreply を詳しく見て、レスポンスの返し方を整理します。

Node.jsクイズに挑戦するHTTPメソッドやルーティングの基本をクイズで確認しよう