Hula hoop isn't a framework

I used around 2 hours to imagine and create my own web framework. The finish result has:
  • Threaded server
  • Session support
  • Static handling support
  • URL to object dispatcher (CherryPy style)
  • AJAX based error handling
  • HTTP error handling
  • Fully WSGI compatible
  • Endless WSGI extension possibilities
  • Super performance - 800 requests per second

You want to know how I did it? Read on, because it's very easy.

If hula hoop isn't a framework, then what is WSGI?

WSGI stands for Web Server Gateway Interface. It's a "new" Python way of collaborating between web projects. This may come as a surprise for you, but Python has A LOT of web frameworks, and a lot of them can't work together. WSGI sets a convention that enables web frameworks to use each others components. This isn't an introduction for WSGI, but here are some links that can get you started on understanding WSGI:

WSGI is really cool!

WSGI architecture

WSGI encapsulates the WSGI application:

Normal WSGI apps

Our architecture will be - notice that we reuse A LOT of code:

The hula hoop architecture

Now what it do? Creating the dispatcher

I like the URL to object approach that is used by CherryPy (and other frameworks). Too bad one can't directly reuse CherryPy's dispatcher. Here is a little visual explanation:

How an URL to object dispatcher works

This is basically the only thing that you need to create! Everything else is served. One can also easily use other approaches for dispatching (or use existing solution - like routes). I had copied some code from CherryPy's dispatcher (which made it even easier :]).

Hello World on dope

A little example showing off:

  • The object architecture
  • The support for sessions
  • The filter function
  • How redirection is handled
  • Static file and directory serving
import amiweb
import os
from paste.httpexceptions import HTTPFound

class Test:
  def filter(self, req):
    if req.session.has_key("logged_in"):
      raise HTTPFound("http://amix.dk/")

  def setLogin(self, req):
    req.session['logged_in'] = True
    req.session.save()
    return "Session saved"
  setLogin.exposed = True

  def index(self, req):
    return "Hello world"
  index.exposed = True

  def sessionTest(self, req):
    if req.session.has_key("counter"):
      req.session['counter'] += 1
    else:
      req.session['counter'] = 0
    req.session.save()
    return "%s" % req.session['counter']
  sessionTest.exposed = True

  def isNotExposed(self, req):
    return "Should not return anything"

    
rc = amiweb.RootController(Test())

#Serve some static directories
rc.dispatcher.setStaticPath("/images/",
    "%s/static/images" % os_path, True)
rc.dispatcher.setStaticPath("/uploads/",
    "%s" % os_path, False)
rc.dispatcher.setStaticPath("/ascii.h",
    "%s/static/ascii.h" % os_path, True)

amiweb.startServer(rc.wsgi_app, 8080)

Installing Python Paste and Beaker

I have included the CherryPy WSGI server. You will need to get Python Paste and Beaker. On their sites you can find guides how to install them. Their sites are:

Get the code

You will find hula hoop amiweb (which isn't a framework) and a test.py (which basically is a hello world application showing different things).

Download the zip

Code · Python 26. Mar 2006
© Amir Salihefendic. Powered by Skeletonz.