express middleware

# express middleware

- [express middleware](http://expressjs.com/en/resources/middleware)

## [body-parser](http://expressjs.com/en/resources/middleware/body-parser.html)

各ハンドラを実行する前に、request ボディを解析して、req.body プロパティで使えるようにする

- 使い方

```
var app = require('express')();
var bodyParser = require('body-parser');

app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json({type: "application/*+json"}));
```

- json parser
    - リクエストされたデータがjson形式にする。req.body で参照可能。
    - typeプロパティを指定することで、解析を実行する Content-type を指定できる。

- raw parser
    - リクエストされたデータをBuffer形式にする。

- text parser
    - リクエストされたデータを文字列にする。

- urlencode parser
    - リクエストされたデータをurlencodeする。


## [express-session](http://expressjs.com/en/resources/middleware/session.html)

セッション管理




## [express-flash](https://www.npmjs.com/package/express-flash)

セッションにフラッシュメッセージを保存するミドルウェア  

```
var cookieParser = require('express-parser');
var session = require('express-session');
var flash = require('express-flash'); # 設定（この設定をするとrequestにflash()メソッドが追加される）
var app = require('express');

app.use(cookieParser());
app.use(session({
  secret: "hogehoge",
  resave: true,
  saveUninitialized: true,
  cookie: {Maxage: 60000},
}));
app.use(flash());

# 使用
# 値付きでコールするとセッションに保存される
//index.ejs
<% if (messages.index) { %>
<%= messages.index %>
<% } %>

app.get("/", function(req, res, next){
    res.render("index");
});
app.get("/flash", function(req, res, next){
    req.flash("msg", "this is flash message!");
    res.redirect("/");
});

# キーのみでセッションの値を取得できる。
app.get("/getvalue", function(req, res, next){
    // flashメソッドをコールするとクッキーから削除される
    res.render("index", {"msg": req.flash("msg")});
});
```


## [cookie-parser](http://expressjs.com/en/resources/middleware/cookie-parser.html)  

クッキーを処理するためのミドルウェア  

```
# 設定（この設定をするとrequestにcookiesプロパティが追加される）
var cookieParser = require('cookie-parser');
var app = require('express');
app.use(cookieParser());
// app.use(cookieParser('signed')); // 署名付きクッキーを使う

# 使用
app.get("/", function(req, res, next){
    console.log('Cookies:' + req.cookies);
});
```


## [multer](http://expressjs.com/en/resources/middleware/multer.html)

ファイル（multipart/form-data）を処理するミドルウェア

- 初期設定
    - dest: ファイルを保存するフォルダ(DiskStorageタイプになる) 
    - storage: multer.diskStorage() or multer.MemoryStorage()
    - fileFilter: アップロードを許可するファイルの種類を指定する
    - limits: アップロードのサイズ制限
    - preservePath: ファイル名だけでなくフルパスを保持する

- multerのメソッドは以下のメソッドを実行することで、middlewareになる。
    - single(fieldname): 1ファイルのみ。req.file に保存される
    - array(fieldname [, maxCount]): 配列指定の複数ファイル。req.files に保存される
    - fields(fields): フィールド名指定の複数ファイル。req.files に保存される
    - none  : ファイルがアップロードされた場合、LIMIT_UNEXPECTED_FILE を出してエラーにする
    - any   : 

- アップロードファイルオブジェクト(req.file | req.files)は以下のプロパティを持つ
    - fieldname: フォームで指定したフィールド名
    - originalname: ユーザ環境下のファイル名
    - encoding: ファイルのエンコードタイプ
    - mimetype: ファイルのMIMEタイプ
    - size: ファイルのバイトサイズ
    - destination: 保存されるフォルダ（DiskStorageタイプのとき）
    - filename: サーバ上のファイル名（DiskStorageタイプのとき）
    - path: サーバ上フルパス（DiskStorageタイプのとき）
    - buffer: 全ファイルのBuffer（MemoryStorageタイプのとき）

```
var express = require("express");
var app = express();
var multer = require("multer");

// 設定
var upload = multer({
     // dest と storageはどちらか指定
    dest: "./upload",
    // storage: multer.diskStorage() or multer.memoryStorage(),
    fileFilter: function(req, file, callback){
        // ここでファイルの確認処理をして

        callback(null, true);     // このファイルをアップロードする場合
        // callback(null, false); // このファイルをアップロードしない場合
    },
    limits: {
        fieldNameSize: 100, // フィールド名
        fieldSize: 1024000, // フィールド名の値(1MByte)
        fields: Infinity,   // ファイル以外のフィールド数
        fileSize: Infinity, // ファイルのサイズ(multipart forms)
        files: Infinity,    // fileフィールドの数(multipart forms)
        parts: Infinity,    // フィールドとファイルの数(multipart forms)
        headerPairs: 2000,  // ヘッダーのキーと値のペアの数(multipart forms)
    },
    preservePath: true,
});

// storageを指定する場合
var storageOpt = multer.diskStorage({
    // どこに保存するかを決定
    destination: function(req, file, callback) {
        callback(null, "/tmp/uploads");
    },
    // ファイル名をどうするか？
    filename: function(req, file, callback) {
        callback(null, file.fieldname + '-' + Date.now());
    }
});
var upload = multer({
    storage: storageOpt,
});

// single() /////////////////////////////////////////////////////////////////
app.get("/file", function(req, res, next){
    res.send("
    <form method="POST" action="/file" enctype="multipart/form-data">
        ファイルをアップロードしてください。
        <input type="file" name="filename">
        <input type="submit" value="upload">
    </form>
    ");
});

app.post("/file",
    upload.single("filename"), // filename: POSTしたファイルのnameプロパティ
    function(req, res, next) {
        console.log(req.file);
        fs.rename(req.file.destination + "/" 
            + req.file.filename, req.file.destination 
            + "/" + req.file.originalname, (err) => {
            if (err) return next(err);
            res.send("uploaded [{req.file.originalname}] as [{req.file.filename}] " 
              + "Size: [{req.file.size} Bytes]<br>"
              + "encoding is [{req.file.encoding}] and "
              + "[mimetpye is {req.file.mimetype}]<br><br>");
        });
    }
);

// array() /////////////////////////////////////////////////////////////
app.get("/file", function(req, res, next){
    res.send("
    <form method="POST" action="/file" enctype="multipart/form-data">
        ファイルをアップロードしてください。
        <input type="file" name="filename">
        <input type="submit" value="upload">
    </form>
    ");
});
app.post("/multifile", 
    upload.array("filenames[]"), // filename: POSTしたファイルのnameプロパティ
    function(req, res, next) {
        // req.files はアップロードファイルオブジェクトの配列になる
        console.log(req.files);
        var str = "";
        req.files.forEach(val => {
            str += formatFileObj(val);
            fs.rename(
                val.destination + "/" + val.filename, 
                val.destination + "/" + val.originalname, 
                (err) => {
                    if (err) return next(err);
                }
            );
        });
        res.send(str);
    }
);

// fields() /////////////////////////////////////////////////////////////
app.get("/file", function(req, res, next){
    res.send("
    <form method="POST" action="/fieldsfile" enctype="multipart/form-data">
        複数ファイルをアップロードしてください。<br>
        <input type="file" name="foo"><br>
        <input type="file" name="bar"><br>
        <input type="submit" value="upload">
    </form>
    ");
});
app.post("/fieldsfile", 
    upload.fields([
        {name: "foo", maxCount: 1}, // filename: POSTしたファイルのnameプロパティ
        {name: "bar", maxCount: 1},
    ]), 
    function(req, res, next) {
        // req.files はnameプロパティをキーとする辞書ファイルになる。値はアップロードファイルオブジェクト。
        console.log(req.files);
        var str = "";
        Object.keys(req.files).forEach(function(key){
            req.files[key].forEach(val => {
                str += formatFileObj(val);
                fs.rename(
                    val.destination + "/" + val.filename,
                    val.destination + "/" + val.originalname,
                    (err) => {
                        if (err) return next(err);
                    }
                );
            });
        });
        res.send(str);
    }
);

// エラー処理する場合 ///////////////////////////////////////////////////////////////
router.post("/file",
   function(req, res, next) {
        var singleupload = upload.single("filename");
        singleupload(req, res, function(err) {
            if (err) return next(err);

            console.log(req.file);
            console.log(req.body);
            fs.rename(req.file.destination + "/" + req.file.filename, req.file.destination + "/" + req.file.originalname, (err) => {
                if (err) return next(err);
                res.send(formatFileObj(req.file));
            });
        });
   }
);

```