Node.js+ExpressでWebAPIサーバを作ってみた

2021/10/18

(最終更新: 2022/11/03

アイキャッチ画像

はじめに

本記事の目的

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

Node.jsに画面サーバを担わせることもできるが、画面側はReactで作成したいので、今回はWEBサーバとして基本的なAPIを提供するところまでを目標とする。

(※一般的に、画面サーバとして利用するときは、ejsなどのテンプレートエンジンを利用する必要がある。)

前提

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

Node.jsのインストール方法メモ

Node.jsのインストールを実施したので方法をメモ。

https://bunsugi.com/node-js-install

前提の補足

今回は Vagrant(Linux仮想サーバ)上に立ち上げた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を作成する。

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クラスのインスタンスとなる。

引数には、サーバーでリクエストを受け取った時の処理を関数として設定することもできる。以下の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はレスポンスする内容を示す。

ここで、reqhttp.IncomingMessageクラスのインスタンスであり、reshttp.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を変数せずに記載することができる。

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)

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

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

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を利用して書き換える

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つめの引数は処理を表す。 このとき、serverrequestイベントの時と同様、reqhttp.IncomingMessageクラスのインスタンスであり、reshttp.ServerResponseクラスのインスタンスである。

そのためres.writeres.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部に何も返却しないときにだけ利用すれば良いとのこと。

こちらの説明がわかりやすかった。

https://neos21.net/blog/2019/03/12-01.html

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

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

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



個別連絡はこちらへ→Twitterお問い合わせ

プロフィール

プロフィールイメージ

はち子

事業会社のシステム部門で働きはじめて5年目の会社員。システム企画/要件定義/システムアーキテクチャ等。

Twitter→@bun_sugi

過去の記事について

はてなブログに掲載の記事(主にプログラミングメモ)についてはこちらに掲載しております。(本ブログに移行中)

タグ一覧

関連記事

Copyright© 2023, エンジニアを目指す日常ブログ

お問い合わせ|プライバシーポリシー