概要
Express(server)から client に HTTP レスポンスを返す際も、
ルーティング(GET / POST / PUT / DELETE)が違っても 毎回ほぼ同じ構造になります。メソッドごとの役割はありますが、
「reqから入力を取り出す → 成功/失敗を判定 → status / Content-Type / body を返す」
という流れは共通フローとして整理できます。
つまり、
- HTTPレスポンスには共通の「骨格(フロー)」がある
- メソッドごとの差分は一部だけ
- 実務では ステータスコード・Content-Type・レスポンスボディ(JSON)を必ず扱う
この記事では、
- Express が client にレスポンスする HTTP処理の共通フロー
- その共通部分を切り出した 実用的な雛形
- GET / POST / PUT / DELETE の 現実的な Express 実装例
を、自分で書けるようになることを目的に整理します。
目次
- HTTPレスポンスの共通フロー
- 共通フローの雛形
- GET レスポンスの雛形
- POST レスポンスの雛形
- PUT レスポンスの雛形
- DELETE レスポンスの雛形
- 各メソッドの違いまとめ
- Express 側との対応関係
- 参考リンク
HTTPレスポンスの共通フロー
HTTPメソッドに関係なく、server(Express)から client にレスポンスする流れは共通しています。
- ルートを受け取る(
app.get/post/put/delete) - 入力を
reqから取り出す(req.query / req.params / req.body) - 入力チェック(不正なら 400)
- 必要な処理を実行する(DB / 配列操作 / 外部API など)
- 成功時のステータスコードを決める(200 / 201 / 204)
- Content-Type を決めてレスポンスボディを返す(JSONなら
res.json()) - 失敗時はステータスコードとエラー内容を返す(例:
{ error: "..." })
この ①〜⑦はすべての HTTP メソッドで共通です。
共通フローの雛形
ここでは、あなたの setupServer() スタイルで、Express 側の共通骨格を用意します。
※「関数化(sendJson/sendError/asyncHandler)」は使いません。
※「チェーン記法(return res.status().json())」も使いません。
const express = require('express');
// 例データ(本来はDBなど)
const messages = [
{ id: 1, text: 'First message from server', time: Date.now() },
{ id: 2, text: 'This is a sample chat line', time: Date.now() },
{ id: 3, text: 'Type something and POST it', time: Date.now() },
];
function setupServer() {
const app = express();
// JSON body を読めるようにする
app.use(express.json());
// 静的ファイル(必要なら)
// app.use('/', express.static('./public'));
// ここに app.get / post / put / delete を定義する
return app;
}
module.exports = { setupServer, messages };
ポイント
- JSON を返すなら
res.json()を使う(基本はこれでOK) -
res.setHeader('Content-Type', 'application/json')は通常不要(res.json()が付ける) -
res.status(200); res.json(...)のように **基本形(分割記法)**で書いてよい
GET レスポンスの雛形
特徴
- データ取得専用
- 条件は
req.query(クエリ)で受け取ることが多い - 成功時は
200 OK
app.get('/api/chat', (req, res) => {
const lastSeenId = Number(req.query.lastSeenId ?? 0);
// 入力チェック
if (Number.isNaN(lastSeenId)) {
res.status(400);
res.json({ error: 'lastSeenId must be a number' });
return;
}
// 取得処理(例:差分だけ返す)
const filtered = messages.filter((m) => m.id > lastSeenId);
// 成功レスポンス
res.status(200);
res.json({ data: filtered });
});
POST レスポンスの雛形
特徴
- 新しいデータを作成する
- 入力は
req.body(JSON)で受け取る - 成功時は
201 Createdが多い
app.post('/api/chat', (req, res) => {
const text = req.body?.text;
// 入力チェック
if (typeof text !== 'string' || text.trim() === '') {
res.status(400);
res.json({ error: 'Cannot send a blank message' });
return;
}
// 作成処理
const newMessage = {
id: messages.length + 1,
text: text,
time: Date.now(),
};
messages.push(newMessage);
// 成功レスポンス(作成した1件を返す)
res.status(201);
res.json({ data: newMessage });
});
PUT レスポンスの雛形
特徴
- 既存データを更新する
- 対象は
req.params.idで受け取る - 更新内容は
req.bodyで受け取る - 成功時は
200 OK(更新後を返す)または204 No Content(返さない)
app.put('/api/chat/:id', (req, res) => {
const id = Number(req.params.id);
const text = req.body?.text;
// 入力チェック
if (Number.isNaN(id)) {
res.status(400);
res.json({ error: 'id must be a number' });
return;
}
if (typeof text !== 'string' || text.trim() === '') {
res.status(400);
res.json({ error: 'text is required' });
return;
}
// 対象検索
const idx = messages.findIndex((m) => m.id === id);
if (idx === -1) {
res.status(404);
res.json({ error: 'message not found' });
return;
}
// 更新処理
const updated = {
...messages[idx],
text: text,
time: Date.now(),
};
messages[idx] = updated;
// 成功レスポンス(更新後を返す)
res.status(200);
res.json({ data: updated });
// 返さないなら(どちらか片方に統一)
// res.status(204);
// res.end();
});
※ PATCH も基本構造は同じ(意味が「部分更新」になるだけ)
DELETE レスポンスの雛形
特徴
- データを削除する
- 対象は
req.params.id - 成功時は
204 No Content(レスポンスボディ無し)が多い
app.delete('/api/chat/:id', (req, res) => {
const id = Number(req.params.id);
// 入力チェック
if (Number.isNaN(id)) {
res.status(400);
res.json({ error: 'id must be a number' });
return;
}
// 対象検索
const idx = messages.findIndex((m) => m.id === id);
if (idx === -1) {
res.status(404);
res.json({ error: 'message not found' });
return;
}
// 削除処理
messages.splice(idx, 1);
// 成功レスポンス(bodyなし)
res.status(204);
res.end();
});
各メソッドの違いまとめ
| 項目 | GET | POST | PUT | DELETE |
|---|---|---|---|---|
| 主な用途 | 取得 | 新規作成 | 更新 | 削除 |
| 入力(req) |
req.query / req.params
|
req.body |
req.params + req.body
|
req.params |
| 成功時 status | 200 | 201 | 200 / 204 | 204 |
| レスポンス body | 多い | 多い(作成結果) | 返す/返さない | 返さないことが多い |
Express 側との対応関係
※ここは 二つの記事で共有のエリアとのことなので、修正・追記せずそのまま貼ってください。
| 対象 | フロントエンド(client) 受信・取得 |
Express(server) 送信・生成 |
補足・意味 |
|---|---|---|---|
| クエリパラメータ |
?id=query を送る |
req.query で受け取る |
主に GET の条件指定 |
| パスパラメータ |
:id を送る |
req.params.id で受け取る |
リソース識別子 |
| リクエストボディ | JSON を送る |
req.body で受け取る |
POST / PUT / PATCH |
| ステータスコード |
res.status で取得 |
res.status() で設定 |
成否・状態の判定 |
| JSONレスポンス |
res.json() で 読む
|
res.json() で 送る
|
JSON API を明示 |
| 任意形式レスポンス |
res.text() / res.blob() / res.arrayBuffer() で 読む
|
res.send() で 送る
|
文字列 / HTML / Buffer 等 |