public
Description: OUTDATED mirror of Rack's darcs repository, use github.com/chneukirchen/rack
Homepage: http://rack.rubyforge.org/
Clone URL: git://github.com/chneukirchen/rack-mirror.git
rack-mirror / lib / rack / session / cookie.rb
100644 72 lines (59 sloc) 2.136 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
module Rack
 
  module Session
 
    # Rack::Session::Cookie provides simple cookie based session management.
    # The session is a Ruby Hash stored as base64 encoded marshalled data
    # set to :key (default: rack.session).
    #
    # Example:
    #
    # use Rack::Session::Cookie, :key => 'rack.session',
    # :domain => 'foo.com',
    # :path => '/',
    # :expire_after => 2592000
    #
    # All parameters are optional.
 
    class Cookie
 
      def initialize(app, options={})
        @app = app
        @key = options[:key] || "rack.session"
        @default_options = {:domain => nil,
          :path => "/",
          :expire_after => nil}.merge(options)
      end
 
      def call(env)
        load_session(env)
        status, headers, body = @app.call(env)
        commit_session(env, status, headers, body)
      end
 
      private
 
      def load_session(env)
        request = Rack::Request.new(env)
        session_data = request.cookies[@key]
 
        begin
          session_data = session_data.unpack("m*").first
          session_data = Marshal.load(session_data)
          env["rack.session"] = session_data
        rescue
          env["rack.session"] = Hash.new
        end
 
        env["rack.session.options"] = @default_options.dup
      end
 
      def commit_session(env, status, headers, body)
        session_data = Marshal.dump(env["rack.session"])
        session_data = [session_data].pack("m*")
 
        if session_data.size > (4096 - @key.size)
          env["rack.errors"].puts("Warning! Rack::Session::Cookie data size exceeds 4K. Content dropped.")
          [status, headers, body]
        else
          options = env["rack.session.options"]
          cookie = Hash.new
          cookie[:value] = session_data
          cookie[:expires] = Time.now + options[:expire_after] unless options[:expire_after].nil?
          response = Rack::Response.new(body, status, headers)
          response.set_cookie(@key, cookie.merge(options))
          response.to_a
        end
      end
 
    end
  end
end