summaryrefslogtreecommitdiff
path: root/pecan/middleware/debug.py
blob: 1a6a482bb4f8b7a6564b6de9881b9bdf56985955 (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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
__CONFIG_HELP__ = '''
<div class="traceback">
  <b>To disable this interface, set </b>
  <a target="window"
  href="https://pecan.readthedocs.org/en/latest/deployment.html#disabling-debug-mode">
    <pre>conf.app.debug = False</pre>
  </a>
</div>
'''  # noqa

try:
    import re
    from backlash.debug import DebuggedApplication

    class DebugMiddleware(DebuggedApplication):

        body_re = re.compile('(<body[^>]*>)', re.I)

        def debug_application(self, environ, start_response):
            for part in super(DebugMiddleware, self).debug_application(
                environ, start_response
            ):
                yield self.body_re.sub('\g<1>%s' % __CONFIG_HELP__, part)


except ImportError:
    from traceback import print_exc
    from pprint import pformat

    from mako.template import Template
    from six.moves import cStringIO as StringIO
    from webob import Response
    from webob.exc import HTTPException

    debug_template_raw = '''<html>
     <head>
      <title>Pecan - Application Error</title>
     <body>
      <header>
        <h1>
          An error occurred!
        </h1>
      </header>
      <div id="error-content">
        <p>
          %(config_help)s
          Pecan offers support for interactive debugging by installing the <a href="https://pypi.python.org/pypi/backlash" target="window">backlash</a> package:
          <br />
          <b><pre>pip install backlash</pre></b>
          ...and reloading this page.
        </p>
        <h2>Traceback</h2>
        <div id="traceback">
          <pre>${traceback}</pre>
        </div>
        <h2>WSGI Environment</h2>
        <div id="environ">
          <pre>${environment}</pre>
        </div>
      </div>
     </body>
    </html>
    ''' % {'config_help': __CONFIG_HELP__}  # noqa

    debug_template = Template(debug_template_raw)

    class DebugMiddleware(object):

        def __init__(self, app, *args, **kwargs):
            self.app = app

        def __call__(self, environ, start_response):
            try:
                return self.app(environ, start_response)
            except Exception as exc:
                # get a formatted exception
                out = StringIO()
                print_exc(file=out)

                # get formatted WSGI environment
                formatted_environ = pformat(environ)

                # render our template
                result = debug_template.render(
                    traceback=out.getvalue(),
                    environment=formatted_environ
                )

                # construct and return our response
                response = Response()
                if isinstance(exc, HTTPException):
                    response.status_int = exc.status
                else:
                    response.status_int = 500
                response.unicode_body = result
                return response(environ, start_response)