Router-Line はじめました
4/18 に開催された 東京Node学園 5時限目 で @KOBA789 さんが自作のルータである Router-Line を紹介していました。
その時から便利そうとは思っていたのですが、最近ちょっとした API サーバを書く時に実際に Router-Line を使ってみて、改めて良いなと思ったので、サンプルを見せながら、個人的に便利だと思う使い方を紹介します。
Router-Line とは
github で「A URL routing module for Node.js」と書いてある通り、Router-Line はシンプルな URL ルータで、それ以外の機能は持っていません。サーバを構築するには Node.js の http モジュールなどと組み合わせて使う必要があります。
個人的には API サーバのルーティングには、Express (Connect) を使うより、すっきりかけて、速度も速いので合っていると感じています。
致命的な欠点は、サンプルがないこと、ですかね、はい。ドキュメントがほぼ皆無で、最初どうやってサーバと組み合わせるか悩みました。自分はテストコード読んで理解しましたが、初心者にはお勧めできない、的な雰囲気になってしまっているのがとても勿体無い。(ので、この記事を書きました)
Router-Line 事始め
Router-Line を利用した API サーバの雛形を書くと以下のようになります。
var http = require('http'), url = require('url'), Router = require('router-line').Router; var router = new Router(); function send(res, status, contentType, body) { res.writeHead(status, { 'Content-Type': contentType }); res.end(body); } /* * ここからルーティングの設定 */ router.add('GET', '/', function (req, res) { res.end('hello world'); }); // ここまでルーティングの設定 /* * HTTP サーバと連携させる。以下は個人的に使っているテンプレートコード。 */ var app = http.createServer(function (req, res) { var uri, r, handler; uri = url.parse(req.url, true); r = router.route(req.method, uri.pathname); if (r) { req.param = function (key) { return r.params[key] ? r.params[key] : uri.query[key]; } handler = r.value; if (typeof handler === 'function') { handler(req, res, r.params); } else if (typeof handler === 'string') { send(res, 200, 'text/plain', handler); } else { send(res, 200, 'application/json', JSON.stringify(handler)); } } else { send(res, 404, 'application/json', JSON.stringify({ reason: 'This not the URL you are looking for' })); } }); app.listen(process.env.PORT || 3000); console.log('Server listen on port %d', app.address().port);
Router-Line の基本
Router の作成
Router = require('router-line').Router; var router = new Router();
普通ですね。今回は1つしか使いませんが、何個でも作れます。
Routing Handler の設定
// HTTP メソッドを指定する add メソッド router.add('HTTP メソッド名(GET|POST|PUT|DELETE)', 'マッチさせる URL', Routing Handler [function, string, object なんでも OK]); // 全HTTP メソッドを一括指定できる ANY メソッド router.ANY('マッチさせる URL', Routing Handler [function, string, object なんでも OK]);
基本的には add() しか使わない。というか、add() しか使ったことない。
router.add('GET', '/', function (req, res) { res.end('index'); });
これを取得するには Router.route() メソッドを使います。
var app = http.createServer(function (req, res) { var uri, r, handler; uri = url.parse(req.url, true); r = router.route(req.method, uri.pathname);
URLに一致する handler がない場合は undefined が返ります。
URLに一致する handler がみつかった場合、params, value というプロパティを持った Object が返ります。
{ params: { Path parameter の解析結果 object }, value: { add()/ANY() で設定した handler object } }
以上です。簡単ですね。
応用編
Path Parameter を使う
コロン (:) で始まる文字列は Path Parameter として解析されます。例えば、以下の様な感じです。
/* * pathParams には route().params の結果が入っている。 */ router.add('GET', '/users/:user/apps/:app/:id', function (req, res, pathParams) { send(res, 200, 'application/json', JSON.stringify(pathParams)); });
これに対して "/users/user1/apps/app2/3" でアクセスすると、
{"user":"user1","app":"app2","id":"3"}
が返ります。実際に動作するサンプルを heroku においておきましたので、色々と URL を変えて試してみてください。 サンプル。
Path Parameter だけど、一部 Option パラメータを指定
URL を括弧で囲むとその部分は省略可能なパラメータとして解析されます。例えば以下。
router.add('GET', '/items/:item(/type/:type)', function (req, res, pathParams) { send(res, 200, 'application/json', JSON.stringify(pathParams)); });
これに対して "/items/item1" でアクセスすると、
{"item":"item1"}
こうなって、"/items/item1/type/small" でアクセスすると、
{"item":"item1","type":"small"}
まとめ
なんとなく Node.js なら Express 的な風潮が見受けられますが、API サーバ(画面なし、form から POST なし) を書くなら Router-Line を検討してみても良いと思います、というか Router-Line お勧めです。