1 # This file is part of the Enkel web programming library.
3 # Copyright (C) 2007 Espen Angell Kristiansen (espeak@users.sourceforge.net)
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 from enkel
.cookie
import Cookie
, get_cookies
20 from enkel
.session
.backend
import NoSuchSessionError
23 class StartResponseWrapper(object):
24 """ Used by SessionMiddleware. """
25 def __init__(self
, start_response
, cookie
):
26 self
.start_response
= start_response
29 def __call__(self
, status
, headers
, exc_info
=None):
30 headers
.append(self
.cookie
.get_httpheader())
31 return self
.start_response(status
, headers
, exc_info
)
34 class SessionMiddleware(object):
35 """ A session middleware.
39 >>> from enkel.wansgli.apptester import AppTester
40 >>> from enkel.session.memory import MemorySession
42 >>> def myapp(env, start_response):
43 ... start_response("200 OK", [("Content-type", "text/plain")])
44 ... session = env["enkel.session"]
45 ... if "num" in session:
46 ... session["num"] += 1
48 ... session["num"] = 0
49 ... return ["This is call number %(num)d to this app" % session]
51 >>> class MyBackend(MemorySession):
52 ... def generate_sid(self):
56 >>> sessionapp = SessionMiddleware(myapp, b)
58 >>> AppTester(sessionapp).run_get().body
59 'This is call number 0 to this app'
61 >>> t = AppTester(sessionapp)
62 >>> t.set_env("HTTP_COOKIE", "sid=xxAb")
64 'This is call number 1 to this app'
66 @cvar ENV_KEY: The environ key used to contain the session.
68 ENV_KEY
= "enkel.session"
69 def __init__(self
, app
, backend
, cookiename
="sid",
70 cookiedomain
=None, cookiepath
="/"):
72 @param app: A WSGI application.
73 @param backend: A session backend following the
74 L{enkel.session.backend.SessionBackend} interface.
75 @param cookiename: The name of the session cookie.
76 @param cookiedomain: See L{enkel.cookie.Cookie.domain}.
77 @param cookiepath: See L{enkel.cookie.Cookie.path}.
80 self
.backend
= backend
81 self
.cookiename
= cookiename
82 self
.cookiedomain
= cookiedomain
83 self
.cookiepath
= cookiepath
85 def __call__(self
, env
, start_response
):
87 # import info from cookie
88 cookies
= get_cookies(env
)
90 if cookies
and self
.cookiename
in cookies
:
92 sid
= cookies
[self
.cookiename
]
97 session
= self
.backend
.load(sid
)
98 except NoSuchSessionError
:
103 sid
= self
.backend
.generate_sid()
104 env
[self
.ENV_KEY
] = session
107 cookie
= Cookie(self
.cookiename
, sid
)
108 cookie
.path
= self
.cookiepath
109 cookie
.domain
= self
.cookiedomain
110 cookie
.set_timeout(self
.backend
.timeout
)
113 sr
= StartResponseWrapper(start_response
, cookie
)
114 for buf
in self
.app(env
, sr
):
116 self
.backend
.save(sid
, session
)
122 return doctest
.DocTestSuite()
124 if __name__
== "__main__":
125 from enkel
.wansgli
.testhelpers
import run_suite