Webの勉強はじめてみた その23 〜HTTPサーバー編〜

N予備校「プログラミング入門Webアプリ」を受講しています。
今回は第3章12〜15節です。

<h2>HTTPサーバー</h2>
`node.js`のモジュールを使ってサーバーを立てる

```javascript
'use strict';
const http = require('http');
const fs = require('fs');
        
const server = http
  .createServer((req, res) => {
    const now = new Date();
    console.info(`[${now}] Requested by ${req.socket.remoteAddress}`);
    res.writeHead(200, {
      'Content-Type': 'text/html; charset=utf-8'
    });

    switch (req.method) {
      case 'GET':
        //res.write('GET ' + req.url);
        const rs = fs.createReadStream('./form.html');
        rs.pipe(res);
        break;
      case 'POST':
        res.write('POST ' + req.url);
        let rawData = '';
        req
          .on('data', chunk => {
            rawData = rawData + chunk;
          })
          .on('end', () => {
            console.info('[' + now + '] Data posted: ' + rawData);
            const decoded = decodeURIComponent(rawData);
            console.info(`${now} 投稿: ${decoded}`);
            res.write(
              `<!DOCTYPE html>
              <html lang='ja'>
                <body>
                  <h1>${decoded}が投稿されました</h1>
                </body>
              </html>`
            );
            res.end();
          });
        break;
      default:
        break;
    }
    //res.end();
  })
  .on('error', e => {
    console.error('[' + new Date() + '] Server Error', e);
  })
  .on('clientError', e => {
    console.error('[' + new Date() + '] Client Error', e);
  });
const port = 8000;
server.listen(port, () => {
  console.info('[' + new Date() + '] Listening on ' + port);
});
```

<h3>http.createServerメソッド</h3>
request: クライアントからの要求
resoponse: リクエストを受けてサーバーが返す内容
`res.WriteHead`: レスポンスするヘッダー情報
`res.end`: レスポンスの終了。必須。 
`req.socket.remoteAddress`: クライアントのIP情報
`req.headers`: クライアント側の情報

<h3>ロギング</h3>
:::note
ログレベル: ログの意味づけ。出力したい情報を明確にする。
:::

`console.info`
標準出力。普段から残しておきたい情報
`console.warn`
標準エラー出力。 警告。問題となる可能性がある情報に使う。
`console.error`
標準エラー出力。 エラー。直ちに対応が必要な情報に使う。

<h3>エラーログ</h3>
:::note
ハンドリング: 自分が操作可能な状態(コントロールできる状態)にすること。
:::

`server`オブジェクトに対して`on`メソッドでエラー時の処理を登録する。

```javascript
.on('error', e => {
    console.error('[' + new Date() + '] Server Error', e);
  })
  .on('clientError', e => {
    console.error('[' + new Date() + '] Client Error', e);
  })
```

<h4>リダイレクトのファイル記述子</h4>
:::note
0: 標準入力
1: 標準出力
2: 標準エラー出力
:::

`2>&1` の意味するところがこれでようやく。

<h4>teeコマンド</h4>
コンソールとファイルの両方に出力
`node index.js 2>&1 | tee -a application.log`

<h3>pipeメソッド</h3>
`fs`モジュールの`createReadStream`メソッドを利用。
指定したパスのページを読み込む準備をする。

:::note
Node.js では Stream の形式のデータは、読み込み用の Stream と書き込み用の Stream を繋つないでそのままデータを受け渡すことができる。
:::

読み込んだStreamをhttpサーバーのレスポンスに渡す。

```javascript
const rs = fs.createReadStream('./form.html');
rs.pipe(res);
```

なお、`pipe`は`res.end`を内部的に実行している。

<h3>URLエンコード</h3>
POSTされたデータはurlエンコードされた状態で送信されるので、`decodeURIComponent`を使って元の値に戻す。
また、`querystring`モジュールの`parse`メソッドでクエリを配列に格納できる。

```javascript
const decoded = decodeURIComponent(rawData);
const qs = require('querystring');
const answer = qs.parse(decoded);
```

<h2>まとめ</h2>
ここまでやっておいてですが、ApacheとHTTPサーバーって同じもの？
Apacheはどちらかといえばソフトウェアになるんだろうか。
今回サーバーとやりとりするにあたって、改めて`Node.js`ってすごいと思った。PHPでやってたことがJavaScriptでできるのかって。
さて、次回はPUGを使って色々やるみたいです。