Python BottleでURLの最後にスラッシュをつける
前々から書いているように、私はWebシステムを制作するのにPythonでBottleとPeeweeを使っている。あまりこの組み合わせで制作しているシステムを見ることはないが非常に便利だ。
私はWSGIを理解していないのでCGIモードとしてBottleを動かしているために恩恵に授かれていない部分もあるかと思うがそれでも便利だ。便利だ便利だと書くほどに便利だ。
そしてたまにBottleについて検索しているとBottleを試用している人を見かける。試用なのでドキュメントを余り読んでいないのかも知れないが、ドキュメントを読まずしてBottleが不便だと記すのは中々渋い。
Python言語によるプログラミングイントロダクション: 世界標準MIT教科書
- 作者: ジョン・V.グッターグ,John V. Guttag,久保幹雄
- 出版社/メーカー: 近代科学社
- 発売日: 2014/12/29
- メディア: 単行本
- この商品を含むブログ (3件) を見る
====
そんななかでBottleのURLディスパッチャ(getとかpostデコレータ)で関数に対してスラッシュの有無両方を設定しているのを見ることが多い。
@get('/entry/<entry_id:int>') @get('/entry/<entry_id:int>/') def entry_view(): pass
こういうのだ。
確かにこうしておけば最後のスラッシュの有無両方のリクエストを捌けるが関数の数だけデコレータが増えるし、何より面倒くさい。
そしてその面倒くさいことはBottleの開発者も放っておくはずがない。
もちろん面倒くさいだけではなくデコレータの書き忘れやタイプミスも増える。
このURLの最後にスラッシュをつけるか付けないか両方のリクエストを受け付けるという書き方があるわけでは無いが、それを実装できるようにはなっている。
Bottleにはリクエスト処理を行う前に処理を実行するためのフックが用意されている(もちろんリクエスト処理のあとのフックもある)。
@hook('before_request') def entry_view(): pass
これだ(もちろん反対は'after_request')。
これを使えばリクエスト前になんらかの処理ができるので、もちろんリクエストURLの書き換えもリダイレクトも実装できる。
@bottle_hook('before_request') def redirect_slash(): request_url = request.environ['PATH_INFO'] # type: str if request_url.startswith('/statics/'): return None if request_url.endswith('/'): return None redirect(request_url + '/')
こんな感じで行ける。少々もさい書き方だがわかりやすいだろうか。
'/statics/'は'static_file'で出しているだろうからスラッシュをつけるのを除外し、最後がスラッシュで終わっていない場合はスラッシュ付きURLにリダイレクトを行う。
リダイレクトでなくて、もちろんリクエストURLにスラッシュが付いていることにしてそのままアクセスさせてもいいが、そうすると同じページのURLが2個できるので私は好きではない。
まぁこんな感じでアホみたいにでかいDjangoなど使わなくても問題ないという参考になればと思う。