Fastifyでルーティングを使用する方法

概要

Fastifyは、簡単にルーティングを定義できる機能を提供しています。
ルーティングは、HTTPリクエストを処理するためのエンドポイントを指定することで定義されます。

以下では、ルーティングの概念、ルートの定義、ルートハンドラの作成、ルーティングパラメータの処理、およびルートのオプションについて詳しく説明します。

ここでは、以下バージョンを使用した、ルーティング方法を説明します。

Fastify v4.0.0
nodejs v19.7.0

また、今回作成するコードは全て、以下に掲載しています。 https://github.com/wiblok/Fastify

ルーティングの概念

ルーティングは、クライアントからのリクエストが特定のエンドポイントに到達した際に、Fastifyアプリケーションがどのように処理するかを定義します。

ルーティングは、HTTPメソッド(GET、POST、PUT、DELETEなど)とパス(URL)の組み合わせで定義されます。

ルートの定義方法

ルーティング使用する方法はいくつかありますが、以下の4つの方法が一般的です。

  1. ショートメソッドを使用する方法
fastify.'<HTTPメソッド>'({'<パス>', async (request, reply) => {
  // ルートの処理
}});
  1. fastify.route()メソッドを使用する方法
fastify.route({
  method: '<HTTPメソッド>',
  url: '<パス>',
  handler: async (request, reply) => {
    // ルートの処理
  }
});
  1. ルートハンドラ関数を直接使用する方法
const routeHandler = async (request, reply) => {
  // ルートの処理
};
fastify.<HTTPメソッド>('<パス>', routeHandler);
  1. ルートオプションを使用する方法
const routeOptions = {
  method: '<HTTPメソッド>',
  url: '<パス>',
  handler: async (request, reply) => {
    // ルートの処理
  }
};
fastify.route(routeOptions);
  • HTTPメソッド: HTTPリクエストのメソッドを指定します(例: get、post、put、deleteなど)。
  • パス: クライアントからのリクエストがマッチするURLパスを指定します。

以下見出しからは、コードを記述します。

ショートメソッドを使用する方法

short.js

const fastify = require("fastify")();

fastify.get("/hello", async (request, reply) => {
  return "Hello, Fastify!";
});

fastify.post("/users", async (request, reply) => {
  const user = request.body;
  // ユーザーの作成処理など...
  return { id: 1, name: user.name };
});

fastify.put("/users/:id", async (request, reply) => {
  const userId = request.params.id;
  const user = request.body;
  // ユーザーの更新処理など...
  return { id: userId, name: user.name };
});

fastify.delete("/users/:id", async (request, reply) => {
  const userId = request.params.id;
  // ユーザーの削除処理など...
  return { message: `User ${userId} has been deleted.` };
});

fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    console.error("サーバーの起動中にエラーが発生しました:", err);
    process.exit(1);
  }
  console.log("サーバーがポート3000で起動しました");
});

解説

  • Fastifyのインスタンスを作成
const fastify = require("fastify")();

Fastifyモジュールをインポートし、そのインスタンスを作成します。

  • GETリクエストのハンドリング:
fastify.get("/hello", async (request, reply) => {
  return "Hello, Fastify!";
});

/helloというパスへのGETリクエストをハンドリングします。リクエストが来ると、“Hello, Fastify!“という文字列をレスポンスとして返します。

  • POSTリクエストのハンドリング
fastify.post("/users", async (request, reply) => {
  const user = request.body;
  // ユーザーの作成処理など...
  return { id: 1, name: user.name };
});

/usersというパスへのPOSTリクエストをハンドリングします。リクエストボディからユーザー情報を取得し、新たなユーザーを作成します。作成したユーザーの情報をレスポンスとして返します。

  • PUTリクエストのハンドリング
fastify.put("/users/:id", async (request, reply) => {
  const userId = request.params.id;
  const user = request.body;
  // ユーザーの更新処理など...
  return { id: userId, name: user.name };
});

/users/:idというパスへのPUTリクエストをハンドリングします。URLのパラメータからユーザーIDを取得し、リクエストボディから更新情報を取得します。その情報を用いてユーザー情報を更新し、更新したユーザーの情報をレスポンスとして返します。

  • DELETEリクエストのハンドリング
