概要: このチュートリアルでは、Expressルーティングについて学びます。これは、エンドポイント(URI)を定義し、クライアントがそれらのエンドポイントをリクエストしたときに応答するプロセスです。
Expressルーティングの概要
エンドポイントとは、特定のURL(Uniform Resource Locator)またはパスと、HTTPメソッド(GET、POST、PUT、…)のことです。
通常、エンドポイントは、クライアントがデータの取得、データの変更、レコードの削除などの特定の操作を実行できる特定のリソースまたは機能を意味します。
たとえば、次のエンドポイントはToDoリストを取得します。
GET /todosこのエンドポイントでは、パスは/todosで、HTTPメソッドはGETです。
次のエンドポイントは、新しいToDo項目を作成します。
POST /todosパスは/todosですが、HTTPメソッドはPOSTです。
Expressでは、ルーティングは、エンドポイントを設定し、クライアントがそれらのエンドポイントをリクエストしたときにアプリケーションがどのように応答するかを定義することです。
ルートは、アプリケーションがエンドポイントへのリクエストをどのように処理するかを定義します。ルートを定義するには、get、post、put、patch、deleteなどのExpressオブジェクトのメソッドと、
ルートを定義するための構文を以下に示します。
app.method(path, handler);Code language: JavaScript (javascript)この構文では、
appは、Expressアプリケーションのインスタンスです。methodは、get、post、put、patch、deleteなどの小文字のHTTPリクエストメソッドです。pathは、サーバー上のパスです。handlerは、ルートが一致したときに実行される関数です。ルートハンドラーは、HTTPリクエストおよびレスポンスオブジェクトに対応するreqおよびresオブジェクトにアクセスできます。
基本的なルートの例
以下は、ルートURL('/')へのGETリクエストのルートを定義します。
app.get('/', (req, res) => {
res.send('Hello World');
});Code language: PHP (php)同様に、以下は'/about'へのGETリクエストのルートを定義します。
app.get('/about', (req, res) => {
res.send('About Page');
});Code language: PHP (php)次の例は、'/login'へのPOSTリクエストのルートを定義します。
app.post('/login', (req, res) => {
res.send('Authenticated');
});Code language: PHP (php)Expressルーティングの例
いくつかのルートを持つExpressアプリケーションを作成してみましょう。
Expressアプリケーションの作成
ステップ1. ターミナルまたはコマンドプロンプトを開き、express-routingなどの新しいディレクトリを作成します。
mkdir express-routing
cd express-routingCode language: JavaScript (javascript)ステップ2. 次のnpmコマンドを実行して、プロジェクトを初期化します。
npm init -yCode language: JavaScript (javascript)これにより、構成、スクリプト、依存関係を含むpackage.jsonファイルが作成されます。
ステップ3. ターミナルから次のnpmコマンドを実行して、Expressをインストールします。
npm install expressCode language: JavaScript (javascript)ステップ4. プロジェクトに.envファイルを追加し、PORTを3000に設定します。
PORT=3000Code language: JavaScript (javascript)ステップ5. Node.jsにESモジュールを使用するように指示するために、次のキー/値ペアをpackage.jsonファイルに追加します。
"type": "module"Code language: JavaScript (javascript)また、scriptsセクションを次のように変更します。
"scripts": {
"start": "node --watch index.js"
},Code language: JavaScript (javascript)これにより、npm startコマンドを実行して、--watchフラグを使用してindex.jsファイルを実行できます。
ステップ6. 次のコードを含むindex.jsファイルを作成します。
import express from 'express';
const app = express();
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});Code language: JavaScript (javascript)ステップ7. ターミナルから次のコマンドを実行して、サーバーを起動します。
npm startCode language: JavaScript (javascript)ステップ8. VS CodeのREST Client拡張機能を使用してルートにリクエストを行うためのapi.httpファイルを作成します。
ルートの追加
ステップ1. ToDo項目の配列と次のToDo IDを返す関数をエクスポートする新しいモジュールtodos.jsモジュールを作成します。
export const todos = [
{ id: 1, title: 'Learn Node.js', completed: true },
{ id: 2, title: 'Master Express', completed: false },
{ id: 3, title: 'Build an API Server', completed: false },
];
export const nextTodoId = () => {
// get the next id for the todo
let maxId = 1;
todos.forEach((todo) => {
if (todo.id > maxId) {
maxId = todo.id;
}
});
return maxId + 1;
};Code language: JavaScript (javascript)ステップ2. todos.jsモジュールからtodos配列とnextTodoId関数をindex.jsモジュールにインポートします。
import { todos, nextTodoId } from './todos.js';Code language: JavaScript (javascript)ステップ3. '/api/todos/'エンドポイントへのGETリクエストのルートを定義します。
import express from 'express';
import { todos, nextTodoId} from './todos.js';
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/api/todos/', (req, res) => {
res.send(todos);
});
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});Code language: JavaScript (javascript)ステップ4. /api/todosエンドポイントへのHTTPリクエストを追加して、api.httpを変更します。
# Get all todos items
GET http://:3000/api/todos/Code language: JavaScript (javascript)/api/todos/エンドポイントにGETリクエストが送信されると、ルートハンドラーが実行され、todos配列をJSONデータとして応答します。
[
{
"id": 1,
"title": "Learn Node.js",
"completed": true
},
{
"id": 2,
"title": "Master Express",
"completed": false
},
{
"id": 3,
"title": "Build an API Server",
"completed": false
}
]Code language: JavaScript (javascript)ルートへのクエリ文字列の追加
完了または未完了のToDo項目のリストを取得するには、次のようにクエリ文字列を/api/todosルートに追加できます。
http://:3000/api/todos/?completed=trueCode language: JavaScript (javascript)または
http://:3000/api/todos/?completed=falseCode language: JavaScript (javascript)URL内の疑問符(?)以降のすべては、クエリ文字列と呼ばれます。この例では、クエリ文字列は次のとおりです。
completed=falseCode language: JavaScript (javascript)クエリ文字列には、1つ以上のパラメータを含めることができます。各パラメータは、等号(=)で区切られた一意のキー/値ペアで表されます。
ExpressでURLからクエリ文字列にアクセスするには、次のようにreq.queryオブジェクトを使用します。
req.queryCode language: JavaScript (javascript)例:
// ...
app.get('/api/todos/', (req, res) => {
console.log(req.query);
});
// ...Code language: JavaScript (javascript)https://:3000/api/todos/?completed=falseエンドポイントにGETリクエストを行うと、コンソールに次のクエリオブジェクトが表示されます。
{ completed: 'false' }Code language: JavaScript (javascript)クエリ文字列のcompletedパラメータにアクセスするには、次を使用できます。
app.get('/api/todos/', (req, res) => {
console.log(req.query.completed);
});Code language: JavaScript (javascript)以下は、completedクエリ文字列が使用可能な場合に、未完了/完了のToDo項目を返すように/api/todos/エンドポイントを変更します。
app.get('/api/todos/', (req, res) => {
if (req?.query?.completed) {
const isCompleted = req.query.completed === 'true';
const filteredTodos = todos.filter(
(todo) => todo.completed === isCompleted
);
res.send(filteredTodos);
}
res.send(todos);
});Code language: JavaScript (javascript)更新されたapi.httpファイルのバージョンを以下に示します。
# Get all todos items
GET http://:3000/api/todos/
###
# Get incompleted todo items:
GET http://:3000/api/todos/?completed=false
###
# Get completed todo items:
GET http://:3000/api/todos/?completed=trueCode language: JavaScript (javascript)ルートパラメータの処理
ルートセグメントは、URL内の位置に指定された値をキャプチャするために使用される名前付きURLセグメントです。例えば
http://:3000/api/todos/1Code language: JavaScript (javascript)このURLでは、1はToDo IDを表すルートパラメータです。
Expressでは、次のようにIDを使用してルートを設定できます。
/api/todo/:idCode language: JavaScript (javascript)ルートパラメータにアクセスするには、req.paramsオブジェクトを使用します。
req.paramsCode language: JavaScript (javascript)ルート/api/todo/:idでは、idはreq.paramsオブジェクトのキーです。したがって、次を使用してアクセスできます。
req.params.idCode language: JavaScript (javascript)ルートパラメータの値は常に文字列であることに注意してください。したがって、目的の型の値に変換する必要があります。
以下は、IDによってToDo項目を返すルートを定義します。
app.get('/api/todos/:id', (req, res) => {
const { id } = req.params;
const todoId = parseInt(id);
if (isNaN(todoId)) {
res.status(400).send(`Invalid id ${id}`);
}
const todo = todos.find((todo) => todo.id === todoId);
if (todo) res.status(200).send(todo);
res.status(404).send(`Todo with id ${id} not found`);
});Code language: JavaScript (javascript)仕組み。
まず、オブジェクトを分割代入して、req.paramsオブジェクトからIDを取得します。
const { id } = req.params;Code language: JavaScript (javascript)次に、ID値を整数に変換します。IDが数値でない場合は、エラーメッセージとともにHTTPステータスコード400で応答します。
const todoId = parseInt(id);
if (isNaN(todoId)) {
res.status(400).send(`Invalid id ${id}`);
}Code language: JavaScript (javascript)3番目に、IDを持つToDoを見つけ、JSONとしてクライアントに返します。
const todo = todos.find((todo) => todo.id === id);
if (todo) res.send(todo);Code language: JavaScript (javascript)最後に、IDを持つToDoが見つからない場合は、HTTPステータスコード404を返します。
res.status(404).send(`Todo with id ${id} not found`);Code language: JavaScript (javascript)すべてをまとめる
以下に、完成したindex.jsモジュールを示します。
import express from 'express';
import { todos, nextTodoId } from './todos.js';
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/api/todos/', (req, res) => {
if (req?.query?.completed) {
const isCompleted = req.query.completed === 'true';
const filteredTodos = todos.filter(
(todo) => todo.completed === isCompleted
);
res.send(filteredTodos);
}
res.send(todos);
});
app.get('/api/todos/:id', (req, res) => {
const { id } = req.params;
const todoId = parseInt(id);
if (isNaN(todoId)) {
res.status(400).send(`Invalid id ${id}`);
}
const todo = todos.find((todo) => todo.id === todoId);
if (todo) res.status(200).send(todo);
res.status(404).send(`Todo with id ${id} not found`);
});
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});
Code language: JavaScript (javascript)Expressルーティングのサンプルソースコードをダウンロードする
まとめ
- エンドポイントとは、クライアントがリソースにアクセスしたり、操作関数を実行したりするために使用できる特定のURL(またはパス)とHTTPメソッドを指します。
- ルートは、アプリケーションが特定のエンドポイントにどのように応答するかを定義します。
- ルートを定義するには、Express appオブジェクトのメソッドを使用します。