wsgi/handler.py
brancholdstable
changeset 8746 88c71ad83d47
parent 8396 8d58fcf68539
child 8593 41259e1f9d48
--- a/wsgi/handler.py	Wed Aug 01 10:30:48 2012 +0200
+++ b/wsgi/handler.py	Thu Mar 21 18:13:31 2013 +0100
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -15,14 +15,16 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""WSGI request handler for cubicweb
+"""WSGI request handler for cubicweb"""
 
-"""
+
 
 __docformat__ = "restructuredtext en"
 
+from itertools import chain, repeat, izip
+
 from cubicweb import AuthenticationError
-from cubicweb.web import Redirect, DirectResponse, StatusResponse, LogOut
+from cubicweb.web import DirectResponse
 from cubicweb.web.application import CubicWebPublisher
 from cubicweb.wsgi.request import CubicWebWsgiRequest
 
@@ -71,7 +73,6 @@
     505: 'HTTP VERSION NOT SUPPORTED',
 }
 
-
 class WSGIResponse(object):
     """encapsulates the wsgi response parameters
     (code, headers and body if there is one)
@@ -79,7 +80,9 @@
     def __init__(self, code, req, body=None):
         text = STATUS_CODE_TEXT.get(code, 'UNKNOWN STATUS CODE')
         self.status =  '%s %s' % (code, text)
-        self.headers = [(str(k), str(v)) for k, v in req.headers_out.items()]
+        self.headers = list(chain(*[izip(repeat(k), v)
+                                    for k, v in req.headers_out.getAllRawHeaders()]))
+        self.headers = [(str(k), str(v)) for k, v in self.headers]
         if body:
             self.body = [body]
         else:
@@ -103,95 +106,31 @@
     def __init__(self, config, vreg=None):
         self.appli = CubicWebPublisher(config, vreg=vreg)
         self.config = config
-        self.base_url = None
-#         self.base_url = config['base-url'] or config.default_base_url()
-#         assert self.base_url[-1] == '/'
-#         self.https_url = config['https-url']
-#         assert not self.https_url or self.https_url[-1] == '/'
+        self.base_url = config['base-url']
+        self.https_url = config['https-url']
         self.url_rewriter = self.appli.vreg['components'].select_or_none('urlrewriter')
 
     def _render(self, req):
         """this function performs the actual rendering
-        XXX missing: https handling, url rewriting, cache management,
-                     authentication
         """
         if self.base_url is None:
             self.base_url = self.config._base_url = req.base_url()
-        # XXX https handling needs to be implemented
-        if req.authmode == 'http':
-            # activate realm-based auth
-            realm = self.config['realm']
-            req.set_header('WWW-Authenticate', [('Basic', {'realm' : realm })], raw=False)
         try:
-            self.appli.connect(req)
-        except Redirect, ex:
-            return self.redirect(req, ex.location)
-        path = req.path
-        if not path or path == "/":
-            path = 'view'
-        try:
-            result = self.appli.publish(path, req)
+            path = req.path
+            result = self.appli.handle_request(req, path)
         except DirectResponse, ex:
-            return WSGIResponse(200, req, ex.response)
-        except StatusResponse, ex:
-            return WSGIResponse(ex.status, req, ex.content)
-        except AuthenticationError:  # must be before AuthenticationError
-            return self.request_auth(req)
-        except LogOut:
-            if self.config['auth-mode'] == 'cookie':
-                # in cookie mode redirecting to the index view is enough :
-                # either anonymous connection is allowed and the page will
-                # be displayed or we'll be redirected to the login form
-                msg = req._('you have been logged out')
-#                 if req.https:
-#                     req._base_url =  self.base_url
-#                     req.https = False
-                url = req.build_url('view', vid='index', __message=msg)
-                return self.redirect(req, url)
-            else:
-                # in http we have to request auth to flush current http auth
-                # information
-                return self.request_auth(req, loggedout=True)
-        except Redirect, ex:
-            return self.redirect(req, ex.location)
-        if not result:
-            # no result, something went wrong...
-            self.error('no data (%s)', req)
-            # 500 Internal server error
-            return self.redirect(req, req.build_url('error'))
-        return WSGIResponse(200, req, result)
+            return ex.response
+        return WSGIResponse(req.status_out, req, result)
 
 
     def __call__(self, environ, start_response):
         """WSGI protocol entry point"""
-        req = CubicWebWsgiRequest(environ, self.appli.vreg, self.base_url)
+        req = CubicWebWsgiRequest(environ, self.appli.vreg)
         response = self._render(req)
         start_response(response.status, response.headers)
         return response.body
 
-    def redirect(self, req, location):
-        """convenience function which builds a redirect WSGIResponse"""
-        self.debug('redirecting to %s', location)
-        req.set_header('location', str(location))
-        return WSGIResponse(303, req)
 
-    def request_auth(self, req, loggedout=False):
-        """returns the appropriate WSGIResponse to require the user to log in
-        """
-#         if self.https_url and req.base_url() != self.https_url:
-#             return self.redirect(self.https_url + 'login')
-        if self.config['auth-mode'] == 'http':
-            code = 401 # UNAUTHORIZED
-        else:
-            code = 403 # FORBIDDEN
-        if loggedout:
-#             if req.https:
-#                 req._base_url =  self.base_url
-#                 req.https = False
-            content = self.appli.loggedout_content(req)
-        else:
-            content = self.appli.need_login_content(req)
-        return WSGIResponse(code, req, content)
 
     # these are overridden by set_log_methods below
     # only defining here to prevent pylint from complaining