Node.jsでシンプルなhttpサーバを構築

## httpとは
WebサーバとWebブラウザの間でWebの情報を受け渡しするときに使う約束事(プロトコル)のこと。

## httpサーバとは
Webブラウザから要求されたリクエスト(「あのページをおくれ」)に対し、レスポンス(「どうぞ、このページだよ」)を返却するサーバのこと。(＝Webサーバと一緒)
httpでやりとりするサーバなのでhttpサーバと呼ばれることがあるものの、基本的にWebサーバーと同じと考えて良いはず。

## 作るもの
 localhost:3000で待機するwebサーバ。

 仕様: 画面のロード時に表示されるフォームのinput内に名前を入力し、submitすると'Hello <名前>！'が表示される

## 手順
まずはモジュールの読み込みから
httpモジュールはhttpサーバを構築する上で必要な機能を提供するモジュールで、Node.jsがインストールされていれば利用可能。
```
const http = require("http");
```

httpサーバの構築はcreateServer()メソッドを使用。
ここではリクエストを受け取った際に行う処理を記述する。
```
const server = http.createServer((request, response) => {

});
```
ファイルの最後で待機状態にするポートを指定する。今回は3000番を指定。
```
server.listen(3000);
```

ここまでで大枠が整った。
現状で一旦`node <ファイル名>`でコードを実行してしてみる。
ブラウザからlocalhost:3000を開くと、ページがぐるぐると読み込み中になっており、portがlistenされているのがわかる。

では改めて、http.createServerの中身を記述していく。

まず'画面のロード時に表示されるフォーム'を実現する。
urlにアクセスされた際、inputフォームを画面に表示するためのHTMLファイルを返却するため、レスポンスヘッダのContent-Typeに "text/html"を指定する。

```
const server = http.createServer((request, response) => {
    response.writeHead(200, {
      "Content-Type": "text/html"
    });
});
```
画面がロードされた際のパスは'/'なので、その際にフォームを返却するよう指定する。
```
const server = http.createServer((request, response) => {
    response.writeHead(200, {
      "Content-Type": "text/html"
    });
    if ('/' == request.url) {
      response.end(`
        <form action="/login" method="POST">
        <input type="text" name="name">
        <input type="submit">
        </form>
      `)
    }
});
```
ここで再度コードを実行すると以下のような画面が表示できる。
![スクリーンショット 2023-07-17 21.07.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472670/0f0daca5-4e1e-fead-71d1-8cd581dc3f49.png)
現在はactionで指定している/loginに何も用意していないので、送信しても応答待ち状態となる。

今度は送信ボタンが押された後の処理を記述する。
送信ボタンが押されるとurlが'/login'となるため、以下の処理を追記。

```
    if ('/' == request.url) {
      response.end(`
        <form action="/login" method="POST">
        <input type="text" name="name">
        <input type="submit">
        </form>
      `)
    }
    else {
      if ('/login' == request.url && 'POST' == request.method) {
           //ここに受け取ったデータを処理する記述を書いていく
      }
    }
```

受け取ったデータを処理するには`reqest.on(イベント名, 関数);`を使用する必要があり、
 - data: クライアントからデータを受け取った際に発生するイベント
 - end: データの受け取りが完了した際に発生するイベント

上記二つのイベントを用いて送信された内容を画面に反映させる。

まずはdataイベントで画面から受け取ったデータをdata変数に格納していく。

```
  else {
    if ('/login' == request.url && 'POST' == request.method) {
      let data = "";
      let view = "";  //後で表示用に使う変数の初期化
      request.on("data", function (_argdata) {
        data += _argdata;
      });
    }
  }

```

次にendイベントで渡ってきたdataをURLSearchParamsを利用してオブジェクト形式に変換し、nameを取り出す。
```
     request.on("end", function() {
       const params = new URLSearchParams(data);
     })
```
そして得た値をview用に加工する。

```
      request.on("end", function() {
        const params = new URLSearchParams(data);
        view += '<p>Hello '+ params.get('name') + '</p>';
      })
```
最後に加工したviewの値をレスポンスとして画面に返却する。
```
      request.on("end", function() {
        const params = new URLSearchParams(data);
        console.log(params.get('name'));
        view += '<p>Hello '+ params.get('name') + ' !</p>';
        response.end(view);
      })
```
コードの全体としては下記となった。
```javascript
const http = require("http");

const server = http.createServer((request, response) => {
  response.writeHead(200, {
    "Content-Type": "text/html"
  });
  if ('/' == request.url) {
    response.end(`
      <form action="/login" method="POST">
      <input type="text" name="name">
      <input type="submit">
      </form>
    `)
  }
  else {
    if ('/login' == request.url && 'POST' == request.method) {
      let data = "";
      let view = "";
      request.on("data", function (_argdata) {
        data += _argdata;
      });
      request.on("end", function() {
        const params = new URLSearchParams(data);
        console.log(params.get('name'));
        view += '<p>Hello '+ params.get('name') + '</p>';
        response.end(view);
      })
    }
  }
});

server.listen(3000);

```

## 動作確認
フォームの送信後の表示: 
![スクリーンショット 2023-07-18 0.32.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472670/27c46714-8508-269d-5d39-13d809b54d92.png)