etwist/request.py
changeset 5155 1dea6e0fdfc1
parent 4425 b9913205d91e
child 5423 e15abfdcce38
--- a/etwist/request.py	Wed Mar 31 17:02:51 2010 +0200
+++ b/etwist/request.py	Tue Apr 06 16:50:53 2010 +0200
@@ -9,22 +9,13 @@
 
 from datetime import datetime
 
-from twisted.web2 import http, http_headers
+from twisted.web import http
 
 from cubicweb.web import DirectResponse
 from cubicweb.web.request import CubicWebRequestBase
 from cubicweb.web.httpcache import GMTOFFSET
-
-def cleanup_files(dct, encoding):
-    d = {}
-    for k, infos in dct.items():
-        for (filename, mt, stream) in infos:
-            if filename:
-                # XXX: suppose that no file submitted <-> no filename
-                filename = unicode(filename, encoding)
-                mt = u'%s/%s' % (mt.mediaType, mt.mediaSubtype)
-                d[k] = (filename, mt, stream)
-    return d
+from cubicweb.web.http_headers import Headers
+from cubicweb.etwist.http import not_modified_response
 
 
 class CubicWebTwistedRequestAdapter(CubicWebRequestBase):
@@ -32,10 +23,15 @@
         self._twreq = req
         self._base_url = base_url
         super(CubicWebTwistedRequestAdapter, self).__init__(vreg, https, req.args)
-        self.form.update(cleanup_files(req.files, self.encoding))
-        # prepare output headers
-        self.headers_out = http_headers.Headers()
-        self._headers = req.headers
+        for key, (name, stream) in req.files.iteritems():
+            if name is None:
+                self.form[key] = (name, stream)
+            else:
+                self.form[key] = (unicode(name, self.encoding), stream)
+        # XXX can't we keep received_headers?
+        self._headers_in = Headers()
+        for k, v in req.received_headers.iteritems():
+            self._headers_in.addRawHeader(k, v)
 
     def base_url(self):
         """return the root url of the instance"""
@@ -63,29 +59,8 @@
         raise KeyError if the header is not set
         """
         if raw:
-            return self._twreq.headers.getRawHeaders(header, [default])[0]
-        return self._twreq.headers.getHeader(header, default)
-
-    def set_header(self, header, value, raw=True):
-        """set an output HTTP header"""
-        if raw:
-            # adding encoded header is important, else page content
-            # will be reconverted back to unicode and apart unefficiency, this
-            # may cause decoding problem (e.g. when downloading a file)
-            self.headers_out.setRawHeaders(header, [str(value)])
-        else:
-            self.headers_out.setHeader(header, value)
-
-    def add_header(self, header, value):
-        """add an output HTTP header"""
-        # adding encoded header is important, else page content
-        # will be reconverted back to unicode and apart unefficiency, this
-        # may cause decoding problem (e.g. when downloading a file)
-        self.headers_out.addRawHeader(header, str(value))
-
-    def remove_header(self, header):
-        """remove an output HTTP header"""
-        self.headers_out.removeHeader(header)
+            return self._headers_in.getRawHeaders(header, [default])[0]
+        return self._headers_in.getHeader(header, default)
 
     def _validate_cache(self):
         """raise a `DirectResponse` exception if a cached page along the way
@@ -95,11 +70,32 @@
             # Expires header seems to be required by IE7
             self.add_header('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
             return
-        try:
-            http.checkPreconditions(self._twreq, _PreResponse(self))
-        except http.HTTPError, ex:
-            self.info('valid http cache, no actual rendering')
-            raise DirectResponse(ex.response)
+
+        # when using both 'Last-Modified' and 'ETag' response headers
+        # (i.e. using respectively If-Modified-Since and If-None-Match request
+        # headers, see
+        # http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.4 for
+        # reference
+
+        cached_because_not_modified_since = False
+
+        last_modified = self.headers_out.getHeader('last-modified')
+        if last_modified is not None:
+            cached_because_not_modified_since = (self._twreq.setLastModified(last_modified)
+                                                 == http.CACHED)
+
+        if not cached_because_not_modified_since:
+            return
+
+        cached_because_etag_is_same = False
+        etag = self.headers_out.getRawHeaders('etag')
+        if etag is not None:
+            cached_because_etag_is_same = self._twreq.setETag(etag[0]) == http.CACHED
+
+        if cached_because_etag_is_same:
+            response = not_modified_response(self._twreq, self._headers_in)
+            raise DirectResponse(response)
+
         # Expires header seems to be required by IE7
         self.add_header('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
 
@@ -120,9 +116,3 @@
             # :/ twisted is returned a localized time stamp
             return datetime.fromtimestamp(mtime) + GMTOFFSET
         return None
-
-
-class _PreResponse(object):
-    def __init__(self, request):
-        self.headers = request.headers_out
-        self.code = 200