エンジニアを目指す日常ブログ

日々勉強したことのメモ。独学ですので間違っていたらコメント等で教えてください。

Node.js + Express でWEB-APIサーバを作成する

はじめに

本記事の目的

Node.jsを利用してWEB APIサーバを立ち上げたい。

Node.jsに画面サーバを担わせることもできるが、画面側はReactで作成したいので、今回はWEBサーバとして基本的なAPIを提供するところまでを目標とする。
(※一般的に、画面サーバとして利用するときは、ejsなどのテンプレートエンジンを利用する必要がある。)

また、今後、DBと連携したり、docker上で立ち上げる作業も必要になる。

前提

  • Node.jsとnpm(Node.jsのパッケージマネージャ)がインストールされていること。

tomiko0404.hatenablog.com

前提の補足

今回は vagrantLinux仮想サーバ)上に立ち上げたdockerコンテナ上で作業している。(vagrant上でnpmインストールができないバグに見舞われたため。)

以下記事の通りdockerコンテナを起動し、コンテナ上で作業している。 docker-composeを利用してdockerコンテナを作成する方法メモ(複数コンテナ対応) - エンジニアを目指す日常ブログ

Node.jsでHTTPサーバを立ち上げる方法(Express不使用)

Node.jsでHTTPサーバを立ち上げる基本的な方法をメモする。 概念としての理解のために記載。 通常はExpressのモジュールを利用するので、書き方は少し変わってきそう。

プロジェクトを作成する

プロジェクトフォルダ(今回はbackend-practice-2)で、

$ npm init

を実行する。このコマンドによって、package.jsonが作成される。

package.jsonとは
s package.jsonとpackage-lock.json とは?(Node.js/React) - エンジニアを目指す日常ブログ

対話型で各種設定をする。今回は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の作成と動作確認

プロジェクトフォルダにapp.jsを作成する。

app.js

console.log("動作確認。");

動作確認のため、コンソール上でapp.jsを実行してみる。

$ node app.js
動作確認。

無事にapp.jsが実行された。

HTTPサーバの作成

app.jsに以下を記載する。

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();

ここで、serverhttp.Serverクラスのインスタンスとなる。

引数には、サーバーでリクエストを受け取った時の処理を関数として設定することもできる。

const server = http.createServer( (req, res)=>{
    処理
});

と書くのと、

const server = http.createServer();
server.on('request', (req, res) => {
    処理
});

は同じ意味になるとのこと。

参考: HTTP | Node.js v16.11.1 Documentation

server.on()

リクエストを受け付けたときに実行する処理を設定できる。 on()は、Node.jsのメソッドで、各クラスが持つイベントを関数で設定できる。

on()の第一引数で指定したイベント発生後、第二引数の関数を実行する。 Serverクラスのイベントとして"request"イベントがあり、以下の記載は"request"イベントに対して処理を設定している。

server.on("request", (req, res) => {
    処理
});

reqはリクエストの中身を表し、resはレスポンスする内容を示す。

ここで、reqhttp.IncomingMessageクラスのインスタンスであり、reshttp.ServerResponseクラスのインスタンスである。

参考:
HTTP | Node.js v16.11.1 Documentation
Node.js - Node.js onとはなんですか?|teratail

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)

serverインスタンスを変数に入れずに一行で書く書き方

一般的には以下の記載が多くなっている。 serverを変数せずに記載することができる。

app.js

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)

ボディ部の確認
ボディ部の確認

ヘッダ部の確認
ヘッダ部の確認

Postmanの使い方: HTTPリクエストツールPostmanの利用/インストール時のエラー対応 - エンジニアを目指す日常ブログ

JSONを返却できるか

APIサーバとして利用したいので、JSONが返却できるか試してみた。

http.createServer((req, res) => {
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end({"id": 2, "message":"Hello"});
}).listen(portNumber);

しかし、

Error: socket hang up

というエラーが返却された。

Expressを利用してHTTPサーバを立ち上げる

Expressとは

Webアプリケーション開発向けのフレームワーク。ルーティングやレスポンスの整形ができる。

公式ホームページ expressjs.com

Expressのインストール

expressをインストールする。

$ npm install express --save

HTTPサーバの作成

プロジェクトを作成するの手順を実施していない場合は、実施すること。

app.jsをExpressを利用して書き換える

app.js

// 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イベントの時と同様、reqhttp.IncomingMessageクラスのインスタンスであり、reshttp.ServerResponseクラスのインスタンスである。

そのためres.writeres.writeHeadも処理中で利用できる。

res.status

HTTPステータスを設定できる。

//例
res.status(200).send('<p>some html</p>');
res.status(400).send('Bad Request');
res.send()

Body部に設定したい内容を記載する。

// 例
res.send('<p>some html</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: "メッセージ" });
});

今度は正常に返却された。

JSONが返却された
JSONが返却された

Content-Typeは自動的にapplication/jsonとなっていた。

ヘッダ部の返却値
ヘッダ部の返却値

app.json()

app.send()のほかに、app.json()というメソッドもあり、こちらを使ってもよさそう。

公式ドキュメント: Express 4.x - API リファレンス

app.end()

expressを利用した場合は、app.end()はBody部に何も返却しないときにだけ利用すれば良いとのこと。

こちらの説明がわかりやすかった。
Express のレスポンス関連メソッド「res.end()」「res.send()」「res.json()」の違い - Neo's World

POSTリクエストを送った場合

今回、GETメソッドを受け取った場合の処理のみ設定したので、POSTメソッドでリクエストした場合は404エラーが返却される。

404エラー
404エラー

おわりに

できたこと

Node.js + Express でサーバを立ち上げ、JSONでレスポンスを返却することができた。

まだできていないこと

  • DBから値を取得する
  • ルーティング

参考資料

こちらの講座をベースに勉強した。 www.udemy.com

関連記事

つづき

モジュールの作成方法

tomiko0404.hatenablog.com

テンプレートエンジン(ejs)を利用してHTMLを返却する

tomiko0404.hatenablog.com

ミドルウェアの作成

tomiko0404.hatenablog.com

画面サーバとWEBサーバを利用して通信させる