Consider the slightly more complicated example below using the imaginary session handling module superSession
:
#!/usr/bin/env python import superSession session = superSession.session() print "Content-type: text/plain\n\n" if session.has_key('visited'): print "You have already visited!" else: session['visited'] = 1 print "This is your first visit."
We create a session object and display a different string depending on whether or not the user has visited the site before. We could follow the approach above and create the following WSGI application to do the same thing:
def application(environ, start_response): import superSession session = superSession.session() if session.has_key('visited'): text = "You have already visited!" else: session['visited'] = 1 text = "This is your first visit." start_response('200 OK', [('Content-type','text/plain')]) return [text]
This would be perfectly good and work perfectly well. We could now refactor the code again:
def exampleApplication(environ, start_response): if environ['superSession'].has_key('visited'): text = "You have already visited!" else: environ['superSession']['visited'] = 1 text = "This is your first visit." start_response('200 OK', [('Content-type','text/plain')]) return [text] def session(application): def app(environ, start_response): if "superSession" not in environ: import superSession environ["superSession"] = superSession.session() # Options would obviously need specifying return application(environ, start_response) return app application = session(exampleApplication)
We have separated out the session code into a different function and added a key to the environ
dictionary called "session"
which contains the session object. Our exampleApplication
then accesses the session object through the environ
dictionary. Note how we have renamed our application
function to exampleApplication
and mapped the name application
to the session(exampleApplication)
object. The WSGI server will still be able to find a callable named application
and so will still be able to run our application.
The session function is now what we call a middleware component as it sits in between the server and the application. It gives the application new functionality but the result of calling session(exampleApplication)
is also just a WSGI application (because the combined object still conforms to the rules listed earlier) and so the server can still run the code.
The huge advantage of refactoring code in this way is that the session functionality can now easily be added to any WSGI application using our session
function. By chaining together these middleware components (which do not even have to be based on the Web Modules) WSGI applications can gain an enormous amount of functionality for very little programming effort by using existing middleware components. This helps make code easy to maintain and offers a very flexible programming methodology.