from urllib2 import * class MyHttpHandler(HTTPErrorProcessor): #parent = OpenerDirector() handler_order = 1 def http_request(self, request): return request https_request = http_request def default_open(self, request): """return None for propagation""" return None def http_open(self, request): """return None for propagation""" return None https_open = http_open def unknown_open(self, request): """return None for propagation""" return None def http_response(self, request, response): response = self.parent.error('http', request, response, response.code, response.msg, response.info()) return response https_response = http_response def http_error_default(self, request, fp, code, msg, headers): """return None for propagation""" raise HTTPError(request.get_full_url(), code, msg, headers, fp) def http_error_XXX(self, request, fp, code, msg, headers): """return None for propagation""" return None urlopen = build_opener(MyHttpHandler).open
build_opener はデフォルトで [ProxyHandler, UnknownHandler, HTTPHandler, HTTPDefaultErrorHandler, HTTPRedirectHandler, FTPHandler, FileHandler, HTTPErrorProcessor] を組み込む。これらの動作を変更したいならそのクラスから導出したクラスを引数に指定する。
ハンドラはマルチスレッドで呼ばれる可能性があるので self ではなく、request で状態を保持する。
メソッドの呼ばれる順
- http_request
- default_open
- http_open
- unknown_open
- http_response
以下は HTTPErrorProcessor.http_response が呼ぶ
- http_error_XXX
- http_error_default
戻り値
*_request は request オブジェクトを必ず返さなければならない。
*_response は response オブジェクトを必ず返さなければならない。
他は assert(bool(result)) な値を返せばハンドラの伝搬は停止する。None を返すと他のハンドラが呼ばれる。例外は好きに投げろ。
割と良くできてると思います。またしても classic class ではありますが。