HerokuでExpressアプリを作る---基本設定

# この記事の内容
HerokuでExpressを作るための方法、この記事では基本的な設定を説明する

- 環境整備
- 静的(HTTP)サーバー
- APIサーバー : リソースとアクセスログの監視

までを実例を挙げて紹介する

## 環境整備
herokuへの登録とherokuのCLIツール群のインストール[^herokuCLI]は割愛する。

### yarnとgitの初期化
```shell-session
$ yarn init
%% 様々な入力
$ yarn add express
$ git init
$ echo "/node_modules/" > .gitignore
```
このようにgitとyarnを初期化しておき、最低限のモジュールの追加と`.gitignore`の設定をしておく

#### エントリーポイント(index.js)
```js:index.js
const path=require('path');
const express=require('express');
const app=express();

// ポートはheroku用の環境変数とローカル用の手動を設定しておく
app.set('port', process.env.PORT || 5050);
// '/public/'以下を静的ファイルの置き場所に指定
app.use(express.static(path.join(__dirname, 'public')));

app.listen(app.get('port'), ()=>{ console.log("Node app is running at localhost:" + app.get('port')); });
```

これで`public/index.html`に`Hello World`を置いておくとindex.jsを起動させておいてブラウザでアクセスすると表示される。

#### 起動ファイルProcfile
herokuではデプロイされるとProcfileを読み起動する。

```text:Procfile
web: node index
```
とするとデプロイと同時に`node index`が走ってサーバーが起動する。

#### herokuにアプリを作って起動

```shell-session
$ heroku login
%% E-mailアドレスを入れる
%% パスワードを入れる
$ heroku create $APPNAME %% APPNAMEが作られる
$ git add .
$ git commit -a -m 'Commit All Files'
$ git push heroku master
```

でデプロイされ起動する。

## APIサーバーとして使う
httpサーバーだけならExpressを使う必要も何ないのでAPI(JSON)サーバーとして使ってみる。
適当なJSONデータを用意して帰すだけならほぼhttpサーバーと変わらないので動的にデータを作ってみる。

### リソースを見る
メモリ使用量とcpu使用量を監視する、それぞれ[process.memoryUsage](https://nodejs.org/api/process.html#process_process_memoryusage)や[process.cpuUsage](https://nodejs.org/api/process.html#process_process_cpuusage_previousvalue)を使う。
`src/log/usage.js`に本体を`src/log.js`にモジュールを書く

```js:src/log.js
const usage=require('./log/usage');
const access=require('./log/access');

const log={
    usage: usage,
    access: access,
}

module.exports=log;
```
```js:src/log/usage.js
onst histories=[];
const min=1;

setInterval(()=>{ histories.push({ date: new Date(), memory: process.memoryUsage(), cpu: process.cpuUsage() }) }, 1000*60*min);

const usage={
    get: ()=>{ return histories; },
}

module.exports=usage;
```
として1分ごとのメモリ使用量とcpu使用量をログにためておく

### アクセスログ
リソースの使用量の他にアクセスログもとっておく、

```js:src/log/access.js
const log=[];

const access={
    add: (req, res, next)=>{
        log.push({ date: new Date(), method: req.method, path: req.path,
                   ip: req.ip,
                   proxyIP: req.ips,
                   userAgent: req.headers['user-agent'] });

        next();
    },

    get: ()=>{ return log; }
}

module.exports=access;
```
IPアドレスは`req.ip`にProxyを使った場合のIPアドレスは`req.ips`に配列として記録されている[^express-ip]。
`headers[user-agent]`[^user-agent]にはユーザーエージェント(多分、クライアントと同じもの)が文字列として入っている。
addはExpressのミドルウェアにセットして使うためにRequestとResponse、それと次に送るための関数nextを引数として受け、処理が終わるとnextを呼ぶ。

### エントリーポイントの変更
以上のAPIを使えるようにエントリーポイント`index.js`に以下を追加する。

```js:index.js
app.use(log.access.add); // accessログに記録するためのミドルウェア

// JSON形式でリソースログを返すAPI
app.get('/log/usage', (req, res)=>{ res.send(log.usage.get()) }); 
// JSON形式でアクセスログを返すAPI
app.get('/log/access', (req, res)=>{ res.send(log.access.get()) }); 
```
とすることでアクセスすればJSON形式として値を返す。

## あとがき
これでhttpサーバーとして使いつつAPIサーバー(動的にJSON形式データを返すサーバー)として使える設定が一応できた。
実際にはHTML,CSSやクライアント側JS、サーバー側もきちんと整備する必要がある(こんな重要な情報がダダ漏れのサーバーはありえないが練習用として使った)。



[^express-ip]: (参考)[expressモジュールによるHTTPサーバ（３）クライアントに関する情報の取得 ](http://info-i.net/express-client-info)
[^user-agent]: (参考)[node.jsでuser agentからできるだけ詳しい情報を得る](http://blog.nakayuki.net/programming/node-js-ua-parse/)、文字列解析はしない。

[^herokuCLI]: Ubuntuではaptにある、他のLinuxディストリビューションやMacも同様だろう