Node.jsの基本　その２

Node.js備忘録として、書き始めました。その１は[こちら](https://qiita.com/kenjiwilkins/items/b390dc779617eb28b9f7 "Node.jsの基本その１")
今回はほぼexpressの基本みたいな回です。

##HTTP
HTTPはインターネットで支配的なプロトコルです。Node.jsはサーバー側クライアント側双方に適したモジュールを持っています。
Node.jsに興味を持っている人なら多くの場合express.jsというウェブアプリケーションフレームワークが存在するのを知っていると思います。expressはとても便利で僕も一度覚えてしまうともう他へ浮気できなくなってしまいました。koaやhapiなどのオルタナティブも存在しますが、Qiitaにおけるexpress.js記事の数は他の追随を許していませんから、初学者はexpress一択でしょう。
しかし、何にせよ基礎の基礎を知っておくのは大事なことです。ビルトインモジュールであるhttpを使ったサーバーとクライアントの書き方を見てみましょう。
[その１](https://qiita.com/kenjiwilkins/items/b390dc779617eb28b9f7　"Node.jsの基本その１")でも用いたHello Worldの例は最も簡素なNode.jsを用いたHTTPサーバーです。

```javascript:server.js
const http = require('http')
http.createServer((req, res) => {
  res.end("Hello World!")
}).listen(3000, "127.0.0.1")
```

####httpを用いたルーティング

```javascript:server.js
const http = require('http')
const url = require('url').URL
const port = 3000
const hostName = "127.0.0.1"

http.createServer((req, res) => {
  const path = new url(req.url, `http://${hostName}:${port}`)
  if(path.pathname === "/"){
    res.writeHead(200, {'Content-Type': 'text/plain'})
    res.end('This is root page\n')
  } else if(path.pathname === "/about"){
    res.writeHead(200, {'Content-Type': 'text/plain'})
    res.end('this is about page\n')
  } else {
    res.writeHead(404, {'Content-Type': 'text/plain'})
    res.end('404姉さん')
  }

}).listen(port, hostName)

console.log(`Server running at http://${hostName}`)
```

###HTTPクライアント

```javascript:client.js
const http = require('http')

http.get('http://www.google.co.jp', (res) => {
  if(res.statusCode == 200){
    console.log('successful')
  } else {
    console.log('google is down again')
  }
}).on('error', error => {
  console.log(error)
})
```

##Express.js

Express.jsは最も採用率の高いウェブアプリケーションフレームワークです。これさえあればウェブアプリケーションを作成する際、まずほとんどの状況に対応できる機能が備わっています。
まずはインストールしてみましょう。

```console
npm install -g express
```
これで環境のどこでもexpressのジェネレーター機能を使えるようになります。

```console
express [web app name]
```
このコマンドで雛形を作成できます。初学ではどのようなモジュールを用意するべきかわかりやすいでしょう。

####起動
```console
cd [web app name]
npm install
node app.js
```

作成されたアプリのディレクトリを見ていきましょう。(express@4.17.1)
####node_modules
インストールされているモジュールをここに保持しています。
####package.json
ざっくり言えばこのウェブアプリケーションに関しての情報を保持しているファイルです。
####binフォルダ
実行用のファイルを入れるためのフォルダです。
####routes
ルーティング用のフォルダです。RESTfulなAPIを作成する上でルーティングは可視化面でもメンテナンス面でも重要で、ユーザーに関しての処理はすべて/userルートへ認証に関しての処理はすべて/authルートへなど個別のexpress.route関数ファイルを用意するのが良いでしょう。次の項目でより詳しく説明します。
####public
スタイルシートやjavascriptファイル、画像などをこのフォルダに保存してアプリケーションにここを参照させるようにします。例としてはbootstrapやjQuerryなどでしょう。
####views
ビューエンジンに指定された形式の同名ファイルを参照します。express generatorはjadeを使用しています。(個人的には少し可読性が低いにしろejsが好きです)
jadeというのはテンプレートエンジンで、いわば雛形です。動的なウェブページのレンダリングに向いています。

##ウェブアプリケーションにおけるルーティング
ルーターの設定は少なくともNode.jsでウェブアプリケーションを作成するうえでとても重要です。どのHTTPリクエストにどのように処理するかの振り分けがルーティングです。

###HTTPメソッド
Express.jsはルート定義の際にhttpメソッドとパスを組み合わせて使用します。
GET, POST, PUT, DELETE, などなど
手始めにはサーバーからデータを受け取るGETとサーバーへデータを送るPOSTを使用するところからでしょう。

GETとPOSTのリクエストのテストを例を書きますが、それに先立ってexpressのミドルウェアでHTTPリクエストの必要な情報を抽出してくれるbody-parserというモジュールをインストールしましょう。

```console
npm install body-parser
```


```javascript:server.js
const express = require('express')
const bodyParser = require('body-parser')
const server = express()
const port = 3000
server.use(bodyParser.urlencoded({extended:true}))
server.use(bodyParser.json())
//root
server.get('/', (req, res) => {
  res.send('hello world')
})
//about get route
server.get('/about', (req, res) => {
  res.send('about route get request called')
})
//about post route
server.post('/about', (req, res) => {
  console.log('called')
  const requestBody = req.body
  console.log(requestBody)
  res.send(req.body)
})

