Werkzeugで遊ぼう! - Routing編

written by shn, on Mar 7, 2009 2:34:00 AM.

リクエストから、各URLへと対応するハンドラを導くのに、Werkzeugではwerkzeug.routingを使う。

wz_routing.py

#! -*- coding:utf-8 -*-
from werkzeug import run_simple
from werkzeug.routing import Map, Rule, Submount, Subdomain

class WSGIApplication(object):
    def __init__(self):
        self.url_map = Map([
            Rule('/hello', endpoint='hello'),
            Rule('/hello/<string:lang>', endpoint='hello'),
        ])
        self.url_adapter = self.url_map.bind('localhost')

    def __call__(self, environ, start_response):
        endpoint, arguments = self.url_adapter.match(environ['PATH_INFO'])

        handler = getattr(self, 'handle_%s' % endpoint)
        return handler(environ, start_response, **arguments)

    def handle_hello(self, environ, start_response, lang='en'):
        writer = start_response('200 OK', [('Content-Type', 'text/plain; charset=utf-8')])
        if lang == 'en':
            return ['Hello']
        elif lang == 'ja':
            return ['こんにちわ']
        elif lang == 'he':
            return ['הלו']
        return ['no hello yet']

if __name__ == '__main__':
    run_simple('localhost', 4000, WSGIApplication())

$ python wz_routing.pyして、$ curl http://localhost:4000/hello とか、 $ curl http://localhost:4000/hello/ja とかしてみるといろいろなhelloが楽しめると思う。

Ruleには、<int>やら、<float>やらも使えるので、/blog/archive/2009/03/とか、twitter.com/shn/repliseみたいなナウいURLが設計しやすくて良いですね~

__call__の中身は、以下のようにも書き換えられる。

return self.url_adapter.dispatch(
    lambda e, a: getattr(self, 'handle_%s' % e)(environ, start_response, **a),
    path_info=environ['PATH_INFO']
)

goodbyeも楽しみたいなーと思って、/goodbyeにアクセスするとNotFound例外が飛ぶ。こいつもwsgi的な奴なので、ちょちょっとするとエラーを表示してくれる。

from werkzeug.exceptions import HTTPException
try:
    endpoint, arguments = self.url_adapter.match(environ['PATH_INFO'])
except HTTPException, e:
    return e(environ, start_response)
else:
    ...

Submountを使うと、Ruleの塊を指定したディレクトリ以下にマッチしてくれるようにしてくれる。似たようなのにSubdomainてのもあるけど、まだ使ったこと無い。subdomain毎にbind()しないといけないのかな?

Leave a Reply