RailsのセッションをJSONで
Railsのセッション情報はこちらの記事にあるように、RubyのMarshalでシリアライズされ、Base64エンコードされたものがクッキーなどに保存される。
ただ、Ruby以外では復元が難しいため、Node.jsなど別言語で書かれたサーバーアプリケーションとセッションを共有しづらい。
なので、こちらの記事を参考にJSONで保存できるようにしてみた(というかほとんどそのまま)。
セッション情報の保存先にはredis-storeライブラリを使ってRedisに保存する。
redis-storeは、RubyGemsにあがっているものだとRails4で動かない(Rails3でもredisライブラリのバージョンが新しいと動かない)。
GitHubを見てみたら、forkされたものが最近のRackのバージョンアップ含めてRails4対応していたので、それを使う。
Gemfile
gem 'redis' gem 'redis-store', github: 'bricker/redis-store' gem 'redis-rails', github: 'bricker/redis-store'
config/initializer/session_store.rb
require 'action_dispatch/middleware/session/redis_store' # # デフォルトだとRubyのMarshalでセッションオブジェクトを保存するため、Node.js側で扱えない # JSONで保存するためにモンキーパッチをあてる # module ActionDispatch module Session class RedisStore # override def get_session(env, sid) with_lock(env, [nil, {}]) do unless sid and session = @pool.get(sid) sid, session = generate_sid, {} unless /^OK/ =~ @pool.set(sid, JSON.generate(session)) raise "Session collision on '#{sid.inspect}'" end end session = JSON.parse(session) unless session == {} if session.has_key?('flash') session['flash'] = ActionDispatch::Flash::FlashHash.new.update(Hash[*session['flash']]) end [sid, session] end end # override def set_session(env, session_id, new_session, options) with_lock(env, false) do jsonize_session = JSON.generate(new_session) @pool.set session_id, jsonize_session, options session_id end end end end end # セッションの生存期間は1週間 Sample::Application.config.session_store :redis_store, servers: { host: "localhost", port: 6379, namespace: "_sessions", db: 10, expire_in: 60 * 60 * 24 * 7 }
redis-store、もう1年くらい更新されてないしissuesもpull reqも溜まってるけど作者の人やる気もうないのかな。。。