expressのres.format()メソッドを使うと、railsのrespond_toみたいに、レスポンスのContent-Typeごとに実行する処理を分けることがきる。
(コンテントネゴシエーターとか呼ばれる機能らしい。)
app.get('/hoge.:format', function(req, res) {
res.format({
json: function(req, res) {
res.send({a: 1});
},
html: function(req, res) {
// ブラウザから /index.json にアクセスしてもこっちが実行される
res.render('index');
},
default: function(req, res) {
res.send(406);
}
});
});
上記のように書けば良いのだけど、このタイプの判定は、リクエストのAcceptヘッダを元に判定しているらしく、ヘッダがついていないと、たとえURLが /hoge.json
だったとしても、jsonの処理が実行されない。
良いやりかたかどうかさだかではないけど、下記の容量で、expressのレスポンスタイプ判定メソッドを拡張すると、:formatという名前のパラメーターがついていた場合は考慮されるようになる。
var __accepts = express.request.accepts;
express.request.accepts = function(type) {
var format = this.params.format
, i;
if (util.isArray(type)) {
for (i = 0; i < type.length; i++) {
t = type[i];
if (type[i] === format) {
return type[i];
}
}
} else if (type === this.params.format) {
return type;
}
return __accepts.call(this, type);
};
var __is = express.request.is;
express.request.is = function(type) {
return this.params.format === type || __is.call(this, type);
};
app.param() とかの便利機能もあるけど、ヘッダを書き換えずにやるにはこういう方法しか思いつかなかった。