1 # This file is part of the Enkel web programming library.
3 # Copyright (C) 2007 Espen Angell Kristiansen (espeak@users.sourceforge.net)
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 """ Error handling middleware. """
21 from BaseHTTPServer
import BaseHTTPRequestHandler
24 from enkel
.error
import EnkelUserError
, EnkelFatal
, EnkelWarning
25 from enkel
.error
.http
import HttpUserError
29 def handle_http_user_error(env
, start_response
):
30 e
= env
["wsgiorg.routing_args"][0][0]
31 status
= "%d %s" % (e
.NUMBER
,
32 BaseHTTPRequestHandler
.responses
[e
.NUMBER
])
33 start_response(status
, [("content-type", "text/html")])
34 yield "<html><body><h1>%(short_message)s</h1>"\
35 "%(long_message)s</body></html>" % e
.__dict
__
37 def handle_user_error(env
, start_response
):
38 e
= env
["wsgiorg.routing_args"][0][0]
40 start_response(status
, [("content-type", "text/html")])
41 yield "<html><body><h1>%(short_message)s</h1>"\
42 "%(long_message)s</body></html>" % e
.__dict
__
45 def handle_other_error(env
, start_response
):
46 start_response("500 error", [("content-type", "text/plain")])
47 return ["Internal server error"]
50 class ErrorHandler(object):
51 """ A WSGI middleware for handling errors.
52 It traps errors and forwards them to another WSGI app.
53 Before forwarding, the exception is added to the WSGI environ
54 dict like this: environ["wsgiorg.routing_args"] = ([exception], {}).
58 >>> from enkel.wsgiapp import WsgiApp
59 >>> class MyErrorHandler(WsgiApp)
60 ... def run_app(self, exception):
61 ... return str(exception)
63 def __init__(self
, app
, use_log
=True,
64 http_error
= handle_http_user_error
,
65 user_error
= handle_user_error
,
66 other_error
= handle_other_error
):
68 @param use_log: If True, log errors using the logging module.
69 HttpUserError and EnkelUserError are sent to
70 logging.debug and other exceptions are sent to
71 logging.error. exc_info=True is used in all 3 cases.
72 @param http_error: A wsgi app that handels any
73 L{enkel.error.http.HttpUserError} that is raised.
74 @param user_error: A wsgi app that handels any
75 L{enkel.error.EnkelUserError} that is raised.
76 @param other_error: A wsgi app that handels any error except
77 HttpUserError and EnkelUserError.
80 self
.use_log
= use_log
81 self
.handle_user_error
= user_error
82 self
.handle_http_error
= http_error
83 self
.handle_other_error
= other_error
85 def __call__(self
, env
, start_response
):
87 return self
.app(env
, start_response
)
88 except HttpUserError
, e
:
90 logging
.debug(str(e
), exc_info
=True)
91 env
["wsgiorg.routing_args"] = ([e
], {})
92 return self
.handle_http_error(env
, start_response
)
93 except EnkelUserError
, e
:
95 logging
.debug(str(e
), exc_info
=True)
96 env
["wsgiorg.routing_args"] = ([e
], {})
97 return self
.handle_user_error(env
, start_response
)
100 logging
.error(str(e
), exc_info
=True)
101 env
["wsgiorg.routing_args"] = ([e
], {})
102 return self
.handle_other_error(env
, start_response
)