はじめに
本記事の目的
Node.jsを利用してWEB APIサーバを立ち上げたい。
Node.jsに画面サーバを担わせることもできるが、画面側はReactで作成したいので、今回はWEBサーバとして基本的なAPIを提供するところまでを目標とする。
(※一般的に、画面サーバとして利用するときは、ejsなどのテンプレートエンジンを利用する必要がある。)
前提
- Node.jsとnpm(Node.jsのパッケージマネージャ)がインストールされていること。
前提の補足
今回は Vagrant(Linux仮想サーバ)上に立ち上げたdockerコンテナ上で作業している。
以下記事の通りdockerコンテナを起動し、コンテナ上で作業している。
docker-composeを利用してdockerコンテナを作成する方法メモ(複数コンテナ対応) - エンジニアを目指す日常ブログ
Node.jsでHTTPサーバを立ち上げる方法(Express不使用)
Node.jsにはデフォルトでHTTPサーバを立ち上げる機能が備わっている。 概念としての理解するため、モジュールを使わずにやってみる。
通常はExpressのモジュールを利用することが多いので、実践では使わなそう。
プロジェクトを作成する
プロジェクトフォルダ(今回はbackend-practice-2
)で、
$ npm init
を実行する。このコマンドによって、package.json
が作成される。
対話型で各種設定をする。今回はpackage nameとentry pointのみ設定した。
- package name:
backend
- entry point:
app.js
package name: (app) backend
version: (1.0.0)
description:
entry point: (index.js) app.js
test command:
git repository:
keywords:
author:
license: (ISC)
app.jsの作成と動作確認
プロジェクトフォルダbackend-practice-2
内にapp.js
を作成する。
console.log("動作確認。");
動作確認のため、コンソール上でapp.js
を実行してみる。
$ node app.js
動作確認。
無事にapp.js
が実行された。
HTTPサーバの作成
app.js
に以下を記載する。
// httpモジュールを呼び出す
const http = require("http");
// ポート番号を設定
const portNumber = 8000;
// サーバーインスタンスを作成
const server = http.createServer();
// onメソッドでリクエスト時の挙動を設定
server.on("request", (req, res) => {
res.writeHead(200, { "Content-Type": "text-plain" });
res.write("Hello world");
res.end();
});
// listenメソッドで待ち受け状態を作る
server.listen(portNumber);
// コンソールにポート番号を表示
console.log(`PortNumber is ${portNumber}`);
メソッドの説明
require()
require()
は、モジュール(関数)を呼び出すメソッド。
今回はhttpモジュールを呼び出して、http
という変数に設定した。
http.createServer()
http.createServer( )
でサーバーインスタンスを生成する。
// 基本構文:
const server = http.createServer();
ここで、server
はhttp.Server
クラスのインスタンスとなる。
引数には、サーバーでリクエストを受け取った時の処理を関数として設定することもできる。以下の2つの記述は同じに意味になるとのこと。
const server = http.createServer( (req, res)=>{
処理
});
const server = http.createServer();
server.on('request', (req, res) => {
処理
});
server.on()
リクエストを受け付けたときに実行する処理を設定できる。
on()
は、Node.jsのメソッドで、各クラスが持つイベントを関数で設定できる。
on()
の第一引数で指定したイベント発生後、第二引数の関数を実行する。
Server
クラスのイベントとして"request"
イベントがあり、以下の記載は"request"
イベントに対して処理を設定している。
server.on("request", (req, res) => {
処理
});
第二引数には関数を設定している。req
はリクエストの中身を表し、res
はレスポンスする内容を示す。
ここで、req
はhttp.IncomingMessage
クラスのインスタンスであり、res
はhttp.ServerResponse
クラスのインスタンスである。
server.listen()
サーバが実際に、指定のポートで待機状態になり、リクエストを受け付けられるようになる。
server.listen(ポート番号)
res.writeHead()
http.ServerResponse
クラスのメソッドとして、writeHead()
がある。
HTTPレスポンスのヘッダーを設定できる。
res.writeHead(HTTPステータスコード, ヘッダーオブジェクト);
res.write()
同じくhttp.ServerResponse
クラスのメソッドである。
Body部に設定する内容を記載する。
res.write(内容)
res.end()
同じくhttp.ServerResponse
クラスのメソッドである。
レスポンスへの書き込みが完了したことを示す。
res.end()
引数に、Body部に設定する内容を記載することもできる。
// 例:
res.end(ok)
同じ内容を短く書いた場合
先ほどは丁寧に記載したが、一般的には単純なWEBサーバを作成するときは以下の記載が多くなっている。
server
を変数せずに記載することができる。
const http = require("http");
const portNumber = 8000;
http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Hello World");
}).listen(portNumber);
HTTPサーバの動作確認
Nodeを実行する。
$ node app.js
PortNumber is 8000
ブラウザから確認しても良いし、
HTTPリクエストツールから確認しても良い。(今回はPostman)
JSONを返却できるか
APIサーバとして利用したいので、JSONが返却できるか試してみた。
しかし単純にres.end()
の引数にオブジェクトを入れると、エラーが返却された。
http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "application/json" });
res.end({id: "1", name: "Taro"});
}).listen(portNumber);
エラーメッセージ:
Error: socket hang up
Expressを利用してHTTPサーバを立ち上げる
Expressとは
Webアプリケーション開発向けのフレームワーク。ルーティングやレスポンスの整形ができる。
公式ホームページ
https://expressjs.com/ja/4x/api.html
Expressのインストール
Expressをインストールする。
$ npm install express --save
HTTPサーバの作成
プロジェクトを作成するの手順を実施していない場合は、実施すること。app.jsをExpressを利用して書き換える
// expressをrequireする
const express = require("express");
// ポート番号を変数に設定
const portNumber = 8000;
// appオブジェクトを作成する
const app = express();
// getメソッドで、ルートパスにアクセスしてきたときの処理を記載する
app.get("/", (req, res) => {
res.status(200).send("Hello World");
});
// リクエストを待ち受ける
app.listen(portNumber);
console.log(`PortNumber is ${portNumber}`);
メソッドの説明
express()
便利なメソッドを持つオブジェクトを作成することができる。
const app = express();
app
はインスタンスと言ってよいのか?その場合のクラスは何になるのか。公式ドキュメントを読んでも良くわからなかった…。
app.get()
GETメソッドのリクエストを受けた場合の処理を記載できる。
app.get("/", (req, res) => {
処理
});
"/"
は、パスを示している。この場合はルートを記載しているのでlocalhost:8000
となる。2つめの引数は処理を表す。
このとき、server
のrequest
イベントの時と同様、req
はhttp.IncomingMessage
クラスのインスタンスであり、res
はhttp.ServerResponse
クラスのインスタンスである。
そのためres.write
やres.writeHead
も処理中で利用できる。
res.status
HTTPステータスを設定できる。
//例
res.status(200).send('<p>文章</p>');
res.status(400).send('Bad Request');
res.send()
Body部に設定したい内容を記載する。
// 例
res.send('<p>文章</p>');
res.send({ user: 'tobi' });
res.send([1, 2, 3]);
動作確認
先ほどと同様に動作確認。
$ node app.js
PortNumber is 8000
問題なくレスポンスが返ってきた。
JSONを返却できるか
app.js
を書き換えて、app.send()
の中にJSONを記載してみた。
app.get("/", (req, res) => {
res.status(200).send({ id: 1, message: "メッセージ" });
});
今度は正常に返却された。
Content-Typeは自動的にapplication/json
となっていた。
app.json()
app.send()
のほかに、app.json()
というメソッドもあり、こちらを使ってもよさそう。
app.end()
Expressを利用した場合は、app.end()
はBody部に何も返却しないときにだけ利用すれば良いとのこと。
こちらの説明がわかりやすかった。
POSTリクエストを送った場合
今回、GETメソッドを受け取った場合の処理のみ設定したので、POSTメソッドでリクエストした場合は404エラーが返却される。
おわりに
できたこと
Node.js + Express でサーバを立ち上げ、JSONでレスポンスを返却することができた。
まだできていないこと
- DBから値を取得する
- ルーティング
参考資料
こちらのUdemy講座をベースに勉強した。
https://www.udemy.com/course/web-application-with-nodejs-express/
関連記事
つづき
モジュールの作成方法
https://tomiko0404.hatenablog.com/entry/2021/10/24/Nodejs-module
テンプレートエンジン(ejs)を利用してHTMLを返却する
https://tomiko0404.hatenablog.com/entry/2021/10/21/Nodejs-ejs
ミドルウェアの作成
https://tomiko0404.hatenablog.com/entry/2021/10/25/nodejs-middleware
画面サーバとWEBサーバを利用して通信させる
https://tomiko0404.hatenablog.com/entry/2021/10/31/front-to-web-server-cors