Implementing VirtualHosts in WSGI

Today I will show a very simple WSGI application to dispatch requests based on host header.

from pasteob import wapp

class HostMap(dict):
    fallback = None
    @wapp
    def __call__(self, req):
        host = req.host.split(':')[0]
        return self.get(host, self.fallback)

I’m using my own @wapp decorator, but you can use webob.dec and it would be alsmost identical (you’d need to have fallback = HTTPNotFound() or similar).

Here’s a simple usage example:

hostmap_app = HostMap({
    'host1.com': Response("host1"),
    'host2.com': Response("host2"),
})
hostmap_app['host3.com'] = Response("host3")
hostmap_app.fallback = Response("unknown host", status=404)

What we have here is a dictionary mapping hosts to WSGI apps which is also an WSGI app itself. If the host from the request is not in the dict, it falls back to .fallback app. All of this is very easy to deduce from the code.

Some points:

  • There are no APIs to memorize at all
  • I can’t imagine a more compact implementation. It’s very hard to have bugs with this little code.
  • The dispatcher can be inspected at runtime in a very obvious way (it’s a dict subclass)
  • It can also be reconfigured at runtime
  • If you need something more fancy, say with regexp matching, it’s still trivial to implement. But only as long as you are solving just the problem at hand and not overgeneralizing.
  • Can we solve more complex host dispatching cases and roll that into this app so it can be reused in more cases? Yes we can. Should we do that? No. Specialized solutions are always a better fit for specific needs, we should just make sure that creating them is as easy as possible, and our HostMap has no role in that.
  • Think about how much more code it takes to add configuration from .ini files to this. Do people really love .ini files that much? In what way configuration in app startup script is inferior, exactly?