Talk given at: | EuroPython 2007 |
---|---|
By: | Michele Simionato |
Organization: | StatPro Italy |
Date: | 2007-07-11 |
This is as a talk for beginners, only knowledge of CGI and a bit of HTTP protocol is expected (non-beginners -> "Zope on a Paste")
WSGI application:
(env, resp) -> chunks of text
env = environment dictionary of the server; resp = function sending to the client the HTTP headers
WSGI middleware:
WSGI app -> enhanced WSGI app
from wsgiref import simple_server def app(env, resp): resp( '200 OK', [('Content-type', 'text/html')]) return ['<h1>Hello, World!</h1>'] server=simple_server.make_server('', 8000, app) server.serve_forever()
It was easy to write a simple command line history plotter
def app(env, resp): form = getformdict(env) if form.get('submitted'): try: fname = make_graph(form.get('code'), batch=True) except Exception, e: resp('500 ERR', [('Content-type', 'text/plain')]) return [traceback.format_exc()] else: resp('200 OK', [('Content-type', 'image/png')]) return file(fname)
else: resp('200 OK', [('Content-type', 'text/html')]) return [ 'Try values such as <pre>fri-gb;AVE</pre>', '<pre>fri-gb;TSCO</pre> <pre>fri-us;DELL</pre>', '<form>', 'insert code ', '<input type="text" name="code"/>', '<input type="submit", name="submitted",' ' value="submit" />', '</form>']
def getformdict(env): qs = env.get('QUERY_STRING') if qs: return dict((k, v[0]) for k, v in cgi.parse_qsl(qs)) else: return {}
WSGI is a the missing link between the low-level mechanics of the Web and the high-level intricacies of the Web frameworks.
class Example(object): def __init__(self, sitename): self.sitename = sitename def __call__(self): yield '<h1>%s: index page</h1>' % self.sitename yield 'goto <a href="./page1">page1</a><br/>' yield 'goto <a href="./page2">page2</a><br/>' yield 'goto <a href="subsite">subsite</a><br/>' def page1(self): yield 'page1' def page2(self): yield 'page2' page1.exposed = page2.exposed = True
class WSGIObjectPublisher(object): def __init__(self, root): self.root = root def __call__(self, env, resp): return self.getsubpage(self.root,env,resp)() def getsubpage(self, root, env, resp): script_name = util.shift_path_info(env) if not script_name: # We've arrived! resp('200 OK',[('content-type','text/html')]) return root ...
try: page = getattr(root, script_name) except AttributeError: resp('404 Not Found',[('content-type','text/plain')]) return lambda:['missing page %r'%script_name] exposed = getattr(page, 'exposed', False) if not exposed: resp('404 Not Found',[('content-type','text/plain')]) return lambda : [ '%r is not exposed!' % script_name] return self.getsubpage(page, env, resp)
Pro:
Contra:
No middleware in the standard library, but lots of useful middleware from third party sources. For instance, authentication middleware:
from paste.auth.basic import AuthBasicHandler def only_for_pippo(env, user, passwd): return user == 'pippo' auth_app = AuthBasicHandler( app, 'app realm', only_for_pippo)
from wsgiref.simple_server import make_server from paste.evalexception import EvalException a, b = 1,0 def app(env, resp): resp('200 OK',[('Content-type','text/html')]) return [str(a/b)] make_server('',9090,EvalException(app) ).serve_forever()
Show evalexception
That's all, folks!
(P.S. at StatPro, we are hiring! ;)