# HG changeset patch # User Tero Marttila # Date 1234742954 -7200 # Node ID fbccc1648d799882a0c7e6f7b3590db3443af03d # Parent 088aa2da1340282d924b865eeb3e38376754b329 improved error handling for CGI/FastCGI diff -r 088aa2da1340 -r fbccc1648d79 error.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/error.py Mon Feb 16 02:09:14 2009 +0200 @@ -0,0 +1,36 @@ +""" + Build error messages +""" + +import traceback, sys + +def build_error (exc_info=None) : + """ + Dumps out a raw traceback of the given/current exception to stdout. + + Returns a (status, content-type, body) tuple, with all components being non-unicode strs. + """ + + + # default + if not exc_info : + exc_info = sys.exc_info() + + # return + return ('500 Internal Server Error', 'text/html; charset=UTF-8', ("""\ +500 Internal Server Error +

Oops!

+

+ An error occured, which was not logged, and will not be reported to anybody. It might be your fault, or it might be + the programmer's, but it's probably not mine. If you think you really care, you can try poking the administrator of + this site to see if they respond. +

+

+ If you do so, please include the following information: +

+

Details:

+
%(traceback)s
+""" % dict( + traceback = ''.join(traceback.format_exception(*exc_info)) + )).encode('utf-8')) + diff -r 088aa2da1340 -r fbccc1648d79 index.cgi --- a/index.cgi Mon Feb 16 01:03:23 2009 +0200 +++ b/index.cgi Mon Feb 16 02:09:14 2009 +0200 @@ -6,30 +6,22 @@ def error () : """ - Dumps out a raw traceback of the current exception to stdout, call from except - """ + Dumps out a raw traceback of the current exception to stdout, call from except. - import traceback, sys + Used for low-level ImportError's + """ - # HTTP headers - sys.stdout.write('Status: 500 Internal Server Error\r\n') - sys.stdout.write('Content-type: text/html\r\n') + # if this import fails, we're doomed + import sys, error + + # format info + status, content_type, body = error.build_error() + + # HTTP headers+body + sys.stdout.write('Status: %s\r\n' % status) + sys.stdout.write('Content-type: %s\r\n' % content_type) sys.stdout.write('\r\n') - sys.stdout.write("""\ -500 Internal Server Error -

Oops!

-

- An error occured, which was not logged, and will not be reported to anybody. It might be your fault, or it might be - the programmer's, but it's probably not mine. If you think you really care, you can try poking the administrator of - this site to see if they respond. -

-

- If you do so, please include the following information: -

-

Details:

-
%(traceback)s
- -""" % dict(traceback=traceback.format_exc())) + sys.stdout.write(body) def main () : """ @@ -37,11 +29,11 @@ """ try : - from qmsk.web import wsgi, cgi_main - import urls + from qmsk.web import cgi_main + import wsgi # create app - app = wsgi.Application(urls.mapper) + app = wsgi.Application() # run once cgi_main.run(app) diff -r 088aa2da1340 -r fbccc1648d79 index.fcgi --- a/index.fcgi Mon Feb 16 01:03:23 2009 +0200 +++ b/index.fcgi Mon Feb 16 02:09:14 2009 +0200 @@ -2,28 +2,25 @@ # :set filetype=py """ - CGI mode using qmsk.web.fastcgi_main + FastCGI mode using qmsk.web.fastcgi_main """ +from qmsk.web import fastcgi_main + +# XXX: error handling for imports? Lighttp sucks hard at this +import wsgi + def main () : """ - Build our wsgi.Application and run + Build our WSGIApplication and run """ - try : - from qmsk.web import wsgi, fastcgi_main - import urls - - # create app - app = wsgi.Application(urls.mapper) + # create app + app = wsgi.Application() - # run once - fastcgi_main.run(app) + # run once + fastcgi_main.run(app) - except : - # display error on stdout - cgi_main.error() - if __name__ == '__main__' : main() diff -r 088aa2da1340 -r fbccc1648d79 wsgi.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wsgi.py Mon Feb 16 02:09:14 2009 +0200 @@ -0,0 +1,31 @@ +""" + Our custom WSGI application +""" + +from qmsk.web import wsgi + +import urls, error + +# our custom app with custom error() method +class Application (wsgi.Application) : + def __init__ (self) : + """ + Construct wsgi.Application with our URLMapper + """ + + super(Application, self).__init__(urls.mapper) + + def handle_error (self, exc_info, env, start_response) : + """ + Use error.build_error and return that + """ + + # get info + status, content_type, body = error.build_error() + + # headers + start_response(status, [('Content-type', content_type)], exc_info) + + # body + return body +