google app engineでInternal server error 500の動作を独自に定義
google app engine では、webapp.RequestHandler の継承クラスを定義することでHTTPリクエストのハンドラを定義します。例外(Internal server error 500 に相当)が発生した場合の動作を、handle_exception メソッドをオーバーライドすることで独自に定義できます。
サンプル
http://code.google.com/intl/ja/appengine/docs/python/gettingstarted/usingwebapp.htmlのコードがベース。
from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app import cgi import logging import sys import traceback class MainPage(webapp.RequestHandler): def get(self): # test raise RuntimeError('runtime error') self.response.headers['Content-Type'] = 'text/plain' self.response.out.write('Hello, webapp World!') def handle_exception(self, exception, debug_mode): self.error(500) logging.exception(exception) if debug_mode: lines = ''.join(traceback.format_exception(*sys.exc_info())) self.response.clear() self.response.out.write('<pre>%s</pre>' % (cgi.escape(lines, quote=True))) else: self.response.headers['Content-Type'] = 'text/plain' self.response.out.write('Internal Server Error 500') application = webapp.WSGIApplication( [('/', MainPage)], debug=False) def main(): run_wsgi_app(application) if __name__ == "__main__": main()
debug=Trueのときは、ベースコードと全く同じように動作し、debug=Falseのときは、Internal Server Error 500 をブラウザに表示する点がベースコードの場合と異なる。
ベースコードからの変更点は、
- handle_exceptionメソッドのオーバーライド
- handle_exceptionメソッドのオーバーライドに伴う追加のimport
- debug=False
getメソッドの raise RuntimeError('runtime error') はテスト用に挿入。本来不要。
RequestHandler クラス
RequestHandler クラスの handle_exception メソッドと error メソッド。error は handle_exception から呼び出される。
def handle_exception(self, exception, debug_mode): """Called if this handler throws an exception during execution. The default behavior is to call self.error(500) and print a stack trace if debug_mode is True. Args: exception: the exception that was thrown debug_mode: True if the web application is running in debug mode """ self.error(500) logging.exception(exception) if debug_mode: lines = ''.join(traceback.format_exception(*sys.exc_info())) self.response.clear() self.response.out.write('<pre>%s</pre>' % (cgi.escape(lines, quote=True)))
def error(self, code): """Clears the response output stream and sets the given HTTP error code. Args: code: the HTTP status error code (e.g., 501) """ self.response.set_status(code) self.response.clear()
handle_exception では、ステータスコードを 500 にセットし、ログをはいている。そして、デバッグモードであれば、トレース情報を出力。