Fastify入門|ルーティング

概要

Fastify は、簡単にルーティングを定義できる機能を提供しています。ルーティングは、HTTP リクエストを処理するためのエンドポイントを指定することで定義されます。Fastify のルーティング機能は、柔軟性が高く、パフォーマンスが優れているため、Web アプリケーションの開発に最適な選択肢の 1 つです。

環境

Fastify v4.0.0
Node v19.7.0

利用例

Fastify のルーティングは、fastify.route()メソッドを使用して定義されます。このメソッドは、HTTP メソッド、URL パターン、および処理関数を指定します。以下は、GET リクエストを処理する簡単な例です。

const fastify = require('fastify')()

fastify.route({
  method: 'GET',
  url: '/hello',
  handler: function (request, reply) {
    reply.send('Hello, World!')
  }
})

ルーティングは、複数の HTTP メソッドを許可する場合や、正規表現を使用した URL パターンの指定、前処理や後処理の追加など、多くの柔軟性があります。また、Fastify は高速であるため、パフォーマンス上の問題がなく、高トラフィックのアプリケーションにも対応できます。

Fastify のルーティング機能は、Web アプリケーション開発に必須の機能であるため、しっかりと理解しておくことが重要です。

ルーティングの宣言方法

前回紹介した方法として、Shorthand Declaration と Full Declaration があります。 Shorthand Declaration は記述がシンプルで綺麗なので、Express.js や Restify を触ったことがある場合はとっつきやすいかもしれません。 一方、Full Declaration はより詳細な設定ができるため、必要に応じて利用することができます。

  1. Full Declaration Full Declaration の場合は、option と method、url を含めた JSON を引数として route メソッドの引数に渡します。Hapi の記述に似ています。
  2. Shorthand Declaration Shorthand Declaration の場合は、Express.js や Restify に似た書き方をすることができます。記述がシンプルで綺麗なので、とっつきやすいかもしれません。

Full Declaration(完全宣言)

Full Declaration場合、option と method と url を含めた json を引数として route メソッドの引数に渡します。Hapi の記述に似ています。

const fastify = require("fastify")({
  logger: true,
  ignoreTrailingSlash: true,
});

const opts = {
  method: "GET",
  url: "/hello",
  schema: {
    querystring: {
      name: { type: "string" },
      excitement: { type: "integer" },
    },
    response: {
      200: {
        type: "object",
        properties: {
          message: { type: "string" },
        },
      },
    },
  },
  handler: function (request, reply) {
    reply.send({ message: "Hello, World!" });
  },
};
fastify.route(opts);

// Run the server!
const start = async () => {
  try {
    await fastify.listen(3000);
  } catch (err) {
    fastify.log.error(err);
    process.exit(1);
  }
};
start();

このように、オプションをオブジェクトで定義することで、より詳細な設定を行うことができます。

Shorthand Declaration(速記宣言)

Shorthand Declaration の場合、記述がシンプルなのでコードが綺麗です。
書き方としてはExpress.jsRestifyと似ているので、どちらか触ったことがある場合はこちらのやり方がとっつきやすくていいと思います。Express.js の書き方が好きな人はこちらで開発を進めることをお勧めします。

- fastify.get(path, [options], handler)
- fastify.head(path, [options], handler)
- fastify.post(path, [options], handler)
- fastify.put(path, [options], handler)
- fastify.delete(path, [options], handler)
- fastify.options(path, [options], handler)
- fastify.patch(path, [options], handler)
const fastify = require("fastify")({
  logger: true,
  ignoreTrailingSlash: true,
});

fastify.get("/hello", {
  schema: {
    querystring: {
      name: { type: "string" },
      excitement: { type: "integer" },
    },
    response: {
      200: {
        type: "object",
        properties: {
          message: { type: "string" },
        },
      },
    },
  },
  handler: function (request, reply) {
    reply.send({ message: "Hello, World!" });
  },
});

// Run the server!
const start = async () => {
  try {
    await fastify.listen(3000);
  } catch (err) {
    fastify.log.error(err);
    process.exit(1);
  }
};
start();

動的 URL 宣言

Fastify では、URL パスに動的な部分がある場合、それを変数として扱うことができます。たとえば、/users/:userId という URL パスがある場合、:userId の部分を変数として扱うことができます。このような変数は、params オブジェクトを介してアクセスできます。

const fastify = require('fastify')();

fastify.get('/users/:userId', async (request, reply) => {
  const userId = request.params.userId;
  reply.send({ message: `User ID is ${userId}` });
});

fastify.listen(3000, (err, address) => {
  if (err) throw err;
  console.log(`Server listening on ${address}`);
});

