Isolate the default handler and extend its role
authorChristophe de Vienne <christophe@unlish.com>
Wed, 09 Jul 2014 17:14:32 +0200
changeset 11484 39768d122f97
parent 11483 7b7ed56bf2fb
child 11485 3905c9f06d0e
Isolate the default handler and extend its role The handler now does the job of CubicWebPublisher.main_handle_request() and calls CubicWebPublisher.core_handle(). Instead of using config.add_notfound_view, a catchall route is defined and the handler plugged to it. Related to #4291173
pyramid_cubicweb/__init__.py
pyramid_cubicweb/handler.py
--- a/pyramid_cubicweb/__init__.py	Sun Jul 06 18:25:31 2014 +0200
+++ b/pyramid_cubicweb/__init__.py	Wed Jul 09 17:14:32 2014 +0200
@@ -1,6 +1,5 @@
 from cubicweb.web.request import CubicWebRequestBase
 from cubicweb.cwconfig import CubicWebConfiguration
-from cubicweb.web.application import CubicWebPublisher
 from cubicweb import repoapi
 
 import cubicweb
@@ -63,25 +62,6 @@
     status_out = property(_get_status_out, _set_status_out)
 
 
-class PyramidSessionHandler(object):
-    """A CW Session handler that rely on the pyramid API to fetch the needed
-    informations"""
-
-    def __init__(self, appli):
-        self.appli = appli
-
-    def get_session(self, req):
-        return req._request.cw_session
-
-    def logout(self, req, goto_url):
-        del req._request.session['cubicweb.sessionid']
-        if not req.session.closed:
-            req.session.repo.close(req.session.sessionid)
-        for name, value in security.forget(req._request):
-            req.headers_out.setHeader(name, value)
-        raise cubicweb.web.LogOut(url=goto_url)
-
-
 def render_view(request, vid, **kwargs):
     vreg = request.registry['cubicweb.registry']
     # XXX The select() function could, know how to handle a pyramid
@@ -128,22 +108,6 @@
     return response
 
 
-class CubicWebPyramidHandler(object):
-    def __init__(self, appli):
-        self.appli = appli
-
-    def __call__(self, request):
-        req = request.cw_request()
-        result = self.appli.handle_request(req, req.path)
-        if result is not None:
-            request.response.body = result
-        request.response.headers.clear()
-        for k, v in req.headers_out.getAllRawHeaders():
-            for item in v:
-                request.response.headers.add(k, item)
-        return request.response
-
-
 def _cw_cnx(request):
     # XXX We should not need to use the session. A temporary one should be
     # enough. (by using repoapi.connect())
@@ -250,15 +214,4 @@
     config.add_route('hello', '/hello')
     config.add_view(hello_world, route_name='hello')
 
-    # Set up a defaut route to handle non-catched urls.
-    # This is to keep legacy compatibility for cubes that makes use of the
-    # cubicweb controllers.
-    cwappli = CubicWebPublisher(
-        cwconfig.repository(), cwconfig,
-        session_handler_fact=PyramidSessionHandler)
-    handler = CubicWebPyramidHandler(cwappli)
-
-    config.registry['cubicweb.appli'] = cwappli
-    config.registry['cubicweb.handler'] = handler
-
-    config.add_notfound_view(handler)
+    config.include('pyramid_cubicweb.handler')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyramid_cubicweb/handler.py	Wed Jul 09 17:14:32 2014 +0200
@@ -0,0 +1,86 @@
+from pyramid import security
+from pyramid.httpexceptions import HTTPSeeOther
+
+from cubicweb.web.application import CubicWebPublisher
+
+from cubicweb.web import (
+    StatusResponse, DirectResponse, Redirect, NotFound, LogOut,
+    RemoteCallFailed, InvalidSession, RequestError, PublishException)
+
+
+class PyramidSessionHandler(object):
+    """A CW Session handler that rely on the pyramid API to fetch the needed
+    informations"""
+
+    def __init__(self, appli):
+        self.appli = appli
+
+    def get_session(self, req):
+        return req._request.cw_session
+
+    def logout(self, req, goto_url):
+        raise LogOut(url=goto_url)
+
+
+class CubicWebPyramidHandler(object):
+    def __init__(self, appli):
+        self.appli = appli
+
+    def __call__(self, request):
+        """
+        Handler that mimics what CubicWebPublisher.main_handle_request does and
+        call CubicWebPyramidHandler.core_handle.
+
+        """
+        # XXX In a later version of this handler, we need to by-pass
+        # core_handle and CubicWebPublisher altogether so that the various CW
+        # exceptions are converted to their pyramid equivalent.
+
+        req = request.cw_request()
+        req.set_cnx(request.cw_cnx)
+
+        # XXX The main handler of CW forbid anonymous https connections
+        # I guess we can drop this "feature" but in doubt I leave this comment
+        # so we don't forget about it. (cdevienne)
+
+        try:
+            content = self.appli.core_handle(req, req.path)
+
+            if content is not None:
+                request.response.body = content
+            request.response.headers.clear()
+            for k, v in req.headers_out.getAllRawHeaders():
+                for item in v:
+                    request.response.headers.add(k, item)
+        except LogOut as ex:
+            # The actual 'logging out' logic should be in separated function
+            # that is accessible by the pyramid views
+            del req._request.session['cubicweb.sessionid']
+            if not req.session.closed:
+                req.session.repo.close(req.session.sessionid)
+            headers = security.forget(request)
+            raise HTTPSeeOther(ex.url, headers=headers)
+        except Redirect as ex:
+            raise HTTPSeeOther(ex.url)
+        # except AuthenticationError:
+        # XXX I don't think it makes sens to catch this ex here (cdevienne)
+
+        return request.response
+
+
+def includeme(config):
+    # Set up a defaut route to handle non-catched urls.
+    # This is to keep legacy compatibility for cubes that makes use of the
+    # cubicweb controllers.
+    cwconfig = config.registry['cubicweb.config']
+    repository = config.registry['cubicweb.repository']
+    cwappli = CubicWebPublisher(
+        repository, cwconfig,
+        session_handler_fact=PyramidSessionHandler)
+    handler = CubicWebPyramidHandler(cwappli)
+
+    config.registry['cubicweb.appli'] = cwappli
+    config.registry['cubicweb.handler'] = handler
+
+    config.add_route('catchall', pattern='*path')
+    config.add_view(handler, route_name='catchall')