One-file WSGI "framework" for no dependency REST API's, etc.
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


This is just a simple one-file WSGI framework. It's designed to plug into
a default Python 2.5+ installation without dependencies, and just drop into 
projects that need a light web layer for testing, a quick REST API, or 
other similar purposes. The Handler class provides a few basic methods for 
quickly building something, and by default the render and render_list methods 
just use Python's string Template library.

Really, the point of this library is that you can just copy and paste
the contents into a file in your library, and extend as desired. 
If you want to install it "properly", just run:

sudo python install

...on some Unix-y type machine.

Here's a simple example:
from funnl import Handler, Server

class Page(Handler):
	route = r'/page_id/(a-z0-9_\-)+'
	def get(self, page_id):
		return self.render('page.htm', page_id=page_id)
server = Server()
You should also be able to pass "server" into any server / middleware 
that expects a WSGI-compatbile application. Just like any normal WSGI
application, you can return arbitrary text or even a generator if 
necessary (for example, if you are reading from a file. The StaticHandler
does this.)

By default the "render" and "render_list" method look for a "views" 
sub-folder in your current directory, but you can easily overwrite this
using the view_path server configuration option:

server = Server(view_path='/var/www/views')

Serving static files is easy. To use a "static" sub-folder in your
current directory, all you have to do is run:


Your files will be available under the /static path. For example, the
URL to a  file in your static folder that is at the location 
"images/favicon.ico" would be:


If you want to serve static files in another directory or with a
different URL, just pass one or both parameters to Server:

server = Server(

There are a few helpful handler methods.

return self.redirect(url) 
This method will send an appropriate 302 response.

response = self.render(view, {key='value', etc.})
This method will substitute any appearance of "$key" with the value, 
using Python's basic string.Template class.

response = self.render_list(subview, list_of_dicts) 
This will substitute the key / value pairs in each dict in the list
for the subview, and then concatenate each entry.

arg = self.get_argument('foo', default='bar')
This method will look through the query string arguments (and one day
POST arguments) for 'foo', and return 'bar' if it is not found. If you
do not pass in a default and the key is not found, it will raise a

self.headers['content-type'] = 'application/rss+xml'
The headers attribute is simply a dict that will be used to generate
the response headers.

self.start_response and self.environment
These provide direct access to the WSGI properties, if you need them. 
Since cookies, the request body, etc. don't have friendly wrappers yet,
you'll probably need self.environment for anything involved. 

If you return a dict from a method, it will turn it into JSON for you and 
set the appropriate headers. Make sure everything in the dict is 

* Document code
* Add POST request body argument parser
* Cookie helpers
* Request body helpers
* More tests, more helper functions

Would love feedback -- although keep in mind I'm not trying to replace
Django or anything, this is just for internal / small projects that need
a quick web layer for testing or something, mostly REST API's and such.