server.listen(port, () => {
  console.log('server listening on:' + port)
})
```

###ルートにおけるパラメータの扱い方

アプリケーションによってはRESTfulであるためにパスからパラメータを受け取る必要があります。expressにおいてはパスの最後に":[parameter_name]"で定義できます。

```javascript
app.get('/api/users/:id', (req, res) => {
  res.send('受け取ったIDは' + req.params.id + 'です')
})
```

###クエリの扱い方

アプリケーションによってはクエリによる検索機能などを導入する必要があるでしょう。
Expressにおいてはパスに"?[query_parameter_name]=[query_value]"で定義されたHTTPコールを

```javascript
req.query.query_parameter_name
```
でその値を扱うことができます。

```javascript
server.get('/search/', (req, res) => {
  res.send(req.query)
})
```

###Routeを外部モジュールとして扱う

小規模なアプリの構築には必ずしも要るとは限りませんが、可読性の向上のため、たとえばユーザーについての処理はすべて/userのルートへ、認証のための処理はすべて/authのルートへ、それぞれ個別のファイルとしてまとめて大元のapp.jsへエクスポートするのが推奨されるでしょう。

```javascript:route/users.js
var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
  res.send('/users called');
});

router.get('/all', (req, res) => {
  res.send('/users/all called')
})

module.exports = router;
```
このルーターをserver.jsでインポートしましょう

```javascript:server.js
const express = require('express')
const bodyParser = require('body-parser')
const usersRoute = require('./routes/users')
const server = express()
const port = 3000
//users route
server.use('/users', usersRoute)
//root
server.get('/', (req, res) => {
  res.send('hello world')
})

server.listen(port, () => {
  console.log('server listening on:' + port)
})
```

###ビューレンダリング
先程からずっと例に使っているres.send()という関数は受け取った値をテキスト及びHTMLとしてクライアントへ送ります。
その他に例えばres.json()という関数は受け取った値を有効なJSONファイルの形式で送信します。
res.render()という描画されてHTMLを返す関数に用いる、ビューテンプレートは非常に便利な機能です。たとえばブログを作成するとして、記事ごとにHTMLを書くのは冗長ですし非効率です。タイトルや本文のデータを受け取ってどのように当てはめて描画するかの雛形を作っておくことで、"/archives/:article_id" で対応するidの記事タイトルや本文を受け渡しするだけでよくて効率的です。

ビューテンプレートエンジンと呼ばれるものは色々あります。僕は個人的にejsをプロジェクトで使ってきたので覚えがありますが、ここではexpress generatorに用いられているjadeで例を出していきましょう。

まずjadeのモジュールをインストールしましょう

```console
npm install jade
```

次にviewsフォルダを作成しindex.jadeファイルを作成しましょう

```jade:index.jade
doctype html
html
  head
    title Jade Example
  body
    h1 #{message}
```

jadeはインデントセンシティブなので開業とtabによる間隔で階層を形成する必要があり、閉じるためのタグがないHTMLを書いているような感じです。受け渡されたデータは#{}の中で変数名を指定します。

```javascript:server.js
const express = require('express')
const bodyParser = require('body-parser')
const server = express()
const port = 3000
//set jade as its view engine
server.set('view engine', 'jade')
//root path
// render index.jade with message = 'hello world!' 
server.get('/', (req, res) => {
  res.render('index', {message:"Hello World!"})
})

server.listen(port, () => {
  console.log('server listening on:' + port)
})
```

###次へ

その３へ続きます。主にmongoDBに関してになると思います。