pso.session
Version: | $Revision: 1.7 $ |
Author: | thanos vassilakis |
Company: | Script Foundry Inc. |
Document URL: | http://sourceforge.net/docman/display_doc.php?docid=10174&group_id=49265 |
Contact: | thanos@scriptfoundry.com |
Feed-back: | pso-development@lists.sourceforge.net | Copyright: | thanos vassilakis 2001,2002 |
Contributions: | Ming Huang and Vadim Shaykevich. |
Last Changed: | $Header: /cvsroot/pso/doc/session-modpython.html,v 1.7 2003/01/03 17:25:06 thanos Exp $ |
Introduction
System Requirements
Real Quick Example - 95% of the Time
What's Going On
More Control - 5% of the Time
- Setting the service id
- Forcing the session id.
- Setting when a session expires.
- Reverting the current session to its previous state.
- Explicitly saving the current session.
- Storing the session files in another path.
- Storing the session data in a database.
- Doing things without cookies.
- Setting the session cookies path and domain
- What else can you do with
pso
?Session classes
Installation
Installation Example
- Mentioned Urls
pso.session
to add easy session
handling to a mod_python
request handler. Python Service
Objects
is a open source internet service development system. Its session
module is ideal for use with mod_python
, and in fact included in
this package is ModPythonRequest
which is the mod_python implementation
bridge. The pso system allows you to develop platform and server independent
request handlers.
Real Quick Example - 95% of the Time
from mod_python import apache def handler(req): req.send_http_header() req.write("Hello World!") return apache.OKIt's .htaccess file is:
AddHandler python-program .py PythonHandler mptest
test: http://www.0x01.com/~thanos/pso/tests/session/modp/mptest.py
.htaccess
file:
AddHandler python-program .py PythonHandler quicktest PythonFixupHandler pso.modpython::fixup PythonLogHandler pso.modpython::cleanupThe PythonFixupHandler
pso.modpython::fixup
adds a
pso service object to the request object. The PythonFixupHandler pso.modpython::cleanup
removes the pso service object from the request object. In the test handler
we need not make any changes, but to demo the use of the pso.session we
we added a few lines:
from mod_python import apache def handler(req): req.send_http_header() try: req.pso().session['visits'] +=1 except: req.pso()Session['visits'] =1 req.write("Hello World! ~ Your visit number: %(visits)d ~ Try Reload !" % req.pso()Session) req.write("session: %s" % req.pso()Session__dict__) return apache.OKThe above example was very quick. A lot of default values were used and many assumption were made, yet it shows you how painless it is to add and use session handling.
test: http://www.0x01.com/~thanos/pso/tests/session/quick/quicktest.py
What's Going On
fixup
is a simple wrapper around pso's ServiceHandler.
def fixup(req, requestImpl= ModPythonRequest, sessionImpl=None):
sys.stdout = req.pso = requestImpl(req)
session = req.pso().getSession( sessionImpl)
req.pso = ServiceHandler(req)
session = req.pso().getSession( sessionImpl)
return apache.OK
The algorithm for pso.session.ServiceHandler.getSession
is the following:
req.subprocess_env
. Default to
the value "host.module name
".
Cookie
" entry from req.headers_in
.
req.headers_out['cookie-set']
the value serviceId=sessionId,
for example: req.headers_out.add('cookie-set','MI6Service=007;')
.
req.pso()
is finalized. PythonOption PSOServiceId 'Your_Service_Id'
<directory>
block.
PythonOption 'Your_Service_Id' 'Your_Session_Id'
<directory>
block.
PythonOption PSOSessionExpire 900 # 15 minutesYou can use simple expressions
PythonOption PSOSessionExpire "15*60" # 15 minutesYou can also set the sessions to expire on a specific date:
PythonOption PSOSessionExpire "Mon, 15 Apr 2001 19:00:00 GMT" # 15 minutesFor more on this format see RFC2068 section 3.3.1 [also RCF822 and RCF1123] If a date is not give all values are seconds relative to the present. You can also control the session's lifespan in your code:
session.expire()
session.expire(0)
test: http://www.0x01.com/~thanos/pso/tests/session/expire/mptest.py
session.expire(15*60) # or PythonOption PSOSessionExpire "60*15" etc. twoDays = 60*60*48 session.expire(date = time()+twoDays)
import time #PythonOption PSOSessionExpireOn "31-12-2002" session.expire("Mon, 15 APR 2001 19:00:00", "%a, %d %b %Y %H:%M:%S")
session.revert()
session.save()
PythonOption PSOSessionFileLoader_Path "/tmp/path0/"# remember the trailing '/'to the .htaccess file or to the relevant apache httpd.conf
<directory>
block.
Test: http://www.0x01.com/~thanos/pso/tests/session/path0/mptest.py
pso.session.CookeFileImpl
overloading the attribute CookieFileImpl.PATH
and then
write your own fixup
.
# file: path1test.py # from mod_python import apache from pso import session, modpython class MyFileImpl(session.CookieFileImpl): PATH="/tmp/path1/" def fixup(req): modpython.fixup(req, sessionImpl=MyFileImpl) return apache.OK . . .Now change the PythonFixupHandler in the .htaccess (or httpd.conf) entry to:
#in .htaccess # PythonHandler path1test PythonFixupHandler path1test::fixup
test: http://www.0x01.com/~thanos/pso/tests/session/path1/path1test.py
# file: path2test.py # from mod_python import apache from pso import session, modpython class MyFileImpl(session.CookieFileImpl): def getPath(self, reqHandler, session): """ you must return the full session file path excluding name. It must be valid, and the handler must have the authority to create or write to the given file. """ return "/tmp/path2/" def fixup(req): modpython.fixup(req, sessionImpl=MyFileImpl) return apache.OK . . .Again remember change the PythonFixupHandler entry to:
#in .htaccess # PythonHandler path1test PythonFixupHandler path2test::fixup
test: http://www.0x01.com/~thanos/pso/tests/session/path2/mptest.py
SessionImpl
. The code below is a bit simplistic,
but illustrates the basic idea, and works!
#file: mysql/mysqltest.py # from mod_python import apache from pso import session, modpython import pickle import base64 from time import time import MySQL class MySQLLoader: dbconn = MySQL.connect("localhost", "test") dbconn.query('use test') def load(self, reqHandler, session): " must return the saved session obj or None. " result = self.dbconn.query("SELECT sessionObj FROM session WHERE sessionId='%s';" % self.getSessionId(reqHandler)) rows = result.fetchrows() if rows: sessionData = rows[0][0] if sessionData: return pickle.loads(base64.decodestring(sessionData)) return session def save(self, reqHandler, session): serviceId = self.getServiceId(reqHandler) sessionId = self.getSessionId(reqHandler) sessionStr = base64.encodestring(pickle.dumps(session,1)) res = self.dbconn.query("UPDATE session SET sessionObj='%s', serviceId='%s' WHERE sessionId='%s';" % (sessionStr, serviceId, sessionId)) if res.affectedrows() == 0: self.dbconn.query("INSERT INTO session (serviceId,sessionId, sessionObj) values ('%s','%s','%s')" % (serviceId, sessionId, sessionStr)) def newSessionId(self, reqHandler): "returns a new id" result = self.dbconn.query("SELECT count(sessionId) FROM session;") rows = result.fetchrows() if rows: int(rows[0][0]) return 0 class MySQLImpl(session.CookieSession, MySQLLoader, session.SessionImpl): pass def fixup(req): modpython.fixup(req, sessionImpl=MySQLImpl) return apache.OK . . .And remember to change the PythonFixupHandler entry in .htaccess file to:
PythonHandler mysqltest PythonFixupHandler mysqltest::fixup
test: http://www.0x01.com/~thanos/pso/tests/session/mysql/mysqltest.py
pso.request.ServiceRequest.serviceUrl
has been implemented.
PSOCookieSession_Comment
is equivalent to Comment
PSOCookieSession_Domain
is equivalent to Domain
PSOCookieSession_Max-Age
is equivalent to Max-Age
PSOCookieSession_Path
is equivalent to Path
PSOCookieSession_Secure
is equivalent to Secure
PSOCookieSession_Version
is equivalent to Version
PSOCookieSession_expires
is equivalent to expires?...
used by Netscape et al. expires
.
expire
takes a string date such as "Mon, 12 Nov 2002 13:04:56
GMT", as defines in RFC2068 section 3.3.1 [also RCF822
and RCF1123]
pso
If we take our above quick example:
from mod_python import apache
def handler(req):
req.send_http_header()
try:
req.pso().session['visits'] +=1
except:
req.pso().session['visits'] =1
req.write("Hello World! ~ Your visit number: %(visits)d ~ Try Reload !" % req.pso().session)
req.write("session: %s" % req.pso()Session__dict__)
return apache.OK
Some simple changes can make it run as mod_python or as cgi
#!/usr/bin python2.2 from pso.session import ServiceHandler, OK def handler(req): req.pso().send_http_header)_ try: req.pso()Session['visits'] +=1 except: req.pso()Session['visits'] =1 print "Hello World! ~ Your visit number: %(visits)d ~ Try Reload !" % req.pso()Session print "session: %s" % req.pso()Session__dict__ return OK if __name__ =='__main__': ServiceHandler().run(handler)The real differences are:
pso.service
.
__main__
,
and invoke your handler through ServiceHandler(handler)Run()
.
req.pso()Write
method that is available for both mod_python and CGI.
Installation:
pso
should be installed using Distutils which
comes standard with python 1.6. and up
$ mkdir ~/public_html/psotest
$ wget http://www.0x01.com/~thanos/pso/dist/current.tgz or for MS lovers: [ http://www.0x01.com/~thanos/pso/dist/current.exe] $ tar zvfx current.tgz
$ cd pso-XX/ $ python2.1 setup.py install --install-purelib=~/public_html/testpso
#.htaccess for testing pso using CGI # # Options ExecCGI directs apache to allow cgi's to be run from this directory. # AddHandler cgi-script .py treat any .py file as a script #SetEnv PSOServiceId MyPSOTest names session cookie as MyPSOtest Options ExecCGI Indexes AddHandler cgi-script .cgi SetEnv PSOServiceId MyPSOTest
#!/usr/bin/env python2.1 # from pso.service import ServiceHandler def testHandler(serviceRequest): print "hello world" if __name__ == '__main__': ServiceHandler().run(testHandler)Now we will set the file permissions, and do the link:
$ chmod a+x test.py $ ln test.py test.cgiand try it from the command line, should give you this:
python:~/public_html/testpso# ./test.cgi set-cookie: SESSION_ID=@60123.0SESSION_ID; content-type: text/html hello world python:~/public_html/testpso#Now lets try it using a browser: http://www.yourhost.com/~yourid/testpso/test.cgi
pso
directory somewhere in the python PATH or to the directory of your request handler.
www.python.org | http://www.python.org/ |
Gregory Trubetskoy's mod_python | http://www.modpython.org/ |
RCF2109 | http://www.faqs.org/rfcs/rfc2109.html |
RFC2068 | http://www.faqs.org/rfcs/rfc2068.html |
RCF822 | http://www.faqs.org/rfcs/rfc822.html |
RCF1123 | http://www.faqs.org/rfcs/rfc1123.html |
Greg Ward's intalling python modules | http://www.python.org/doc/current/inst/inst.html |