ES6過渡期のMithril入門　③WebフレームワークKoaにPOST

#0) 今回は、web連携最初の関門、POST
先人のおかげで、あまり苦労せず。Expressに比べ、モジュール選定の自由が高い分、あちこち調べながらとはなったが。あと、Curlのお勉強も必要となった。

#1) MithrilのPOST関係コードを見る

Mithril黒ムツ本(というらしい)の[サンプル](https://github.com/oreilly-japan/mithril-book-sample)のうち、２章のToDo3を参考にする。
MVVMモデルのMithrilということで、追加ボタンを押した後、
> [View]
- m("input", {onchange: m.withAttr("value", vm.description), value: vm.description()})
-  m("button", {onclick: vm.add}, "追加")
> [ViewModel] 
- vm.add = function (){ ... Todo.save(vm.list())...}
> [Model]
- Todo.save = function...

の順に、メソッドが呼ばれサーバへのPOSTが行われる。Mithtil APIのm.requestを用い、dataコレクションを送付:

```引用元=github.com/oreilly-japan/mithril-book-sample/blob/master/chapter02_tutorial/todo3/client/app.js
// サーバに現在のタスクを送信
Todo.save = function (todoList) {
    var data = todoList.filter(function (todo) { return !todo.done(); });
    m.request({method: "POST", url: "/tasks", data: data});
};
```

受け側のexpressコードは以下:

```引用元github.com/oreilly-japan/mithril-book-sample/blob/master/chapter02_tutorial/todo3/server.js
app.post("/tasks", function (req, res) {
    console.log("post tasks");
    fs.writeFileSync("todo.json", JSON.stringify(req.body));
    res.status(200).end();
});
```
req.bodyはJSONの配列で、これを、fsモジュールより、ローカルファイルのtodo.jsonに書き出している。

m.requestによる呼び出しに対応するcurlは以下:
> curl localhost:8000/tasks -H 'Content-Type: application/json' --data-binary '[{"description":"入力内容","done":false}]'
*cf. Curlどう書くんだっけ?という時は、こちらを参考: [WebAPIリクエスト仕様書としてcurlコマンドのご提案](http://qiita.com/Hiraku/items/dfda2f8a5353b0742271)*

doneは、ToDoのチェックがされたかどうか(true/false)。

#2) KoaでMithrilからのPOSTを受ける。
ということで、上記のcurlリクエストを受けるKoaコードを書いてみる。

まずは、今回の作業に必要となりそうな、Koaのモジュールを改めて導入。
>npm init
>npm install koa koa-router koa-bodyparser koa-json koa-static co-views jade fs --save

このうち、koa-bodyparser がPOSTされたbodyをパースしてくれる。本質コードは、これだけ:

```coffee
router.post '/', (next)->
    fs.writeFileSync "todo.json",JSON.stringify(@request.body)
  yield next

```

curlの--data-binary以下から送付された内容(ここではJSON配列)が、@request.bodyに格納されるので、その内容をファイルに書き出す。

今回から、よく出来たラウター・モジュールとして、koa-routerを導入。
結果、app本体部分は以下のコードに:

```app.coffee
koa = require 'koa'
api = do require 'koa-router'
serve = require 'koa-static'

api.use '/tasks', require './api/tasks' 
#/tasksへのリクエストは./api/task.coffeeにて処理

app = koa()
app
.use do require 'koa-bodyparser'
.use do require 'koa-json'
.use api.routes()
.use api.allowedMethods()
.use serve __dirname + '/static' #静的HTMLは、/static以下に置く。
.listen 3000
```

ToDoタスクの登録・一覧部分のコード:

```./api/task.coffee
router = do require 'koa-router'
fs = require　"fs"

# `POST /tasks` = タスク登録(todo.jsonに書き出し)
router.post '/', (next)->
    console.log "post tasks"
    fs.writeFileSync "todo.json",JSON.stringify(@request.body)
  yield next

# `GET /tasks` = タスク一覧(todo.jsonから読み出し)
router.get '/', (next)->
    console.log "get tasks"
    docs =  JSON.parse fs.readFileSync("todo.json", "utf8")
    @body = docs
    yield next

module.exports = router.routes()
```

koa-routerのおかげで、コードも適切にモジュール化され、めでたしめでたし。
・・・で終わりにしたかったのだが、router.post～yield nextだけでは、タスク一覧の更新をよろしくやってくれないらしい(ブラウザ画面をリフレッシュすると、更新されたタスク一覧が表示される)。このあたり、Mithril側の責務だと思うが、次回への宿題とする。

#3) 次回以降
Mithrilとkoa-routerの組み合わせをマスターすると共に、mongodbあたりへの永続化を行う。
ここまでできたら、全体をgithubに上げることとしたい。

koa-routerとKoaでのmongoの扱いについては、先人:[koaでjsonwebtokenを使っていい感じに認証する](http://qiita.com/endaaman/items/1282e688970675cc77dd)が、自前認証モジュール含め、かなりいい感じ。Thanks！