別のサーバーにある画像ファイルを、koaで動作しているサービスから渡す必要に迫られました。
そんなときにもkoa。スマートに仕上げてくれます。
コード (sample.js)
var koa = require('koa');
var route = require('koa-route');
var app = koa();
//-- ここから下はcoのサンプルから
var thunkify = require('thunkify');
var request = require('request')
.defaults({ encoding: null }); //←これがミソ!
var get = thunkify(request.get);
//!-- ここまで
app.use(route.get('/hoge.png', function *(){
var url = 'http://www.google.co.jp/images/srpr/logo11w.png';
var img = yield get(url);
this.type = img[0].headers['content-type']; //ヘッダー付ける
this.body = img[1]; //Bufferオブジェクト
}));
app.listen(3000);
実行
node --harmony sample.js
結果
curl -v localhost:3000/hoge.png
もしくは
open http://localhost:3000/hoge.png
(OS X限定)
まとめ
yieldを使った非同期処理を同期っぽくこなす場合はその処理がyieldableである必要があります。
httpをつかったファイルのダウンロードをyieldableな処理で実行するサンプルコードは、koaのベースとなるCoのReadmeに書いてあります。
今回はそちらの利用方法を参考にさせてもらいました。
Coにあるサンプルコードのままでは、バイナリデータを扱うようなことはできません。
request.getが取得したデータをテキストとして解釈してしまうためです。
それを防ぐために、default({ encoding: null })
とオプションを指定します。
これで正常にバイナリデータをBufferとして扱えるようになります。
JSONオブジェクトを渡した際は、Content-Typeがapplication/json
にセットされていたのですが、今回のようにBufferが渡された場合は、application/octet-stream
がセットされてしまいます。
仕方がないので、this.type
にダウンロードしたファイルのHTTPヘッダ情報から得たContetn-Typeを入れてあげます。
そこまでスマートではないですが、今までのcallback地獄よりはきれいに書けると思います。
koa、使わない手はないでしょう。