概要
API連携でテストする必要があって、Node.jsで、モックサーバーを書いたんだけど、かなりコードが見づらいし、使いにくかった。
気軽に使えるように、標準モジュールで書いたんだけど、いまいちで、expressとかは高機能なので、気軽に使えるルーティング機能をつくってみた。
Dockerなくても動きますが、おまけで書いてます。
開発環境
- Windows 11
- Docker Desktop
- Node.js 12
フォルダ構成
- 作業フォルダ
- server.js
- router.js
- public フォルダ
|- test.html 静的ファイルのサンプル
Httpモジュールの基本
内容を理解するための、基本となるコードです。
localhostの8080ポートにアクセスすると、「Hello World」が表示されます。
リクエストとレスポンスがわたってくるコールバック関数を追加していく感じです。
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World');
});
server.listen(8080);
本当はコールバック関数内で、urlのパスを取得して分岐しながら処理を記載していきます。
コード
ルーティングのコードです。
機能は、主に、ルーティング機能です。getとpostメソッドのコールバック関数を登録、静的ファイルの読み込みなどです。静的ファイルは、ルーティングに登録されていないURLで、「public」フォルダ配下にあれば読み取ります。
「bodyParser」は、POSTのリクエストボディをreq.bodyに埋め込みます。
router.js
var parser = require('url');
var fs = require('fs');
var handlers = {};
exports.get = (url, handler) => {
handlers["GET/"+url] = handler;
}
exports.post = (url, handler) => {
handlers["POST/"+url] = handler;
}
exports.route = (req) => {
var url = parser.parse(req.url, true);
var handler = handlers[req.method+"/"+url.pathname];
if (!handler) handler = this.missing(req);
return handler;
}
exports.missing = (req) => {
var url = parser.parse(req.url, true);
var path = __dirname + "/public" + url.pathname
try {
var data = fs.readFileSync(path);
mime = req.headers.accepts || 'text/html'
return (req, res) => {
res.writeHead(200, {'Content-Type': mime});
res.write(data);
res.end();
}
} catch (e) {
return (req, res) => {
res.writeHead(404, {'Content-Type': 'text/plain'});
res.write("No route registerd for " + url.pathname);
res.end();
}
}
}
exports.bodyParser = (req) => {
return new Promise((resolve, reject) => {
if (req.method !== 'POST') {
resolve();
return;
}
var data = '';
req.on('data', (chunk) => {
data += chunk.toString();
})
req.on('end', () => {
try {
req.body = JSON.parse(data);
} catch (e) {
req.body = {};
}
resolve();
});
req.on('error', (e) => {
reject(e);
});
});
}
server.js
createServerのコールバック関数で、ルーティングの処理を追加します。内容はコメント
// server.js
const http = require('http');
const router = require('./router'); // routerを読み込み
router.get('/', (req, res) => { // httpメソッドが「GET」、パスが「/」を登録
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<html><body>Hello World!</body></html>')
});
const server = http.createServer(async (req, res) => {
await router.bodyParser(req); // POSTパラメータ対応
const handler = router.route(req); // 登録済みの関数を取得(ルーティング)
handler(req, res); // 関数の実行
});
// start server on port 8080
server.listen(8080);
実行
server.jsを実行します。
node server.js
chromeなどのブラウザでURLを開きます。
http://localhost:8080/
おまけ
Dockerfile
FROM node:12
# アプリケーションディレクトリを作成する
WORKDIR /usr/src/app
# アプリケーションのソースをバンドルする
COPY . .
EXPOSE 8080
CMD [ "node", "server.js" ]
コメント