はじめに
前回は、
今回は、 WSGIの仕組みの中でも重要な、
まずは、
ミドルウェアとは
ミドルウェアとは、
たとえば
- リクエストURLに応じたアプリケーションのマッピング
- ユーザ認証
- レスポンスヘッダへの情報追加
- アプリケーションで生成された動的コンテンツのキャッシュ
といったような処理です。

図1では、
実際のミドルウェア
ここで、
今回は、
- 何もしないミドルウェア
- URLマッピングを行うミドルウェア
の2種類です。
今回使用するサンプルのソースはmiddleware.
今回は、
実行は前回と同様に
$ python middleware.py
とします。
実行した後に、



何もしないミドルウェアも使用していますが、
それでは、
何もしないミドルウェア
最初は、
class Nop(object):
''' 何もしないミドルウェア (クラス版) '''
def __init__(self, application):
self.application = application
def __call__(self, environ, start_response):
return self.application(environ, start_response)
ミドルウェアの基本的な処理は、
何もしないミドルウェアは、
>>> application = Nop(application)
このようにしておくと、 WebサーバからNopの__
URLマッピングを行うミドルウェア
次は、
たとえば、http://
であったとき、http://
とhttp://
で別のアプリケーションに処理を割り振る、
class SelectApp(object):
''' パスによるアプリケーション振り分けを行う '''
def __init__(self, table, notfound=notFound):
# パスは長い順にマッチさせたいので、あらかじめソートしておく
tmp = sorted(table, key=lambda x:len(x), reverse=True)
# 扱いやすいように、タプルのリストにしておく
table = [(x, table[x]) for x in tmp]
self.table = table
# 割り振るパスが見つからなかったときに呼び出すアプリケーション
self.notfound = notfound
def __call__(self, environ, start_response):
''' リクエストのパスを見て振り分ける '''
name = 'SCRIPT_NAME'
info = 'PATH_INFO'
scriptname = environ.get(name, '')
pathinfo = environ.get(info, '')
for p, app in self.table:
if p == '' or p == '/' and pathinfo.startswith(p):
return app(environ, start_response)
# 同じパスならそのまま
# 同じパスで始まっていて、その後にスラッシュがある
if pathinfo == p or pathinfo.startswith(p) and \
pathinfo[len(p)] == '/':
scriptname = scriptname + p
pathinfo = pathinfo[len(p):]
# リクエスト情報を書き換える
environ[name] = scriptname
environ[info] = pathinfo
return app(environ, start_response)
return self.notfound(environ, start_response)
このミドルウェアは、
>>> application = SelectApp({'/path1':app1, '/path2':app2})
こうしておくと、
それでは実装の解説に入ります。
SelectAppのコンストラクタでは、
__
SCRIPT_http://
にあるならば、 SCRIPT_
PATH_http://
がアプリケーションのある位置で、http://
とアクセスした場合、
振り分けは、
ただし、'/path'
の振り分けに'/path/
だけでなく'/pathother'
なども含まれてしまいます。なので、 PATH_
判定で一致した場合は、 PATH_
すべてのパスに一致しない場合は、
まとめ
以上が WSGI アプリケーションにおけるミドルウェアの仕組みです。
このように、
このようなミドルウェアは、
今回までで、
次回は、