fastify.delete("/users/:id", async (request, reply) => {
  const userId = request.params.id;
  // ユーザーの削除処理など...
  return { message: `User ${userId} has been deleted.` };
});

/users/:idというパスへのDELETEリクエストをハンドリングします。URLのパラメータからユーザーIDを取得し、そのユーザーを削除します。削除したことを示すメッセージをレスポンスとして返します。

  • サーバーの起動
fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    console.error("サーバーの起動中にエラーが発生しました:", err);
    process.exit(1);
  }
  console.log("サーバーがポート3000で起動しました");
});

Fastifyのインスタンスをポート3000でリッスンさせ、サーバーを起動します。もし何らかのエラーが発生した場合は、エラーメッセージをコンソールに出力し、プロセスを終了します。エラーがなければ、“サーバーがポート3000で起動しました"というメッセージをコンソールに出力します。

テスト

# GETリクエストのテスト
curl -X GET http://localhost:3000/hello
# POSTリクエストのテスト
curl -X POST -H "Content-Type: application/json" -d '{"name":"John Doe"}' http://localhost:3000/users
# PUTリクエストのテスト
curl -X PUT -H "Content-Type: application/json" -d '{"name":"Jane Smith"}' http://localhost:3000/users/1
# DELETEリクエストのテスト
curl -X DELETE http://localhost:3000/users/1

ルートメソッドを使用する方法

route.js

const fastify = require("fastify")();

fastify.route({
  method: "GET",
  url: "/hello",
  handler: async (request, reply) => {
    return "Hello, Fastify!";
  },
});

fastify.route({
  method: "POST",
  url: "/users",
  handler: async (request, reply) => {
    const user = request.body;
    // ユーザーの作成処理など...
    return { id: 1, name: user.name };
  },
});

fastify.route({
  method: "PUT",
  url: "/users/:id",
  handler: async (request, reply) => {
    const userId = request.params.id;
    const user = request.body;
    // ユーザーの更新処理など...
    return { id: userId, name: user.name };
  },
});

fastify.route({
  method: "DELETE",
  url: "/users/:id",
  handler: async (request, reply) => {
    const userId = request.params.id;
    // ユーザーの削除処理など...
    return { message: `User ${userId} has been deleted.` };
  },
});

fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    console.error("サーバーの起動中にエラーが発生しました:", err);
    process.exit(1);
  }
  console.log("サーバーがポート3000で起動しました");
});

解説

  • Fastifyのインスタンスを作成
const fastify = require("fastify")();

Fastifyモジュールをインポートし、そのインスタンスを作成します。

  • GETリクエストのハンドリング:
fastify.route({
  method: "GET",
  url: "/hello",
  handler: async (request, reply) => {
    return "Hello, Fastify!";
  },
});

/helloというパスへのGETリクエストをハンドリングします。リクエストが来ると、“Hello, Fastify!“という文字列をレスポンスとして返します。

  • POSTリクエストのハンドリング
fastify.route({
  method: "POST",
  url: "/users",
  handler: async (request, reply) => {
    const user = request.body;
    // ユーザーの作成処理など...
    return { id: 1, name: user.name };
  },
});

/usersというパスへのPOSTリクエストをハンドリングします。リクエストボディからユーザー情報を取得し、新たなユーザーを作成します。作成したユーザーの情報をレスポンスとして返します。

  • PUTリクエストのハンドリング
fastify.route({
  method: "PUT",
  url: "/users/:id",
  handler: async (request, reply) => {
    const userId = request.params.id;
    const user = request.body;
    // ユーザーの更新処理など...
    return { id: userId, name: user.name };
  },
});

/users/:idというパスへのPUTリクエストをハンドリングします。URLのパラメータからユーザーIDを取得し、リクエストボディから更新情報を取得します。その情報を用いてユーザー情報を更新し、更新したユーザーの情報をレスポンスとして返します。

  • DELETEリクエストのハンドリング
fastify.route({
  method: "DELETE",
  url: "/users/:id",
  handler: async (request, reply) => {
    const userId = request.params.id;
    // ユーザーの削除処理など...
    return { message: `User ${userId} has been deleted.` };
  },
});

