🍈
(ほぼ) パケ無しNode.jsでAPI
なんの記事?
ほぼ素のNode.jsでDBと疎通して、データをIOするシンプルなWebAPIを実装しました
- 使ったライブラリ:
pg(Postgresクライアント) - Expressなどは利用せず
APIの構成
- ヘルスチェック + AWSのサービスをDBに登録、一覧、詳細API表示する
- GET /health
- GET /aws-services
- GET /aws-service/{id}
- POST /aws-service
- やらないこと
- 認証の実装
- ORMの選定
- 画面側の実装
ディレクトリ構成
- 📁ROOT
- 📝compose.yaml コンテナ定義。appフォルダをマウントする
- 📁app
- 📝package.json
- 📝server.js HTTPサーバ本体
- 📁api
- 📝route.js パスで下位フォルダに振り分け
- 📁health
- 📝handler.js : HTTPメソッドなどで振り分けて、executerに投げる
- 📝executer.js: 関連する処理を📁dbに投げる
- 📁aws-service
- 📝handler.js
- 📝executer.js
- 📁db
- 📁aws-service: aws-serviceテーブルのDAO
- 📁health: DAOはないが、healthチェックの一環でテスト接続する
- 📝connection.js DBコネクションのハンドリング
- 📝core.js SQL実行
- 📁util 雑多な処理
工夫したところ
📁app/api配下
route.jsがトップレベルのパスの振分を責務とさせた
- 配下の<domain>フォルダへ処理を投げてあげる
- healthとaws-serviceが対象
domainフォルダは handler と executer で構成することで関心を分離させる
- handler はHTTPメソッドとセカンドレベル以降のドメインの振分を責務とし、適切なexecuterを実行する
- executer は dbフォルダに処理を投げる
- dbフォルダへの事前/事後処理を責務とする
- 実装していないが、validationがあったらこの辺りで処理させるといい感じかも
📁app/db配下
SQLの組み立てとSQL実行で責務を分けたい & DRYにしたかったので、
core.js#runSQLにコネクションのやり取りとSQLの実行を任せ、各DAOはSQLの構築に集中させた。
SQL組み立ては可能な限り1ファイル1SQLにすることで関心を分離できてそう
HTTP POST の処理
素のNode.jsだとHTTP POSTでbodyが受け取れなかった!
streaming でいい感じにできそうだったので、以下の処理を実装。
GET時には処理させたくないのでPromiseで書き、
合わせたほうがきれいだったのでPOSTもPromiseで実装した。
const readPostBody = (req) => {
if (req.method !== "POST") {
return Promise.resolve({});
}
return new Promise((resolve, reject) => {
let body = "";
req.on("data", (chunk) => {
body += chunk.toString(); // Convert Buffer to string
});
req.on("end", () => {
try {
resolve(JSON.parse(body)); // Parse JSON string to object
} catch (error) {
reject(new Error("Invalid JSON format"));
}
});
req.on("error", (error) => {
reject(error);
});
});
};
所感
やっぱりフレームワークないと実装が煩雑に散らかるなあという気持ち。
とはいえ、素に近い状態でのNodejs x HTTPサーバに関する知見が増えたのはうれしい🙌
WebFramework n本ノック
Discussion