Commit 2ca9cc69 authored by Julien Cristau's avatar Julien Cristau
Browse files

[web/httpcache] fix Last-Modified generation

time.mktime takes a time tuple in *local* time.  We have an UTC datetime coming
from the last_modified method, which we were interpreting as local time,
leading to hilarity.  Use calendar.timegm instead.

Add tests for Last-Modified generation of the 'download' and 'manage'
views.
parent 1694e6e9ff94
......@@ -19,7 +19,7 @@
__docformat__ = "restructuredtext en"
from time import mktime
from calendar import timegm
from datetime import datetime
class NoHTTPCacheManager(object):
......@@ -78,7 +78,7 @@ class EtagHTTPCacheManager(NoHTTPCacheManager):
# the front-end correctly generate it
# ("%a, %d %b %Y %H:%M:%S GMT" return localized date that
# twisted don't parse correctly)
req.set_header('Last-modified', mktime(mdate.timetuple()), raw=False)
req.set_header('Last-modified', timegm(mdate.timetuple()), raw=False)
class EntityHTTPCacheManager(EtagHTTPCacheManager):
......
......@@ -17,13 +17,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/>.
from datetime import datetime
from functools import partial
from logilab.common.testlib import unittest_main
from pytz import utc
from cubicweb.devtools.testlib import CubicWebTC, real_error_handling
from cubicweb import view
from cubicweb.predicates import is_instance
from cubicweb.web import http_headers
class IDownloadableUser(view.EntityAdapter):
__regid__ = 'IDownloadable'
......@@ -72,6 +75,9 @@ class IDownloadableTC(CubicWebTC):
get('content-disposition'))
self.assertEqual(['text/plain;charset=ascii'],
get('content-type'))
last_mod = http_headers.parseDateTime(get('last-modified')[0])
self.assertEqual(datetime.fromtimestamp(last_mod, tz=utc),
req.user.modification_date.replace(microsecond=0))
self.assertEqual(b'Babar is not dead!', data)
def test_header_with_space(self):
......@@ -146,4 +152,5 @@ class IDownloadableTC(CubicWebTC):
self.assertEqual(req.status_out, 500)
if __name__ == '__main__':
unittest_main()
from unittest import main
main()
......@@ -17,6 +17,8 @@
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
"""cubicweb.web.views.basecontrollers unit tests"""
import time
from six import text_type
from six.moves.urllib.parse import urlsplit, urlunsplit, urljoin, parse_qs
......@@ -31,7 +33,7 @@ from cubicweb.devtools.testlib import CubicWebTC
from cubicweb.devtools.webtest import CubicWebTestTC
from cubicweb.utils import json_dumps
from cubicweb.uilib import rql_for_eid
from cubicweb.web import Redirect, RemoteCallFailed
from cubicweb.web import Redirect, RemoteCallFailed, http_headers
import cubicweb.server.session
from cubicweb.server.session import Connection
from cubicweb.web.views.autoform import get_pending_inserts, get_pending_deletes
......@@ -44,9 +46,11 @@ from cubicweb.predicates import is_instance
class ViewControllerTC(CubicWebTestTC):
def test_view_ctrl_with_valid_cache_headers(self):
now = time.time()
resp = self.webapp.get('/manage')
self.assertEqual(resp.etag, 'manage/guests')
self.assertEqual(resp.status_code, 200)
self.assertGreaterEqual(http_headers.parseDateTime(resp.headers['Last-Modified']), int(now))
cache_headers = {'if-modified-since': resp.headers['Last-Modified'],
'if-none-match': resp.etag}
resp = self.webapp.get('/manage', headers=cache_headers)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment