Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ session data might be lost at any time! If cookie-only sessions have not been
disabled, then small sessions will still be stored in cookies (this is faster
than memcache).

If you want to exclude certain URLs from session generation use the `ignore_paths`
parameter, which should contain a regular expression. Not generating Cookies is
important in certian HTTP caching scenarios. E.g.

app = SessionMiddleware(app, cookie_key=COOKIE_KEY, ignore_paths='^/images/.*$')

You will also want to create a cronjob to periodically remove expired sessions
from the datastore. You can find the [example
cronjob](http://github.com/dound/gae-sessions/tree/master/demo/cron.yaml) and
Expand Down Expand Up @@ -135,8 +141,8 @@ for authentication Here's a few lines of example code too:
session.regenerate_id()


_Author_: [David Underhill](http://www.dound.com)
_Updated_: 2011-Jul-03 (v1.07)
_Author_: [David Underhill](http://www.dound.com)
_Updated_: 2011-Jul-03 (v1.07)
_License_: Apache License Version 2.0

For more information, please visit the [gae-sessions webpage](http://wiki.github.com/dound/gae-sessions/).
Expand Down
17 changes: 12 additions & 5 deletions gaesessions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import logging
import pickle
import os
import re
import threading
import time

Expand Down Expand Up @@ -446,27 +447,33 @@ class SessionMiddleware(object):
memcache/datastore latency which is critical for small sessions. Larger
sessions are kept in memcache+datastore instead. Defaults to 10KB.
"""
def __init__(self, app, cookie_key, lifetime=DEFAULT_LIFETIME, no_datastore=False, cookie_only_threshold=DEFAULT_COOKIE_ONLY_THRESH):
def __init__(self, app, cookie_key, lifetime=DEFAULT_LIFETIME, no_datastore=False, cookie_only_threshold=DEFAULT_COOKIE_ONLY_THRESH, ignore_paths=None):
self.app = app
self.lifetime = lifetime
self.no_datastore = no_datastore
self.cookie_only_thresh = cookie_only_threshold
self.cookie_key = cookie_key
self.ignore_paths = ignore_paths
if not self.cookie_key:
raise ValueError("cookie_key MUST be specified")
if len(self.cookie_key) < 32:
raise ValueError("RFC2104 recommends you use at least a 32 character key. Try os.urandom(64) to make a key.")
if self.ignore_paths:
self.ignore_paths = re.compile(self.ignore_paths)

def __call__(self, environ, start_response):
# initialize a session for the current user
_tls.current_session = Session(lifetime=self.lifetime, no_datastore=self.no_datastore, cookie_only_threshold=self.cookie_only_thresh, cookie_key=self.cookie_key)

# create a hook for us to insert a cookie into the response headers
def my_start_response(status, headers, exc_info=None):
_tls.current_session.save() # store the session if it was changed
for ch in _tls.current_session.make_cookie_headers():
headers.append(('Set-Cookie', ch))
return start_response(status, headers, exc_info)
if self.ignore_paths and self.ignore_paths.match(environ['PATH_INFO']):
return start_response(status, headers, exc_info)
else:
_tls.current_session.save() # store the session if it was changed
for ch in _tls.current_session.make_cookie_headers():
headers.append(('Set-Cookie', ch))
return start_response(status, headers, exc_info)

# let the app do its thing
return self.app(environ, my_start_response)
Expand Down