Some things

Better living through biologically-inspired optimization

Stupid Python Tricks II: A 50-line micro-web framework.

It doesn't work with anything but Python's builtin HTTP server, it has no templating, it basically has nothing but URL dispatching, and only for control classes defined within the file. Nevertheless, I present a microscopic model-view-controller framework. Um, minus the model, and the view. Requires Python Routes, a reimplementation of Ruby on Rails' famous RESTful default URL dispatching for Python.


# eigenframe.py - a proper frame(work)

import BaseHTTPServer, SimpleHTTPServer, sys
from routes import Mapper

dispatcher = Mapper()

def bad_url():
    return "Bad URL"

class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def run_app(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

        # nice rails-style mapping.
        dispatcher.connect(":(ctrl)/:(act)/:(id)")
        dispatcher.connect(":(ctrl)", act="index", id=None)
        dispatcher.connect(":(ctrl)/:(act)", id=None)
        dispatcher.connect("/",ctrl="default",act="index",id=None)
        dispatcher.create_regs([]) # what does this do? whatever.
        route=dispatcher.match(self.path)

        if route is not None:
            data = self.do_call(route['ctrl'].title(),route['act'],route['id'])
            self.wfile.write(data)
        else:
            self.wfile.write(bad_url())

    def do_GET(self):
        if self.path.startswith("/static/") or self.path == "/favicon.ico":
            SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
        else:
            self.run_app()

    def do_call(self, ctrl, act, id):
        try:
            mod = __import__(ctrl)
        except:
            return bad_url()
        cls = vars(mod)[ctrl]()
        return getattr(cls, act)(id)

def run(port=defaultport):
    httpd = BaseHTTPServer.HTTPServer(("", port), Handler)
    httpd.serve_forever()

if __name__ == "__main__":
    run(8000)

When it sees a controller like blaahg it looks to Blaahg.py for a controller clled Blaahg. So load up a new file, Default.py with the contents as follows:


import eigenframe

class Default:
    def index(self):
        return "Jumping is not a crime"

if __name__ == "__main__": eigenframe.run()

Now access http://localhost:8000.


warren@Stampy:~/agg$ lynx -dump http://localhost:8000/

   Jumping is not a crime

warren@Stampy:~/agg$

So it has a 7-line "hello, world", about 20 times better than in Java. Buzzword compliance: REST, Convention over Configuration. Obviously it can't do much but the point is clear: dynamic languages really are a huge win. And with that I'm going to bed.

Comments

Thank you for this example, it helped me understand how to integrate routes and BaseHTTPServer in a case where I wanted a really micro desktop-based webserver for a mini-app.

Add a comment

you're not logged in