Subscribed unsubscribe Subscribe Subscribe

HerokuでRedisを使ってNodeアプリのセッション管理

何となくHerokuももうちょっと触ってみようと思ってチョロっと調べていて
Getting Started on Heroku with Node.js | Heroku Dev Center
を読んでいたら、Postgresを使う場合とRedisを使う場合のやり方が書いてあったのでRedisを少し使ってみた。
どうやらHerokuのaddonsとして簡単にRedis To GoのRedisサービスと繋げることができるようで、自分でRedis To Goの方に登録して設定したりしなくても使えるようになるらしい。
まずは

$ heroku addons:add redistogo

と叩くが、Accountがverifyされていないと使えない、ようなエラーメッセージが出てきたのでhttps://api.heroku.com/accountからクレジットカード情報など登録。登録しても無料プランで使うことも出来る…ということですよね?
で、登録したら無事にaddonsが使えるようになった。知らなかったけどRedis To Goってnanoという無料プランがあったんですね…

$ heroku addons | grep redis
redistogo:nano
$ heroku config
PATH          => bin:node_modules/.bin:/usr/local/bin:/usr/bin:/bin
REDISTOGO_URL => redis://redistogo:************************************@pike.redistogo.com:****/

みたいにREDISTOGO_URLという環境変数が追加されるようなので、これを利用して繋ぐことになる。
Node.jsの場合、その環境変数をparseしてくれて簡単に繋ぐためのredis-urlっていうモジュールがあり、またHeroku環境でconnect-redisでsession管理するためのconnect-heroku-redisなんていう特化したモジュールまでnpm上にあがってる。しかしredis-urlはpasswordとdatabaseがvar宣言されてなくてglobal化されてしまうぞ…微妙。。(※追記: pull req送ったらすぐに取り込んでもらえました。)
とりあえずそのへんのモジュールに頼らずにconnect-redisだけ使ってexpressでredistogoに繋いでセッション使えるようにするものを書いてみた。雛形は

$ express -s hoge

で作ったもの。package.json

{
    "name": "hoge",
    "version": "0.0.1",
    "private": true,
    "dependencies": {
        "connect-redis": ">=1.0.7",
        "express": "2.4.6",
        "jade": ">= 0.15.4"

    }
}

というかんじで

/**
 * Module dependencies.
 */

var express = require('express');
var app = module.exports = express.createServer();
var RedisStore = require('connect-redis')(express);

// Configuration
app.configure(function () {
    var url = require('url');
    var parsed_url  = url.parse(process.env.REDISTOGO_URL || 'http://localhost:6379');
    var parsed_auth = (parsed_url.auth || '').split(':');

    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(express.cookieParser());
    app.use(express.session({
        secret: 'your secret here',
        store: new RedisStore({
            host: parsed_url.hostname,
            port: parsed_url.port,
            pass: parsed_auth[1]
        })
    }));
    app.use(app.router);
    app.use(express['static'](__dirname + '/public'));
});

app.configure('development', function () {
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function () {
    app.use(express.errorHandler());
});

// Routes
app.get('/', function (req, res) {
    var hoge = req.session.hoge || 0;
    console.log(hoge++);
    req.session.hoge = hoge;
    res.render('index', {
        title: 'Express'
    });
});

app.listen(process.env.PORT || 3000, function () {
    console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});

と書いてdeployしてみたら、とりあえず動いた。