=== modified file 'repoze/bfg/router.py'
--- repoze/bfg/router.py	2010-01-25 12:37:07 +0000
+++ repoze/bfg/router.py	2010-03-08 21:52:32 +0000
@@ -1,6 +1,10 @@
 from zope.interface import implements
 from zope.interface import providedBy
 
+from webob.exc import HTTPClientError
+from webob.exc import HTTPNotFound
+from webob.exc import HTTPUnauthorized
+
 from repoze.bfg.interfaces import IDebugLogger
 from repoze.bfg.interfaces import IForbiddenView
 from repoze.bfg.interfaces import INotFoundView
@@ -130,20 +134,28 @@
                     response = view_callable(context, request)
 
             # handle exceptions raised during root finding and view lookup
-            except Forbidden, why:
+            except (Forbidden, HTTPUnauthorized), why:
                 try:
                     msg = why[0]
+                    # First argument may be None if it is HTTPUnauthorized
+                    if msg is None:
+                        msg = ''
                 except (IndexError, TypeError):
                     msg = ''
                 environ['repoze.bfg.message'] = msg
                 response = self.forbidden_view(context, request)
-            except NotFound, why:
+            except (NotFound, HTTPNotFound), why:
                 try:
                     msg = why[0]
+                    # First argument may be None if it is HTTPNotFound
+                    if msg is None:
+                        msg = ''
                 except (IndexError, TypeError):
                     msg = ''
                 environ['repoze.bfg.message'] = msg
                 response = self.notfound_view(context, request)
+            except HTTPClientError, why:
+                response = why
 
             # process the response
             has_listeners and registry.notify(NewResponse(response))

=== modified file 'repoze/bfg/tests/test_router.py'
--- repoze/bfg/tests/test_router.py	2010-01-24 08:45:35 +0000
+++ repoze/bfg/tests/test_router.py	2010-03-08 21:52:32 +0000
@@ -407,6 +407,46 @@
         self.assertEqual(start_response.status, '401 Unauthorized')
         self.assertEqual(environ['repoze.bfg.message'], 'unauthorized')
 
+    def test_call_view_raises_webob_exc_httpunauthorized(self):
+        from zope.interface import Interface
+        from zope.interface import directlyProvides
+        class IContext(Interface):
+            pass
+        from repoze.bfg.interfaces import IRequest
+        context = DummyContext()
+        directlyProvides(context, IContext)
+        self._registerTraverserFactory(context, subpath=[''])
+        response = DummyResponse()
+        from webob.exc import HTTPUnauthorized
+        view = DummyView(response, raise_=HTTPUnauthorized("unauthorized"))
+        environ = self._makeEnviron()
+        self._registerView(view, '', IRequest, IContext)
+        router = self._makeOne()
+        start_response = DummyStartResponse()
+        response = router(environ, start_response)
+        self.assertEqual(start_response.status, '401 Unauthorized')
+        self.assertEqual(environ['repoze.bfg.message'], 'unauthorized')
+
+    def test_call_view_raises_webob_exc_httpunauthorized_no_arg(self):
+        from zope.interface import Interface
+        from zope.interface import directlyProvides
+        class IContext(Interface):
+            pass
+        from repoze.bfg.interfaces import IRequest
+        context = DummyContext()
+        directlyProvides(context, IContext)
+        self._registerTraverserFactory(context, subpath=[''])
+        response = DummyResponse()
+        from webob.exc import HTTPUnauthorized
+        view = DummyView(response, raise_=HTTPUnauthorized())
+        environ = self._makeEnviron()
+        self._registerView(view, '', IRequest, IContext)
+        router = self._makeOne()
+        start_response = DummyStartResponse()
+        response = router(environ, start_response)
+        self.assertEqual(start_response.status, '401 Unauthorized')
+        self.assertEqual(environ['repoze.bfg.message'], '')
+
     def test_call_view_raises_notfound(self):
         from zope.interface import Interface
         from zope.interface import directlyProvides
@@ -426,6 +466,81 @@
         self.assertEqual(start_response.status, '404 Not Found')
         self.assertEqual(environ['repoze.bfg.message'], 'notfound')
 
