[Checkins] SVN: bobo/branches/patrick-exc-fix/ don't allow exceptions to propagate by default

Patrick Strawderman patrick at zope.com
Mon Oct 17 16:38:00 EST 2011


Log message for revision 123100:
  don't allow exceptions to propagate by default
  

Changed:
  A   bobo/branches/patrick-exc-fix/
  U   bobo/branches/patrick-exc-fix/bobo/src/bobo.py
  U   bobo/branches/patrick-exc-fix/bobodoctestumentation/src/bobodoctestumentation/boboserver.test
  U   bobo/branches/patrick-exc-fix/bobodoctestumentation/src/bobodoctestumentation/more.txt

-=-
Modified: bobo/branches/patrick-exc-fix/bobo/src/bobo.py
===================================================================
--- bobo/trunk/bobo/src/bobo.py	2011-10-17 14:51:36 UTC (rev 123099)
+++ bobo/branches/patrick-exc-fix/bobo/src/bobo.py	2011-10-17 21:37:59 UTC (rev 123100)
@@ -34,10 +34,13 @@
 
 __metaclass__ = type
 
+import logging
 import re
 import sys
 import webob
 
+log = logging.getLogger(__name__)
+
 bbbbad_errors = KeyboardInterrupt, SystemExit, MemoryError
 
 _default_content_type = 'text/html; charset=UTF-8'
@@ -193,12 +196,12 @@
             return self.method_not_allowed(request, method, v.allowed)
         except MissingFormVariable, v:
             return self.missing_form_variable(request, method, v.name)
-        except NotFound, v:
+        except NotFound:
             return self.not_found(request, method)
         except bbbbad_errors:
             raise
         except Exception:
-            if not hasattr(self, 'exception'):
+            if request.environ.get("x-wsgiorg.throw_errors"):
                 raise
             return self.exception(request, method, sys.exc_info())
 
@@ -278,6 +281,13 @@
             "Method Not Allowed", "Invalid request method: %s" % method,
             [('Allow', ', '.join(sorted(methods)))])
 
+    def exception(self, request, method, exc_info):
+        log.exception(request.url)
+        return _err_response(
+            500, method,
+            "Internal Server Error", "An error occurred.")
+
+
 def _err_response(status, method, title, message, headers=()):
     response = webob.Response(status=status, headerlist=headers or [])
     response.content_type = 'text/html; charset=UTF-8'

Modified: bobo/branches/patrick-exc-fix/bobodoctestumentation/src/bobodoctestumentation/boboserver.test
===================================================================
--- bobo/trunk/bobodoctestumentation/src/bobodoctestumentation/boboserver.test	2011-10-17 14:51:36 UTC (rev 123099)
+++ bobo/branches/patrick-exc-fix/bobodoctestumentation/src/bobodoctestumentation/boboserver.test	2011-10-17 21:37:59 UTC (rev 123100)
@@ -138,7 +138,7 @@
     Serving ['foo', 'bobo__main__'] on port 80...
     serve_forever '' 80
 
-    >>> try: req('/x')
+    >>> try: req('/x', environ={"x-wsgiorg.throw_errors": "1"})
     ... except Exception, v: print 'raised', v
     ... else: print '???'
     ... # doctest: +ELLIPSIS

Modified: bobo/branches/patrick-exc-fix/bobodoctestumentation/src/bobodoctestumentation/more.txt
===================================================================
--- bobo/trunk/bobodoctestumentation/src/bobodoctestumentation/more.txt	2011-10-17 14:51:36 UTC (rev 123099)
+++ bobo/branches/patrick-exc-fix/bobodoctestumentation/src/bobodoctestumentation/more.txt	2011-10-17 21:37:59 UTC (rev 123100)
@@ -541,7 +541,7 @@
 Error response generation
 -------------------------
 
-There are three cases for which bobo has to generate error responses:
+There are four cases for which bobo has to generate error responses:
 
 1. When a resource can't be found, bobo generates a "404 Not Found"
    response.
@@ -551,6 +551,9 @@
    parameter and the parameter is isn't in the given form data, bobo
    generates a "405 Forbidden" response with a body that indicates the
    missing parameter.
+4. When a route handler raises an exception, bobo generates a
+   "500 Internal Server Error" response.
+   
 
 For each of these responses, bobo generates a small HTML body.
 
@@ -745,11 +748,14 @@
 Uncaught exceptions
 ~~~~~~~~~~~~~~~~~~~
 
-Normally, bobo let's uncaught exceptions propagate to calling
-middleware or servers.  If you want to provide custom handling of
-uncaught exceptions, you can include an ``exception`` method in
-the object you give to ``bobo_errors``.
+Normally, bobo does not let uncaught exceptions propagate; however,
+if the `x-wsgiorg.throw_errors` key is present in the environment,
+any uncaught exceptions will be raised.
 
+If you want to provide custom handling of uncaught exceptions,
+you can include an ``exception`` method in the object you
+give to ``bobo_errors``.
+
 ::
 
    import bobo, webob
@@ -780,11 +786,32 @@
     >>> update_module('badapp',
     ...   'import bobo\n\n at bobo.resource\ndef bad(x, y):\n  pass\n')
     >>> app = webtest.TestApp(bobo.Application(bobo_resources='badapp'))
-    >>> app.get('/bad.html')
+    >>> print app.get('/bad.html', status=500).body
+    <html>
+    <head><title>Internal Server Error</title></head>
+    <body>An error occurred.</body>
+    </html>
+    <BLANKLINE>
+
+   The default exception handler logs the traceback.
+
+    >>> import logging
+    >>> import sys
+    >>> handler = logging.StreamHandler(sys.stdout)
+    >>> bobo.log.addHandler(handler)
+    >>> app.get('/bad.html', status=500) and None # doctest: +ELLIPSIS
+    http://localhost/bad.html
     Traceback (most recent call last):
     ...
     TypeError: bad() takes exactly 2 arguments (1 given)
+    
+    >>> bobo.log.removeHandler(handler)
 
+    >>> app.get("/bad.html", extra_environ={"x-wsgiorg.throw_errors": "1"})
+    Traceback (most recent call last):
+    ...
+    TypeError: bad() takes exactly 2 arguments (1 given)
+
     >>> app = webtest.TestApp(bobo.Application(
     ...    bobo_resources='badapp', bobo_errors='errorsample2:Errors()'))
     >>> app.get('/bad.html', status=500).body



More information about the checkins mailing list