ゴミ箱の中のメモ帳

まだ見ぬ息子たちへ綴る手記

Python BottleでURLの最後にスラッシュをつける

前々から書いているように、私はWebシステムを制作するのにPythonでBottleとPeeweeを使っている。あまりこの組み合わせで制作しているシステムを見ることはないが非常に便利だ。

私はWSGIを理解していないのでCGIモードとしてBottleを動かしているために恩恵に授かれていない部分もあるかと思うがそれでも便利だ。便利だ便利だと書くほどに便利だ。

そしてたまにBottleについて検索しているとBottleを試用している人を見かける。試用なのでドキュメントを余り読んでいないのかも知れないが、ドキュメントを読まずしてBottleが不便だと記すのは中々渋い。

 

Pythonプロフェッショナルプログラミング第2版

Pythonプロフェッショナルプログラミング第2版

 

 

Python言語によるプログラミングイントロダクション: 世界標準MIT教科書

Python言語によるプログラミングイントロダクション: 世界標準MIT教科書

 

 

====
そんななかで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など使わなくても問題ないという参考になればと思う。