+    def test_call_view_raises_webob_exc_httpnotfound(self):
+        from zope.interface import Interface
+        from zope.interface import directlyProvides
+        class IContext(Interface):
+            pass
+        from repoze.bfg.interfaces import IRequest
+        context = DummyContext()
+        directlyProvides(context, IContext)
+        self._registerTraverserFactory(context, subpath=[''])
+        response = DummyResponse()
+        from webob.exc import HTTPNotFound
+        view = DummyView(response, raise_=HTTPNotFound("notfound"))
+        environ = self._makeEnviron()
+        self._registerView(view, '', IRequest, IContext)
+        router = self._makeOne()
+        start_response = DummyStartResponse()
+        response = router(environ, start_response)
+        self.assertEqual(start_response.status, '404 Not Found')
+        self.assertEqual(environ['repoze.bfg.message'], 'notfound')
+
+    def test_call_view_raises_webob_exc_httpnotfound_no_arg(self):
+        from zope.interface import Interface
+        from zope.interface import directlyProvides
+        class IContext(Interface):
+            pass
+        from repoze.bfg.interfaces import IRequest
+        context = DummyContext()
+        directlyProvides(context, IContext)
+        self._registerTraverserFactory(context, subpath=[''])
+        response = DummyResponse()
+        from webob.exc import HTTPNotFound
+        view = DummyView(response, raise_=HTTPNotFound())
+        environ = self._makeEnviron()
+        self._registerView(view, '', IRequest, IContext)
+        router = self._makeOne()
+        start_response = DummyStartResponse()
+        response = router(environ, start_response)
+        self.assertEqual(start_response.status, '404 Not Found')
+        self.assertEqual(environ['repoze.bfg.message'], '')
+
+    def test_call_view_raises_webob_exc_httpclienterror(self):
+        from zope.interface import Interface
+        from zope.interface import directlyProvides
+        class IContext(Interface):
+            pass
+        from repoze.bfg.interfaces import IRequest
+        context = DummyContext()
+        directlyProvides(context, IContext)
+        self._registerTraverserFactory(context, subpath=[''])
+        from webob.exc import (
+            HTTPBadRequest, HTTPPaymentRequired, HTTPMethodNotAllowed,
+            HTTPNotAcceptable, HTTPProxyAuthenticationRequired,
+            HTTPRequestTimeout, HTTPConflict, HTTPGone,
+            HTTPLengthRequired, HTTPPreconditionFailed,
+            HTTPRequestEntityTooLarge, HTTPRequestURITooLong,
+            HTTPUnsupportedMediaType, HTTPRequestRangeNotSatisfiable,
+            HTTPExpectationFailed)
+        for exc_cls in (
+                HTTPBadRequest, HTTPPaymentRequired, HTTPMethodNotAllowed,
+                HTTPNotAcceptable, HTTPProxyAuthenticationRequired,
+                HTTPRequestTimeout, HTTPConflict, HTTPGone,
+                HTTPLengthRequired, HTTPPreconditionFailed,
+                HTTPRequestEntityTooLarge, HTTPRequestURITooLong,
+                HTTPUnsupportedMediaType, HTTPRequestRangeNotSatisfiable,
+                HTTPExpectationFailed):
+            exc = exc_cls()
+            response = DummyResponse()
+            view = DummyView(response, raise_=exc)
+            environ = self._makeEnviron()
+            self._registerView(view, '', IRequest, IContext)
+            router = self._makeOne()
+            start_response = DummyStartResponse()
+            response = router(environ, start_response)
+            self.assertEqual(start_response.status, exc.status)
+
     def test_call_request_has_global_response_headers(self):
         from zope.interface import Interface
         from zope.interface import directlyProvides
@@ -604,10 +719,11 @@
 
 class DummyView:
     def __init__(self, response, raise_unauthorized=False,
-                 raise_notfound=False):
+                 raise_notfound=False, raise_=None):
         self.response = response
         self.raise_unauthorized = raise_unauthorized
         self.raise_notfound = raise_notfound
+        self.raise_ = raise_
 
     def __call__(self, context, request):
         self.context = context
@@ -618,6 +734,8 @@
         if self.raise_notfound:
             from repoze.bfg.exceptions import NotFound
             raise NotFound('notfound')
+        if isinstance(self.raise_, Exception):
+            raise self.raise_
         return self.response
 
 class DummyRootFactory:

