Node.jsでWebサーバーを稼働させてHTTPメソッドを確認する

[bootstrap][bootstrap] やら [swagger][swagger] やらに任せっきりで サーバーサイド JavaScript がどこまで行えるかを正しく把握していなかったので、[Node.js][nodejs]の理解の補填がてら覚書ます。

> [Bootstrap · 世界で最も人気のあるフロントエンドフレームワーク][bootstrap]

> [API Documentation &amp; Design Tools for Teams | Swagger][swagger]

> [Node.js とは | Node.js][nodejs]

[bootstrap]: https://getbootstrap.jp/
[swagger]: https://swagger.io/
[nodejs]: https://nodejs.org/ja/about

# ゴール
- Node.jsでのサーバ構築内容を把握する
- HTTPメソッドの定義（& 動確）方法を把握する

# 環境整備

1. [WSL][wsl] を構築します。

   > [WSL を使用して Windows に Linux をインストールする][wsl]

   [wsl]: https://learn.microsoft.com/ja-jp/windows/wsl/install
   - bashの調整はここでは割愛します。
   - 以降コマンドはwslコンソール上のコマンドを指します。  
     （Ubuntuでもそのまま使えるね :smile: ）

1. パッケージマネージャを更新します。

   ```bash
   sudo apt-get update
   sudo apt-get upgrade -y
   ```

1. Node.js をインストールします。

   ```bash
   sudo apt install npm -y
   ```

## ファイルの整備
### package.json

- パッケージマネージャ経由で `express` と `nodemon` をインストールします。

  ```bash
  npm init -y
  npm i express mongoose
  ```

- `scripts` を修正します。

  ```diff
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
  +  "start": "node ./src/server.js",
  +  "server": "nodemon ./src/server.js"
   },
  ```

## src/server.js

- `server.js` を作成します。

  ```bash
  mkdir -p src
  touch src/server.js
  ```

- `server.js` を編集します。（Port: 5000）

  ```javascript
  const express = require("express");
  const port = 5000;
  const app = express();
  app.listen(port, () => {
    console.log(`Server started on port ${port}`);
  });
  ```

## 疎通確認
- package.jsonを開き、
  `デバッグ` を選択し、`server` を選択します。

   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1866227/29df5209-a688-577f-2cf7-2d147bebc50b.png)

- 直接コマンドで稼働させても良いかと。

  ```bash
  npm run server
  ```

   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1866227/07490a17-e669-1384-ee20-ce7182ca2880.png)


# HTTPメソッド

## 応答を返すWebサーバーの作成

- `controller` を作成します。

   ```bash
   mkdir -p backend/controller
   touch backend/controller/todoRoutes.js
   ```

   ```javascript
   const getTodos = (req, res) => {
     res.status(200).json({ message: "Get todos" });
   };
   const setTodo = (req, res) => {
     res.status(200).json({ message: "Set todo" });
   };
   const updateTodo = (req, res) => {
     res.status(200).json({ message: `Update todo ${req.params.id}` });
   };
   const deleteTodo = (req, res) => {
     res.status(200).json({ message: `Delete todo ${req.params.id}` });
   };
   module.exports = {
     getTodos,
     setTodo,
     updateTodo,
     deleteTodo,
   };
   ```

- `routes` を作成します。

   ```bash
   mkdir -p backend/routes
   touch backend/routes/todoRoutes.js
   ```

   ```javascript
   const express = require("express");
   const router = express.Router();
   const {
     getTodos,
     setTodo,
     updateTodo,
     deleteTodo,
   } = require("../controllers/todosController");
   router.route("/").get(getTodos).post(setTodo);
   router.route("/:id").put(updateTodo).delete(deleteTodo);
   module.exports = router;
   ```

- `server.js` を修正します。

  ```diff
    const app = express();
  + app.use("/api/todos", require("./backend/routes/todoRoutes"));
    app.listen(port, () => {
  ```

# 動作確認

<details><summary>curlコマンドを用いる場合</summary>

## 動作方法その1

### 事前準備（[jq][jq]インストール）

  ```bash
  sudo apt install jq
  ```

  > [jq][jq] は、軽量で柔軟なコマンドライン JSON プロセッサです。

  [jq]: https://jqlang.github.io/jq/

  - 今回はレスポンスを見やすく整形するために使います。

### CRUD

  - Create

    ```bash
    curl -X POST http://localhost:5000/api/todos -m 3 | jq
    ```

    ```bash
    {
      "message": "Set todo"
    }
    ```

  - Read

    ```bash
    curl -X GET http://localhost:5000/api/todos -m 3 | jq
    ```

    ```bash
    {
      "message": "Get todos"
    }
    ```

  - Update

    ```bash
    curl -X PUT http://localhost:5000/api/todos/1 -m 3 | jq
    ```

    ```bash
    {
      "message": "Update todo 1"
    }
    ```

  - Delete

    ```bash
    curl -X DELETE http://localhost:5000/api/todos/2 -m 3 | jq
    ```

    ```bash
    {
      "message": "Delete todo 2"
    }
    ```

</details>

<details><summary>test.http を用いる場合</summary>

## 動作方法その2

### 事前準備（[REST Client][rest-client]インストール）

1. 拡張機能で `rest` で検索します。
2. `REST Client` をインストールします。 
  
[rest-client]: https://marketplace.visualstudio.com/items?itemName=humao.rest-client

### CRUD

- ファイル作成
    ```bash
    mkdir -p test
    touch test/test.http
    ```

- ファイル編集
    ```http
    GET http://localhost:5000/api/todos/ HTTP/1.1
    ###
    POST http://localhost:5000/api/todos/ HTTP/1.1
    ###
    PUT  http://localhost:5000/api/todos/1 HTTP/1.1
    ###
    DELETE  http://localhost:5000/api/todos/2 HTTP/1.1
    ```

- 利用手順

  1. `*.http` ファイルを開きます。
  1. `Send Request` を実行します。 

- 利用イメージ
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1866227/6c1707e8-0900-3d36-4bac-e2e6c631d8c5.png)

### FAQ

  - `RequestError: connect ECONNREFUSED 127.0.0.1:5000.` とエラー表示されて動かないんだが？

    |項目|備考|
    |-|-|
    |原因|ドメイン解決できていないためサーバーのポートを通過できてません。|
    |解決方法|ドメイン解決します。<br>具体的には、`C:\Windows\System32\drivers\etc\hosts` に localhost を足します。|
    |解決イメージ|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1866227/92e940d3-1af3-84ed-8f80-000934083cba.png)|

</details>



# 参考
- [Windows Subsystem for Linux - Wikipedia][wsl]
- [How to setup a Node.js server port - DEV Community][25l6]
- [expressjs][expressjs]
- [nodemon][nodemon]

[wsl]: https://ja.wikipedia.org/wiki/Windows_Subsystem_for_Linux
[25l6]: https://dev.to/aneeqakhan/how-to-setup-a-nodejs-server-port-25l6
[expressjs]: https://expressjs.com/ja/
[nodemon]: https://nodemon.io/