<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Singletoned &#187; werkzeug</title>
	<atom:link href="http://blog.singletoned.net/tag/werkzeug/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.singletoned.net</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Thu, 21 Jan 2010 20:50:16 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>I think I understand WSGI</title>
		<link>http://blog.singletoned.net/2008/03/i-think-i-understand-wsgi/</link>
		<comments>http://blog.singletoned.net/2008/03/i-think-i-understand-wsgi/#comments</comments>
		<pubDate>Thu, 20 Mar 2008 16:33:07 +0000</pubDate>
		<dc:creator>Ed Singleton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[werkzeug]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://www.singletoned.net/2008/03/20/i-think-i-understand-wsgi/</guid>
		<description><![CDATA[I&#8217;ve been messing around with Python web frameworks for a quite a while now.  Trying out lots of different ones and seeing which one feels like the best fit.  As I&#8217;ve got closer and closer to the right one, I&#8217;ve also found that i am getting closer and closer to using WSGI.

WSGI seems [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been messing around with Python web frameworks for a quite a while now.  Trying out lots of different ones and seeing which one feels like the best fit.  As I&#8217;ve got closer and closer to the right one, I&#8217;ve also found that i am getting closer and closer to using WSGI.</p>

<p>WSGI seems excellent and could be great for Python.  Frameworks tend to make things seem more difficult and mysterious than they really are.  What has taken me a long time to learn is that WSGI is really very simple.</p>

<p>At it&#8217;s simplest there are three aspects to it:</p>

<ul>
<li>You receive a dictionary with useful information in it (environ)</li>
<li>You receive a function to call that starts the response (start_response)</li>
<li>You return an iterator (ie a list) of strings (this is your page body)</li>
</ul>

<p>Anything on top of that is just helpers.  Helpers are great, but you don&#8217;t need a framework that hides what is really going on, when it&#8217;s as simple as that.</p>

<p>You can create a hello world app as simple as:</p>

<p><pre><code>def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    return ["Hello World"]
</code></pre></p>

<p>Obviously that just returns <code>Hello World</code> with no html.  Which is bad. So:</p>

<p><pre><code>def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    begin_body = "&lt;html&gt;&lt;body&gt;"
    body = "Hello World"
    end_body = "&lt;/body&gt;&lt;/html&gt;"
    return [begin_body, body, end_body]
</code></pre></p>

<p>We don&#8217;t want to write <code>begin_body</code> and <code>end_body</code> every time, so lets write a function to handle this for us:</p>

<p><pre><code>def put_in_body(<em>args):
    begin_body = "&lt;html&gt;&lt;body&gt;"
    end_body = "&lt;/body&gt;&lt;/html&gt;"
    return [begin_body] + list(</em>args) + [end_body]
</code></pre></p>

<p>Then we can just:</p>

<p><pre><code>def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    return put_in_body("Hello World")
</code></pre></p>

<p>We&#8217;re going to want to be able to do lots of different things, and we don&#8217;t want to write them all in the body of one function, so let&#8217;s write a dispatcher:</p>

<p><pre><code>def dispatch(environ):
    # We need to get the path from the environ, and work out where to go.
    path_info = environ.get('PATH_INFO', '')
    if path_info == "/goodbye":
        return goodbye(environ)
    else:
        return hello_world(environ)</p>

<p>def hello_world(environ):
    return ["Hello World"]</p>

<p>def goodbye(environ):
    return ["Goodbye World"]</p>

<p>def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    return put_in_body(dispatch(environ))
</code></pre></p>

<p>Now if you go to /goodbye it will say &#8220;Goodbye World&#8221;, otherwise it will say &#8220;Hello World&#8221;.</p>

<p>As you can see it is all very straightforward.  It allows you to do things however you want.  Adding more and more functionality is just a case of adding functions that returns strings, and telling the dispatcher when to call that function.</p>

<p>In a later post I&#8217;ll talk about threading.  It turns out that&#8217;s easy as well.</p>

<p>If you want to run the code above, just <code>easy_install paste</code> and then add this to the bottom of your file (which I called <code>wsgi_sample.py</code>):</p>

<p><pre><code>if <strong>name</strong> == '<strong>main</strong>':
    from paste import httpserver
    httpserver.serve(app, host='127.0.0.1', port='8080')
</code></pre></p>

<p>Then you can do <code>python wsgi_sample.py</code> and visit http://localhost:8080 to see it working (don&#8217;t forget to visit http://localhost:8080/goodbye before you leave).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.singletoned.net/2008/03/i-think-i-understand-wsgi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