/users/:idというパスへのDELETEリクエストをハンドリングします。URLのパラメータからユーザーIDを取得し、そのユーザーを削除します。削除したことを示すメッセージをレスポンスとして返します。

  • サーバーの起動
fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    console.error("サーバーの起動中にエラーが発生しました:", err);


    process.exit(1);
  }
  console.log("サーバーがポート3000で起動しました");
});

Fastifyのインスタンスをポート3000でリッスンさせ、サーバーを起動します。もし何らかのエラーが発生した場合は、エラーメッセージをコンソールに出力し、プロセスを終了します。エラーがなければ、“サーバーがポート3000で起動しました"というメッセージをコンソールに出力します。

テスト

# GETリクエストのテスト
curl -X GET http://localhost:3000/hello
# POSTリクエストのテスト
curl -X POST -H "Content-Type: application/json" -d '{"name":"John Doe"}' http://localhost:3000/users
# PUTリクエストのテスト
curl -X PUT -H "Content-Type: application/json" -d '{"name":"Jane Smith"}' http://localhost:3000/users/1
# DELETEリクエストのテスト
curl -X DELETE http://localhost:3000/users/1

ルートハンドラ関数を直接使用する方法

handler.js

const fastify = require("fastify")();

const helloHandler = async (request, reply) => {
  return "Hello, Fastify!";
};

const createUserHandler = async (request, reply) => {
  const user = request.body;
  // ユーザーの作成処理など...
  return { id: 1, name: user.name };
};

const updateUserHandler = async (request, reply) => {
  const userId = request.params.id;
  const user = request.body;
  // ユーザーの更新処理など...
  return { id: userId, name: user.name };
};

const deleteUserHandler = async (request, reply) => {
  const userId = request.params.id;
  // ユーザーの削除処理など...
  return { message: `User ${userId} has been deleted.` };
};

fastify.get("/hello", helloHandler);
fastify.post("/users", createUserHandler);
fastify.put("/users/:id", updateUserHandler);
fastify.delete("/users/:id", deleteUserHandler);

fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    console.error("サーバーの起動中にエラーが発生しました:", err);
    process.exit(1);
  }
  console.log("サーバーがポート3000で起動しました");
});

解説

  • Fastifyのインスタンスを作成
const fastify = require("fastify")();

Fastifyモジュールをインポートし、そのインスタンスを作成します。

  • ハンドラの定義
const helloHandler = async (request, reply) => {
  return "Hello, Fastify!";
};

const createUserHandler = async (request, reply) => {
  const user = request.body;
  // ユーザーの作成処理など...
  return { id: 1, name: user.name };
};

const updateUserHandler = async (request, reply) => {
  const userId = request.params.id;
  const user = request.body;
  // ユーザーの更新処理など...
  return { id: userId, name: user.name };
};

const deleteUserHandler = async (request, reply) => {
  const userId = request.params.id;
  // ユーザーの削除処理など...
  return { message: `User ${userId} has been deleted.` };
};

各リクエストのハンドラを関数として定義します。これらの関数は、それぞれGET、POST、PUT、DELETEリクエストを処理します。

  • ルーティングの設定
fastify.get("/hello", helloHandler);
fastify.post("/users", createUserHandler);
fastify.put("/users/:id", updateUserHandler);
fastify.delete("/users/:id", deleteUserHandler);

Fastifyのインスタンスに対して、各リクエストのハンドラを設定します。これにより、特定のURLへの特定のHTTPメソッドのリクエストが来たときに、対応するハンドラが呼び出されます。

  • サーバーの起動
fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    console.error("サーバーの起動中にエラーが発生しました:", err);
    process.exit(1);
  }
  console.log("サーバーがポート3000で起動しました");
});

Fastifyのインスタンスをポート3000でリッスンさせ、サーバーを起動します。もし何らかのエラーが発生した場合は、エラーメッセージをコンソールに出力し、プロセスを終了します。エラーがなければ、“サーバーがポート3000で起動しました"というメッセージをコンソールに出力します。

テスト

# GETリクエストのテスト
curl -X GET http://localhost:3000/hello
# POSTリクエストのテスト
curl -X POST -H "Content-Type: application/json" -d '{"name":"John Doe"}' http://localhost:3000/users
# PUTリクエストのテスト
curl -X PUT -H "Content-Type: application/json" -d '{"name":"Jane Smith"}' http://localhost:3000/users/1
# DELETEリクエストのテスト
curl -X DELETE http://localhost:3000/users/1

