しかしRack::Session系のライブラリで、現在のセッションID取得をどうやるかについてはドキュメントに分かりやすく書いておらず、探しにくかったです。(Rack::Session::Cookieの場合のみ、セッションのデータ自体にセッションIDが格納されるようですが、それ以外ではIDは入りません。)結局ソースコード読んで見つけました。結論から先に言いますと、
env['rack.session'].id
で取得できます。SinatraやPadrinoを使っている場合はもっと簡潔に
session.id
でOKです。(Sinatraにおけるsessionメソッドはrequest.sessionを呼びだします。Rack::Request#sessionは@env['rack.session']を返します。Sinatraにおけるenvメソッドはインスタンス変数@envへのアクセサですので、結局同じことになります。)
なお、今回(メインで)参照したソースコードはこれ↓。
https://github.com/rack/rack/blob/master/lib/rack/session/abstract/id.rb
上記URLにはRack::Session::Abstract::SessionHashとRack::Session::Abstract::IDの定義が書かれています。
ここにセッションIDを取得していそうなメソッドを発見。Rack::Session::Abstract::ID#current_session_id です。こいつを定義している部分で、
def current_session_id(env) env[ENV_SESSION_KEY].id end
とやってますね。ちなみにRack::Session::Abstractモジュールの冒頭の方で
ENV_SESSION_KEY = 'rack.session’.freeze
と定義されてます。よって、env[‘rack.session’].idを呼べばセッションIDが取得できるとわかります。
なお、env[‘rack.session’]の中身は何かというと、Rack::Session::Abstract::ID#prepare_session で
env[ENV_SESSION_KEY] = session_class.new(self, env)
としてまして、ここでsession_classが何かといえば、Rack::Session::Abstract::ID#session_class の定義が
def session_class SessionHash end
となってます。要するに、env[‘rack.session’]に入っているのはRack::Session::Abstract::SessionHashのインスタンスなのでした。ちなみに、アプリケーション中で p env[‘rack.session’] などとするとハッシュに見える結果が返ってきますが、これは inspect メソッドが定義されているからです。
def inspect if loaded? @data.inspect else "#<#{self.class}:0x#{self.object_id.to_s(16)} not yet loaded>" end end
インスタンス変数@data はハッシュですので、 inspect した結果がハッシュになるのですね。(Kernel.#p は内部的にObject#inspect を呼びます。)
ついでに、Rack::Session::Abstract::SessionHash#id を見てみますと
def id return @id if @loaded or instance_variable_defined?(:@id) @id = @store.send(:extract_session_id, @env) end
となってまして、セッションIDはRack::Session::Abstract::SessionHashのインスタンス変数@idに保持されていることがわかります。
※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうぞ。
※2014/05/22更新:Rack::Session::Cookieの場合のみ、セッションのデータ自体にセッションIDが格納される点について追記。
※2014/06/04更新:SinatraやPadrinoの場合のより簡潔な書き方を追記。
0 件のコメント:
コメントを投稿