Node.js学んでみた ~その① 簡易サーバー作成編~


【今回お世話になったサイト】
https://www.sejuku.net/blog/72566
http://gihyo.jp/dev/serial/01/nodejs/0001
http://uraway.hatenablog.com/entry/2015/11/03/node.js%E3%81%A7web%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%92%E7%AB%8B%E3%81%A6%E3%82%8B%E3%81%BE%E3%81%A7%E3%82%92%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B
https://www.sejuku.net/blog/71663
https://www.tech-tech.xyz/nodejs-readfile-readfilesync.html
https://nodejs.org/api/process.html#process_process

最近鉄板屋に行った時ふと「鉄板ネタの鉄板ってなんで鉄板？」と思って調べたら、
鉄板が堅い＝手堅い　って感じらしいです。ダイヤモンド板でもいいじゃん、と思いました。

本題。
いつもお世話になっているNode.jsをしっかり学びたい欲があります。
メモがわりに学んだことをまとめます。

##REPL
**REPL**は`Read-eval-print loop`の略です。
Node.jsの対話実行環境だとか。
Node.jsを落とした状態のターミナルで、`node`を押すと開始します。
ここでNodeを使えちゃう！
終了するときは`Ctrl+Cです。


##ファイルから実行する
age.jsというファイルを作成し、以下のように記述します。

```javascript:age.js
const number = process.argv[2] || 0;
console.log(`あなたは${number}歳ですね。`);
```
nodeは`process.argv[2]`でコマンドラインの引数を取得してくれます。
なぜ引数が２なのかというと、0はnodeコマンドファイルのパス、1は実行中のファイルのパスが入るらしいです。

そしてコマンドラインで以下のようにぽちぽちすれば...

```
node src/js/age.js 100  //"あなたは100歳ですね。"と出力される
```
おおー！
初Node.js成功です。（パス部分はファイルを作った場所によって異なります。）

##Webサーバーが作れる！
【httpレスポンス、httpリクエストについて】
https://itsakura.com/network-http-get-post
【MIMEタイプについて】
https://qiita.com/NoxGit/items/6808bf539ce8fb713532

この辺を学んでる前提で以下のようにやります。

```javascript

var http = require('http');
var server = http.createServer(function(request,response){
  response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});
  response.end('hello,world');
})

server.listen(8080);
```


###var http = require('http')
nodeでは`require`でモジュールを読み込む、ということをします。
普段webpackなんかでお世話になってます。
ここでは`require('http')`での登場です。

###http.createServer
`http.createServer`はイベントハンドラーの設定です！JSJSしてますね。
ここにリクエストが来た時のイベントを記述していきます。

###response.writeHead
`response.writeHead`っていうのはレスポンスのヘッド部分に色々記載していくメソッドになります。
強制で200,つまり成功にして、MINEタイプをhtmlに指定している、というところでしょうか。

###response.end
ここはhttpレスポンスのボディ部分に記載してくれるメソッドです。
みんな大好きhello,worldを入れました。

###そして伝説へ...
`server.listen(8080)`でサーバーが待ち受け状態になります。
このファイルを保存し、ターミナルで先ほどのように読み込み（今回引数なし）、
http://localhost:8080/ に接続するとhello,worldがひょっこり表示されます。
すごい!簡単！

【追記】
ちなみに上記コードですが、下記のように書き換えることもできます。
requestイベントによって発火できるということですね。

```javascript
var server = http.createServer()
server.on('request' , (request, response) => {
  var data = 'Hello World'
  response.writeHead(200, {
    'Content-Type': 'text/plain'
  })
  response.write(data, 'utf8')
  response.end()
})
server.listen(8080)
```



##HTMLファイルの読み込み

```javascript
var http = require('http');
var html = require('fs').readFileSync('src/index.html')
var server = http.createServer(function(request,response){
  response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});
  response.end(html);
})

server.listen(8080);
```

###require('fs').readFileSync('src/index.html')
fsモジュールはファイルの読み書きや削除などを取りまとめてるモジュールになります。
ファイルの読みには主に二種類あって、
`readFile`は非同期処理で読み込みをしてくれます。Nodeっぽいですね。
一方で`readSyncFile`は同期処理になります。
（ちなみにパスはファイルの置き場所によって異なります）

そしてこのjsを読み込んでhttp://localhost:8080/ に接続すると...
おお、準備したindex.htmlが読み込まれています。（感動....)

##GetかPostか

```javascript:
var http = require('http');
var html = require('fs').readFileSync('src/index.html')
var server = http.createServer(function(request,response){
  response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});

  if(request.method =='GET'){
    console.log('GETです');
  }
  response.end(html);
})

server.listen(8080,'127.0.0.1');
```
`request.method`でGET/Methodを判別することができます。
このコードだと、GETの時にターミナルに"GETです"と表示されます。
POSTも同様に分岐できます。

##例外処理について
このままのコードだと例外が起きた時にサーバーごと落ちてしまいます。例外処理を覚えます。
まず知らないといけなかったのが`process.on`について。これは`addEventListener`に似ています。

```javascript
process.on('uncaughtException', (e) => console.log(e));
```
`process`はnodeの状態なんかを保持するグローバルオブジェクトらしいです。
`uncaughtException`が例外がキャッチされない時に発動するイベントで、その時の処理をコールバック関数で登録していますね。

しかしこれだけの処理だとリクエストを投げたままなので、数分経ったらやっぱり切れてしまうらしい。

例外処理といえば`try~catch`ですが、非同期処理ではうまくいかないので、`domain`というのを使います。

```javascript
const domain = require('domain');
const server = http.createServer((req, res) => {
  var d = domain.create();
  d.on('error', (e) => {
    res.statusCode = 500;
    res.end(e);
  });
  d.run(() => action(req, res));
});
```
(https://naosim.hatenablog.jp/entry/zero_server 様よりコード引用）
やっぱりサーバー周りはめっちゃ大変ですね。次回はライブラリの学習なんかもできればと思います。


##ついで話①:server.listenについて
`listen`メソッドは以下の構文になっています。
第二引数にホストを指定できるんですね。

```javascript
server.listen(setting.port,setting.host)
```


【次回】
[Node.js学んでみた ~その② ルーティング編~](https://qiita.com/irico/items/1beb6ccf8479b12d7065)