ルートオプションを使用する方法

option.js

const fastify = require("fastify")();

const helloRouteOptions = {
  method: "GET",
  url: "/hello",
  handler: async (request, reply) => {
    return "Hello, Fastify!";
  },
};

const createUserRouteOptions = {
  method: "POST",
  url: "/users",
  handler: async (request, reply) => {
    const user = request.body;
    // ユーザーの作成処理など...
    return { id: 1, name: user.name };
  },
};

const updateUserRouteOptions = {
  method: "PUT",
  url: "/users/:id",
  handler: async (request, reply) => {
    const userId = request.params.id;
    const user = request.body;
    // ユーザーの更新処理など...
    return { id: userId, name: user.name };
  },
};

const deleteUserRouteOptions = {
  method: "DELETE",
  url: "/users/:id",
  handler: async (request, reply) => {
    const userId = request.params.id;
    // ユーザーの削除処理など...
    return { message: `User ${userId} has been deleted.` };
  },
};

fastify.route(helloRouteOptions);
fastify.route(createUserRouteOptions);
fastify.route(updateUserRouteOptions);
fastify.route(deleteUserRouteOptions);

fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    console.error("サーバーの起動中にエラーが発生しました:", err);
    process.exit(1);
  }
  console.log("サーバーがポート3000で起動しました");
});

解説

  • Fastifyのインスタンスを作成
const fastify = require("fastify")();

Fastifyモジュールをインポートし、そのインスタンスを作成します。

  • ルートオプションの定義
const helloRouteOptions = {
  method: "GET",
  url: "/hello",
  handler: async (request, reply) => {
    return "Hello, Fastify!";
  },
};

const createUserRouteOptions = {
  method: "POST",
  url: "/users",
  handler: async (request, reply) => {
    const user = request.body;
    // ユーザーの作成処理など...
    return { id: 1, name: user.name };
  },
};

const updateUserRouteOptions = {
  method: "PUT",
  url: "/users/:id",
  handler: async (request, reply) => {
    const userId = request.params.id;
    const user = request.body;
    // ユーザーの更新処理など...
    return { id: userId, name: user.name };
  },
};

const deleteUserRouteOptions = {
  method: "DELETE",
  url: "/users/:id",
  handler: async (request, reply) => {
    const userId = request.params.id;
    // ユーザーの削除処理など...
    return { message: `User ${userId} has been deleted.` };
  },
};

各リクエストのルートオプションをオブジェクトとして定義します。これらのオブジェクトは、それぞれGET、POST、PUT、DELETEリクエストを処理します。

  • ルーティングの設定
fastify.route(helloRouteOptions);
fastify.route(createUserRouteOptions);
fastify.route(updateUserRouteOptions);
fastify.route(deleteUserRouteOptions);

Fastifyのインスタンスに対して、各リクエストのルートオプションを設定します。これにより、特定のURLへの特定のHTTPメソッドのリクエストが来たときに、対応するハンドラが呼び出されます。

  • サーバーの起動
fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    console.error("サーバーの起動中にエラーが発生しました:", err);
    process.exit(1);
  }
  console.log("サーバーがポート3000で起動しました");
});

Fastifyのインスタンスをポート3000でリッスンさせ、サーバーを起動します。もし何らかのエラーが発生した場合は、エラーメッセージをコンソールに出力し、プロセスを終了します。エラーがなければ、“サーバーがポート3000で起動しました"というメッセージをコンソールに出力します。

解説

# GETリクエストのテスト
curl -X GET http://localhost:3000/hello
# POSTリクエストのテスト
curl -X POST -H "Content-Type: application/json" -d '{"name":"John Doe"}' http://localhost:3000/users
# PUTリクエストのテスト
curl -X PUT -H "Content-Type: application/json" -d '{"name":"Jane Smith"}' http://localhost:3000/users/1
# DELETEリクエストのテスト
curl -X DELETE http://localhost:3000/users/1

まとめ

Fastify ではルーティングに関する豊富な機能を提供しています。簡単なルーティングから高度なルーティングまで、様々なニーズに対応することができます。

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

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

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