上記のコードでは、/users/:userId という URL パスにアクセスした場合、:userId の部分に入力された値を取得して返します。Fastify では、URL パスに変数を含むルーティングの設定が簡単に行えるため、このような動的な URL を使ったアプリケーションを開発することができます。

リクエストの妥当性チェック

Fastify では、リクエストの妥当性チェックをスキーマ定義によって行うことができます。スキーマ定義を用いることで、API のドキュメント作成、リクエストのバリデーション、自動生成されたテストの作成が容易になります。

スキーマ定義を使用するには、 schema プロパティを使用します。例えば、次のようなスキーマを作成することができます。

const schema = {
  body: {
    type: "object",
    required: ["name", "age"],
    properties: {
      name: { type: "string" },
      age: { type: "integer", minimum: 0 },
    },
  },
  response: {
    200: {
      type: "object",
      properties: {
        success: { type: "boolean" },
        message: { type: "string" },
      },
    },
  },
};

上記の例では、body プロパティにはリクエストボディのスキーマを、response プロパティにはレスポンスのスキーマを定義しています。body プロパティでは、name と age の 2 つのプロパティが必須であることを定義しています。また、age プロパティには最小値が 0 であることを定義しています。

スキーマを定義した後は、ルーティング定義の schema プロパティにスキーマオブジェクトを渡すことで、リクエストのバリデーションを行うことができます。

fastify.post("/", {
  schema: schema,
}, async (request, reply) => {
  const { name, age } = request.body;
  reply.send({ success: true, message: `Hello, ${name}! You are ${age} years old.` });
});

上記の例では、fastify.post()の第 2 引数にスキーマオブジェクトを渡すことで、リクエストの妥当性チェックを行っています。リクエストボディがスキーマに従っていない場合は、Fastify は自動的に 400 Bad Request エラーを返します。

Fastify では、JSON スキーマだけでなく、JSON Hyper-Schema、OpenAPI / Swagger スキーマなど、様々な種類のスキーマ定義に対応しています。

ハンドラー関数

ルーティングの設定では、handler プロパティにハンドラー関数を設定することができます。ハンドラー関数は、リクエストを受け取り、レスポンスを返す関数です。次の例では、/hello エンドポイントにリクエストが送信されたときに、handler プロパティに定義されたハンドラー関数が呼び出されます。


fastify.get('/hello', function (request, reply) {
reply.send({ hello: 'world' })
})

Fastify では、ハンドラー関数が非同期関数である場合、Fastify はその関数が完了するまでレスポンスを保留します。このため、Fastify では、非同期関数の使用を推奨しています。


fastify.get('/hello', async function (request, reply) {
const result = await someAsyncFunction()
reply.send(result)
})

スキーマバリデーション

Fastify は、リクエストとレスポンスのバリデーションをサポートしています。バリデーションを設定するには、schema プロパティを使用します。schema オブジェクトには、querystring、params、body、headers、response などのプロパティを定義できます。


const schema = {
  querystring: {
    name: { type: 'string' },
    age: { type: 'integer' }
  }
}

fastify.get('/user', { schema }, function (request, reply) {
  const { name, age } = request.query
  reply.send(`Hello, ${name}! You are ${age} years old.`)
})

この例では、querystring オブジェクトに、name と age の 2 つのプロパティを定義しています。これにより、リクエストパラメーターが正しい形式であることをバリデーションできます。バリデーションに失敗した場合、Fastify は自動的にエラーレスポンスを返します。

まとめ

Fastify ではルーティングに関する豊富な機能を提供しています。簡単なルーティングから高度なルーティングまで、様々なニーズに対応することができます。この記事では、Fastify のルーティングについて、基本的なことから動的 URL やバリデーション、妥当性チェックといった高度な機能に至るまで解説しました。

基本的なルーティングでは、HTTP メソッドと URL パスを指定するだけで簡単にルーティングを実装することができます。Fastify では、シンプルなルーティング以外にも、正規表現を用いたルーティングや、HTTP メソッドのエイリアス、ハンドラ関数のライフサイクルなど、柔軟なルーティングを実装することができます。

動的 URL では、URL パラメータの取得方法やバリデーション、妥当性チェックなど、より高度なルーティングが必要になります。Fastify では、動的 URL に対してパラメータの取得方法やバリデーションを行うためのシンプルな API を提供しています。

また、Fastify ではスキーマに基づいたバリデーションや妥当性チェックを簡単に実装することができます。リクエストの妥当性チェックを行うことで、セキュリティ上の問題を回避することができます。

Fastify は、高速でシンプルな Web アプリケーションフレームワークとして知られています。Fastify のルーティングは、高度な機能を備えた柔軟な API を提供しているため、Web アプリケーション開発において欠かせない機能の一つです。