summaryrefslogtreecommitdiff
path: root/paste/cgitb_catcher.py
blob: b4175830eef3d8be4e46e241de2d88438380c6a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"""
WSGI middleware

Captures any exceptions and prints a pretty report.  See the cgitb
documentation for more:
  http://python.org/doc/current/lib/module-cgitb.html
"""

import cgitb
from cStringIO import StringIO
import sys

class DummyFile(object):
    pass

def middleware(application, **kw):

    def start_application(environ, start_response):
        started = []

        def detect_start_response(status, headers, exc_info=None):
            started.append(start_response(status, headers, exc_info))
            return started[0]
        
        try:
            app_iter = application(environ, detect_start_response)
            return catching_iter(app_iter)
        except:
            if not started:
                write = start_response('500 Internal Server Error',
                                       [('content-type', 'text/html')])
            else:
                write = started[0]
            dummy_file = DummyFile()
            dummy_file.write = write
            dummy_file = StringIO()
            hook = cgitb.Hook(**kw)
            hook.file = dummy_file
            hook(*sys.exc_info())
            return [dummy_file.getvalue()]

    def catching_iter(app_iter):
        if not app_iter:
            raise StopIteration
        try:
            for v in app_iter:
                yield v
        except:
            exc = sys.exc_info()
            dummy_file = StringIO()
            hook = cgitb.Hook(**kw)
            hook.file = dummy_file
            hook(*exc)
            yield dummy_file.getvalue()

    return start_application