def ZCache_set(self, ob, data, view_name, keywords, mtime_func): # Note the blatant ignorance of view_name and keywords. # Standard HTTP accelerators are not able to make use of this # data. mtime_func is also ignored because using "now" for # Last-Modified is as good as using any time in the past. REQUEST = ob.REQUEST RESPONSE = REQUEST.RESPONSE anon = 1 u = REQUEST.get('AUTHENTICATED_USER', None) if u is not None: if u.getUserName() != 'Anonymous User': anon = 0 phys_path = ob.getPhysicalPath() if self.hit_counts.has_key(phys_path): hits = self.hit_counts[phys_path] else: self.hit_counts[phys_path] = hits = [0,0] if anon: hits[0] = hits[0] + 1 else: hits[1] = hits[1] + 1 if not anon and self.anonymous_only: return # Set HTTP Expires and Cache-Control headers seconds=self.interval expires=rfc1123_date(time.time() + seconds) RESPONSE.setHeader('Last-Modified',rfc1123_date(time.time())) RESPONSE.setHeader('Cache-Control', 'max-age=%d' % seconds) RESPONSE.setHeader('Expires', expires)
def test__OldCacheHeaders(self): from Products.CMFCore.utils import _OldCacheHeaders _FILE_MOD_TIME = 1000000000 _FILE_RFC_DATE = rfc1123_date(_FILE_MOD_TIME) class Obj(Implicit): def modified(self): return DateTime(_FILE_MOD_TIME) # date < _file_mod_time env = {'HTTP_IF_MODIFIED_SINCE': rfc1123_date(_FILE_MOD_TIME - 1)} obj = makerequest(Obj(), environ=env) _OldCacheHeaders(obj) self.assertEqual(obj.REQUEST.RESPONSE.getHeader('Last-Modified'), _FILE_RFC_DATE) # date > _file_mod_time env = {'HTTP_IF_MODIFIED_SINCE': rfc1123_date(_FILE_MOD_TIME + 1)} obj = makerequest(Obj(), environ=env) _OldCacheHeaders(obj) self.assertEqual(obj.REQUEST.RESPONSE.getHeader('Last-Modified'), None) # invalid date env = {'HTTP_IF_MODIFIED_SINCE': 'Fri, 37 Feb 3121 29:64:46'} obj = makerequest(Obj(), environ=env) _OldCacheHeaders(obj) self.assertEqual(obj.REQUEST.RESPONSE.getHeader('Last-Modified'), _FILE_RFC_DATE)
def test_set_expiry_header(self): """ if you register the image with @set_expiry_header=True, expect another header called 'Expires' """ class MyProduct: pass registerImage(MyProduct, "image.jpg", rel_path="tests", set_expiry_header=True) instance = MyProduct() img = getattr(instance, "image.jpg") REQUEST = self.app.REQUEST RESPONSE = REQUEST.RESPONSE bin_content = img.index_html(REQUEST, RESPONSE) self.assertEqual( RESPONSE.getHeader("last-modified"), rfc1123_date(os.stat(right_here("image.jpg"))[stat.ST_MTIME]) ) self.assertEqual(RESPONSE.getHeader("cache-control"), "public,max-age=3600") # default self.assertEqual(RESPONSE.getHeader("content-type"), "image/jpeg") self.assertEqual(int(RESPONSE.getHeader("content-length")), os.stat(right_here("image.jpg"))[stat.ST_SIZE]) self.assertEqual(RESPONSE.getHeader("expires"), rfc1123_date(time() + img.max_age)) # expect a expires header for the infinitely cached alias img_infinite_name = instance.misc_infinite_aliases["image.jpg"] img_infinite = getattr(instance, img_infinite_name) bin_content = img_infinite.index_html(REQUEST, RESPONSE) self.assertEqual(RESPONSE.getHeader("expires"), rfc1123_date(time() + EXPIRY_INFINITY))
def assertExpiresEqual(self, expires, moment): """Assert that the Expires header is equal to a moment or one second earlier or later. Should work for other headers too, but Expires is the most common, at least in these tests. There are some spurious test failures because 'now' is calculated, then a request is made and some headers are set, but this takes slightly too long and the resulting Expires header is one second after 'now'. - expires: usually response.getHeader('Expires') - moment: number of seconds, usually DateTime().timeTime(). NOT an rfc1123 date """ if expires == rfc1123_date(moment): return if expires == rfc1123_date(moment + 1): return if expires == rfc1123_date(moment - 1): return # We have a failure. Call the method that would originally be # called. self.assertEqual(expires, rfc1123_date(moment))
def __call__(self): logger.debug( u'Processing request from ' + self.request.environ['REMOTE_ADDR']) if self._needs_hard_refresh(): return '' if self._not_modified(): return '' # the Expires header will help us control how often clients # will ask for a page; this supercedes the value defined on our # JavaScript code so, if we put here a value above 1 minute, # clients will wait that time before requesting the page again expires = rfc1123_date(time() + 59) # page expires in 59 seconds last_modified = rfc1123_date(self.context.modified()) self.request.RESPONSE.setHeader('Cache-Control', 'public') self.request.RESPONSE.setHeader('Expires', expires) self.request.RESPONSE.setHeader('Last-Modified', last_modified) # https://github.com/plone/plone.protect/issues/64 self.latest_journalentries = self.get_latest_journalentries() if len(self.latest_journalentries) == 0: return '' return self.index()
def testIfModSince(self): now = time.time() e = {'SERVER_NAME': 'foo', 'SERVER_PORT': '80', 'REQUEST_METHOD': 'GET'} # not modified since t_notmod = rfc1123_date(now) e['HTTP_IF_MODIFIED_SINCE'] = t_notmod out = BytesIO() resp = HTTPResponse(stdout=out) req = HTTPRequest(sys.stdin, e, resp) data = self.file.index_html(req, resp) self.assertEqual(resp.getStatus(), 304) self.assertEqual(data, b'') # modified since t_mod = rfc1123_date(now - 100) e['HTTP_IF_MODIFIED_SINCE'] = t_mod out = BytesIO() resp = HTTPResponse(stdout=out) req = HTTPRequest(sys.stdin, e, resp) data = self.file.index_html(req, resp) self.assertEqual(resp.getStatus(), 200) self.assertEqual(data, bytes(self.file.data))
def test_basic_BetterImageFile(self): """ test the BetterImageFile class """ class MyProduct: pass mtime = os.stat(right_here("image.jpg"))[stat.ST_MTIME] registerImage(MyProduct, right_here("image.jpg"), rel_path="tests") instance = MyProduct() img = getattr(instance, "image.jpg", None) self.assertNotEqual(img, None) # expect also that it creates a file called # image.<mttime of file>.jpg img_infinite = getattr(instance, "image.%s.jpg" % mtime, None) self.assertNotEqual(img_infinite, None) # expect this to be a BetterImageFile instance self.assertEqual(img.__class__, BetterImageFile) self.assertTrue(isinstance(img, BetterImageFile)) # rendering it should return a big binary content load self.assertEqual(len(str(img)), os.stat(right_here("image.jpg"))[stat.ST_SIZE]) self.assertEqual(len(str(img_infinite)), os.stat(right_here("image.jpg"))[stat.ST_SIZE]) # there should now be a dict set in the instance called misc_infinite_aliases # which links 'image.jpg' to 'image.<mttime of file>.jpg' self.assertTrue(bool(getattr(instance, "misc_infinite_aliases"))) aliases = instance.misc_infinite_aliases self.assertTrue(isinstance(aliases, dict)) self.assertTrue("image.jpg" in aliases) self.assertEqual(aliases.get("image.jpg"), "image.%s.jpg" % mtime) # if we render it with img.index_html() expect certain headers to be set REQUEST = self.app.REQUEST RESPONSE = REQUEST.RESPONSE bin_content = img.index_html(REQUEST, RESPONSE) self.assertEqual( RESPONSE.getHeader("last-modified"), rfc1123_date(os.stat(right_here("image.jpg"))[stat.ST_MTIME]) ) self.assertEqual(RESPONSE.getHeader("cache-control"), "public,max-age=3600") # default self.assertEqual(RESPONSE.getHeader("content-type"), "image/jpeg") self.assertEqual(int(RESPONSE.getHeader("content-length")), os.stat(right_here("image.jpg"))[stat.ST_SIZE]) # if we render the infinitely cached one we can expect different headers bin_content = img_infinite.index_html(REQUEST, RESPONSE) self.assertEqual( RESPONSE.getHeader("last-modified"), rfc1123_date(os.stat(right_here("image.jpg"))[stat.ST_MTIME]) ) self.assertEqual(RESPONSE.getHeader("cache-control"), "public,max-age=%s" % EXPIRY_INFINITY) # self.assertEqual(RESPONSE.getHeader("content-type"), "image/jpeg") self.assertEqual(int(RESPONSE.getHeader("content-length")), os.stat(right_here("image.jpg"))[stat.ST_SIZE])
def testDebugModeSplitting2(self): self.tool.registerKineticStylesheet("ham") now = DateTime() days = 7 soon = now + days self.tool.setDebugMode(True) # Publish in debug mode response = self.publish(self.toolpath + "/ham") self.failIfEqual(response.getHeader("Expires"), rfc1123_date(soon.timeTime())) self.assertEqual(response.getHeader("Expires"), rfc1123_date(now.timeTime())) self.assertEqual(response.getHeader("Cache-Control"), "max-age=0")
def testDebugModeSplitting2(self): self.tool.registerKineticStylesheet('ham') now = DateTime() days = 7 soon = now + days self.tool.setDebugMode(True) # Publish in debug mode response = self.publish(self.toolpath+'/ham') self.tool.setDebugMode(False) self.failIfEqual(response.getHeader('Expires'), rfc1123_date(soon.timeTime())) self.assertEqual(response.getHeader('Expires'), rfc1123_date(now.timeTime())) self.assertEqual(response.getHeader('Cache-Control'), 'max-age=0')
def test_maxAge( self ): policy = self._makePolicy( 'aged', max_age_secs=86400 ) context = self._makeContext() headers = policy.getHeaders( context ) self.assertEqual( len( headers ), 3 ) self.assertEqual( headers[0][0].lower() , 'last-modified' ) self.assertEqual( headers[0][1] , rfc1123_date(self._epoch.timeTime()) ) self.assertEqual( headers[1][0].lower() , 'expires' ) self.assertEqual( headers[1][1] , rfc1123_date((self._epoch+1).timeTime()) ) self.assertEqual( headers[2][0].lower() , 'cache-control' ) self.assertEqual( headers[2][1] , 'max-age=86400' )
def _if_modified_since_request_handler(self, REQUEST, RESPONSE): # HTTP If-Modified-Since header handling: return True if # we can handle this request by returning a 304 response header = REQUEST.get_header('If-Modified-Since', None) if header is not None: header = header.split(';')[0] # Some proxies seem to send invalid date strings for this # header. If the date string is not valid, we ignore it # rather than raise an error to be generally consistent # with common servers such as Apache (which can usually # understand the screwy date string as a lucky side effect # of the way they parse it). # This happens to be what RFC2616 tells us to do in the face of an # invalid date. try: mod_since = int(DateTime(header).timeTime()) except Exception: mod_since = None if mod_since is not None: if self._p_mtime: last_mod = int(self._p_mtime) else: last_mod = 0 if last_mod > 0 and last_mod <= mod_since: RESPONSE.setHeader('Last-Modified', rfc1123_date(self._p_mtime)) RESPONSE.setHeader('Content-Type', self.content_type) RESPONSE.setHeader('Accept-Ranges', 'bytes') RESPONSE.setStatus(304) return True
def HEAD(self, REQUEST, RESPONSE): """Retrieve resource information without a response body.""" self.dav__init(REQUEST, RESPONSE) content_type = None if hasattr(self, 'content_type'): content_type = absattr(self.content_type) if content_type is None: url = urlfix(REQUEST['URL'], 'HEAD') name = unquote(filter(None, url.split('/')[-1])) content_type, encoding = mimetypes.guess_type(name) if content_type is None: if hasattr(self, 'default_content_type'): content_type = absattr(self.default_content_type) if content_type is None: content_type = 'application/octet-stream' RESPONSE.setHeader('Content-Type', content_type.lower()) if hasattr(aq_base(self), 'get_size'): RESPONSE.setHeader('Content-Length', absattr(self.get_size)) if hasattr(self, '_p_mtime'): mtime = rfc1123_date(self._p_mtime) RESPONSE.setHeader('Last-Modified', mtime) if hasattr(aq_base(self), 'http__etag'): etag = self.http__etag(readonly=1) if etag: RESPONSE.setHeader('Etag', etag) RESPONSE.setStatus(200) return RESPONSE
def test_index_html_with_304_and_caching(self): # See collector #355 cpm = DummyCachingManager() getSiteManager().registerUtility(cpm, ICachingPolicyManager) original_len = len(self.RESPONSE.headers) _path, ref = self._extractFile() self.app.image = self._makeOne('test_image', 'test_image.gif', file=ref) image = self.app.image transaction.savepoint(optimistic=True) mod_time = image.modified() self.REQUEST.environ['IF_MODIFIED_SINCE' ] = '%s;' % rfc1123_date(mod_time + 1) data = image.index_html(self.REQUEST, self.RESPONSE) self.assertEqual(data, '') self.assertEqual(self.RESPONSE.getStatus(), 304) headers = self.RESPONSE.headers self.failUnless(len(headers) >= original_len + 3) self.failUnless('foo' in headers.keys()) self.failUnless('bar' in headers.keys()) self.assertEqual(headers['test_path'], '/test_image')
def __call__(self): """Download the file""" self.setCacheHeaders() RESPONSE=self.REQUEST['RESPONSE'] status = "" if WITH_LNK_PARSER: # get the target file into a MS-Link status, lnkpath = lnkparse(self.getRelativePath(), self.getFilesystemPath()) if status == 'OK': RESPONSE.redirect('%s/%s' % (self.REQUEST.URL2, lnkpath)) return elif status == 'ERROR_RELPATH': # File without a valid target file RESPONSE.redirect(self.absolute_url() + '/symbolic_link_notfound') return elif status == 'ERROR_OUTREFLECTPATH': # File without a valid target file RESPONSE.redirect(self.absolute_url() + '/targetfile_out_basepath') return # - Return file content iterator = filestream_iterator(self.getFilesystemPath(), 'rb') RESPONSE.setHeader('Last-Modified', rfc1123_date(self.getStatus()[ST_MTIME])) RESPONSE.setHeader('Content-Type', self.Format()) RESPONSE.setHeader('Content-Length', len(iterator)) return iterator
def __status_info(self): certificate = False document = self.restrictedTraverse(self.document_url) try: memcached_dict = self.getPortalObject().portal_memcached.getMemcachedDict( key_prefix='slap_tool', plugin_path='portal_memcached/default_memcached_plugin') try: d = memcached_dict[document.getReference()] except KeyError: d = { "user": "******", 'created_at': '%s' % rfc1123_date(DateTime()), "text": "#error no data found for %s" % document.getReference() } else: d = json.loads(d) except Exception: LOG('SlapOSRestApiV1', ERROR, 'Problem while trying to generate status information:', error=True) self.REQUEST.response.setStatus(500) self.REQUEST.response.setBody(jsonify({'error': 'There is system issue, please try again later.'})) else: d['@document'] = self.document_url self.REQUEST.response.setStatus(200) self.REQUEST.response.setHeader('Cache-Control', 'max-age=300, private') self.REQUEST.response.setBody(jsonify(d)) return self.REQUEST.response
def _FSCacheHeaders(obj): # Old-style setting of modified headers for FS-based objects REQUEST = getattr(obj, 'REQUEST', None) if REQUEST is None: return False RESPONSE = REQUEST.RESPONSE header = REQUEST.getHeader('If-Modified-Since', None) # Reduce resolution to one second, else if-modified-since would # always be older if system resolution is higher last_mod = int(obj._file_mod_time) if header is not None: header = header.split(';')[0] # Some proxies seem to send invalid date strings for this # header. If the date string is not valid, we ignore it # rather than raise an error to be generally consistent # with common servers such as Apache (which can usually # understand the screwy date string as a lucky side effect # of the way they parse it). try: mod_since = DateTime(header) mod_since = long(mod_since.timeTime()) except (TypeError, DateTimeError): mod_since = None if mod_since is not None: if last_mod > 0 and last_mod <= mod_since: RESPONSE.setStatus(304) return True #Last-Modified will get stomped on by a cache policy if there is #one set.... RESPONSE.setHeader('Last-Modified', rfc1123_date(last_mod))
def HEAD(self, REQUEST, RESPONSE): """Retrieve resource information without a response body.""" self.dav__init(REQUEST, RESPONSE) content_type = None if hasattr(self, 'content_type'): content_type = absattr(self.content_type) if content_type is None: url = urlfix(REQUEST['URL'], 'HEAD') name = unquote([_f for _f in url.split('/') if _f][-1]) content_type, encoding = mimetypes.guess_type(name) if content_type is None: if hasattr(self, 'default_content_type'): content_type = absattr(self.default_content_type) if content_type is None: content_type = 'application/octet-stream' RESPONSE.setHeader('Content-Type', content_type.lower()) if hasattr(aq_base(self), 'get_size'): RESPONSE.setHeader('Content-Length', absattr(self.get_size)) if hasattr(self, '_p_mtime'): mtime = rfc1123_date(self._p_mtime) RESPONSE.setHeader('Last-Modified', mtime) if hasattr(aq_base(self), 'http__etag'): etag = self.http__etag(readonly=1) if etag: RESPONSE.setHeader('Etag', etag) RESPONSE.setStatus(200) return RESPONSE
def testContentLengthHeaders(self): # Test that the main page retains its content-type self.setRoles(['Manager']) request = self.portal.REQUEST request.environ['IF_MODIFIED_SINCE'] = rfc1123_date( (DateTime() - 60.0 / (24.0 * 3600.0))) # if modified in the last minute #print self.portal.REQUEST.get_header('If-Modified-Since') self.tool.registerStylesheet('test_rr_1.css') self.portal.addDTMLMethod('testmethod', file="""/* YES WE ARE RENDERED */""") self.tool.registerStylesheet('testmethod') self.portal.addDTMLMethod('testmethod2', file="""/* YES WE ARE RENDERED 2 */""") self.tool.registerStylesheet('testmethod2') # we also add an fsfile for good measure self.tool.registerStylesheet('test_rr_2.css') rs = self.tool.getEvaluatedResources(self.portal) self.assertEqual(len(rs), 1) response = self.publish(self.toolpath + '/' + rs[0].getId()) self.assertEqual(response.getHeader('Content-Type'), 'text/css;charset=utf-8') #print str(response) self.assertEqual(int(response.getHeader('content-length')), len(response.getBody())) self.assertEqual(response.getStatus(), 200)
def __init__(self, path, _prefix): """ Instantiate *without* reading the file. o 'path' should normally be relative to the directory containing the module instantiating us. o '_prefix' should normally be the 'globals()' of the module instantiating us. """ if isinstance(_prefix, basestring): self._filepath = os_path.join(_prefix, path) else: self._package = _prefix['__name__'] self._entry_subpath = path self.__name__= os_path.split(path)[1] if DevelopmentMode: # In development mode, a shorter time is handy max_age = 60 # One minute else: # A longer time reduces latency in production mode max_age = 3600 # One hour last_dot = path.rfind('.') + 1 # guess content type until we read the file self._content_type = 'image/%s' % path[last_dot:] self._last_modified = DateTime() self._last_modified_str = rfc1123_date() # "now" self._cache_control = 'public,max-age=%d' % max_age
def __init__(self, path, _prefix=None, max_age_development=60, max_age_production=3600, content_type=None, set_expiry_header=True): if _prefix is None: _prefix = getConfiguration().softwarehome elif type(_prefix) is not type(''): _prefix = package_home(_prefix) path = os.path.join(_prefix, path) self.path = self.original_path = path self.set_expiry_header = set_expiry_header if DevelopmentMode: # In development mode, a shorter time is handy max_age = max_age_development else: # A longer time reduces latency in production mode max_age = max_age_production self.max_age = max_age self.cch = 'public,max-age=%d' % max_age data = open(path, 'rb').read() if content_type is None: content_type, __ = my_guess_content_type(path, data) if content_type: self.content_type=content_type else: raise ValueError, "content_type not set or couldn't be guessed" #self.content_type='text/plain' self.__name__=path[path.rfind('/')+1:] self.lmt=float(os.stat(path)[8]) or time.time() self.lmh=rfc1123_date(self.lmt) self.content_size = os.stat(path)[stat.ST_SIZE]
def getHeaders( self, expr_context ): """ Does this request match our predicate? If so, return a sequence of caching headers as ( key, value ) tuples. Otherwise, return an empty sequence. """ headers = [] if self._predicate( expr_context ): mtime = self._mtime_func( expr_context ) if type( mtime ) is type( '' ): mtime = DateTime( mtime ) if mtime is not None: mtime_flt = mtime.timeTime() mtime_str = rfc1123_date(mtime_flt) headers.append( ( 'Last-modified', mtime_str ) ) control = [] if self._max_age_secs is not None: now = expr_context.vars[ 'time' ] exp_time_str = rfc1123_date(now.timeTime() + self._max_age_secs) headers.append( ( 'Expires', exp_time_str ) ) control.append( 'max-age=%d' % self._max_age_secs ) if self._no_cache: control.append( 'no-cache' ) if self._no_store: control.append( 'no-store' ) if self._must_revalidate: control.append( 'must-revalidate' ) if control: headers.append( ( 'Cache-control', ', '.join( control ) ) ) if self.getVary(): headers.append( ( 'Vary', self._vary ) ) if self.getETagFunc(): headers.append( ( 'ETag', self._etag_func( expr_context ) ) ) return headers
def map_icon(self, rating, type, RESPONSE, number=None): ret = map_icon(rating, type, number) RESPONSE.setHeader('Content-Type', 'image/png') RESPONSE.setHeader('Cache-Control', 'public,max-age=86400') RESPONSE.setHeader('Expires', rfc1123_date(time() + 86400)) return ret
def test_lookupMatchBar( self ): mgr = self._makeOneWithPolicies() headers = mgr.getHTTPCachingHeaders( content=DummyContent2(self._epoch) , view_method='foo_view' , keywords={ 'bar' : 1 } , time=self._epoch ) self.assertEqual( len( headers ), 3 ) self.assertEqual( headers[0][0].lower() , 'last-modified' ) self.assertEqual( headers[0][1] , rfc1123_date(self._epoch.timeTime()) ) self.assertEqual( headers[1][0].lower() , 'expires' ) self.assertEqual( headers[1][1] , rfc1123_date(self._epoch.timeTime()) ) self.assertEqual( headers[2][0].lower() , 'cache-control' ) self.assertEqual( headers[2][1], 'max-age=0' )
def __call__(self, *args, **kwargs): """ edit.css """ self.request.RESPONSE.setHeader("content-type", "text/css") expires = rfc1123_date((DateTime() + 365).timeTime()) self.request.RESPONSE.setHeader("Expires", expires) self.request.RESPONSE.setHeader("Cache-Control", "max-age=%d" % self.duration) return self.get_content()
def test_empty(self): policy = self._makePolicy('empty') context = self._makeContext() headers = policy.getHeaders(context) self.assertEqual(len(headers), 1) self.assertEqual(headers[0][0], 'Last-modified') self.assertEqual(headers[0][1], rfc1123_date(self._epoch.timeTime()))
def test_06_Check_LastModified_Header(self): """Checks that Last-Modified header set by caching policy manager is correctly filled with getModificationDate of content. This test check "unauthenticated" Policy installed by erp5_web: """ request = self.portal.REQUEST website = self.setupWebSite() path = website.absolute_url_path() response = self.publish(path) self.assertTrue(response.getHeader('x-cache-headers-set-by'), 'CachingPolicyManager: /erp5/caching_policy_manager') web_section_portal_type = 'Web Section' web_section = website.newContent(portal_type=web_section_portal_type) path = web_section.absolute_url_path() response = self.publish(path) self.assertTrue(response.getHeader('x-cache-headers-set-by'), 'CachingPolicyManager: /erp5/caching_policy_manager') # unauthenticated document_portal_type = 'Text' document_module = self.portal.getDefaultModule(document_portal_type) document = document_module.newContent(portal_type=document_portal_type, reference='NXD-Document-TEXT.Cache') document.publish() self.tic() path = website.absolute_url_path() + '/NXD-Document-TEXT.Cache' response = self.publish(path) last_modified_header = response.getHeader('Last-Modified') self.assertTrue(last_modified_header) from App.Common import rfc1123_date # Convert the Date into string according RFC 1123 Time Format modification_date = rfc1123_date(document.getModificationDate()) self.assertEqual(modification_date, last_modified_header) # Upload a presentation with 3 pages. upload_file = makeFileUpload('P-DMS-Presentation.3.Pages-001-en.odp') document = document_module.newContent(portal_type='Presentation', file=upload_file) reference = 'P-DMS-Presentation.3.Pages' document.edit(reference=reference) document.publish() self.tic() website_url = website.absolute_url_path() # Check we can access to the 3 drawings converted into images. # Those images can be accessible through extensible content # url : path-of-document + '/' + 'img' + page-index + '.png' for i in range(3): path = '/'.join((website_url, reference, 'img%s.png' % i)) response = self.publish(path) policy_list = self.portal.caching_policy_manager.listPolicies() policy = [policy for policy in policy_list\ if policy[0] == 'unauthenticated'][0] self.assertEquals(response.getHeader('Content-Type'), 'image/png') self.assertEquals(response.getHeader('Cache-Control'), 'max-age=%s, public' % policy[1].getMaxAgeSecs())
def index_html(self, REQUEST, RESPONSE): """ The default view of the contents of a File or Image. Returns the contents of the file or image. Also, sets the Content-Type HTTP header to the objects content type. """ if self._if_modified_since_request_handler(REQUEST, RESPONSE): # we were able to handle this by returning a 304 # unfortunately, because the HTTP cache manager uses the cache # API, and because 304 responses are required to carry the Expires # header for HTTP/1.1, we need to call ZCacheable_set here. # This is nonsensical for caches other than the HTTP cache manager # unfortunately. self.ZCacheable_set(None) return b'' if self.precondition and hasattr(self, str(self.precondition)): # Grab whatever precondition was defined and then # execute it. The precondition will raise an exception # if something violates its terms. c = getattr(self, str(self.precondition)) if hasattr(c, 'isDocTemp') and c.isDocTemp: c(REQUEST['PARENTS'][1], REQUEST) else: c() if self._range_request_handler(REQUEST, RESPONSE): # we served a chunk of content in response to a range request. return b'' RESPONSE.setHeader('Last-Modified', rfc1123_date(self._p_mtime)) RESPONSE.setHeader('Content-Type', self.content_type) RESPONSE.setHeader('Content-Length', self.size) RESPONSE.setHeader('Accept-Ranges', 'bytes') if self.ZCacheable_isCachingEnabled(): result = self.ZCacheable_get(default=None) if result is not None: # We will always get None from RAMCacheManager and HTTP # Accelerated Cache Manager but we will get # something implementing the IStreamIterator interface # from a "FileCacheManager" return result self.ZCacheable_set(None) data = self.data if isinstance(data, binary_type): RESPONSE.setBase(None) return data while data is not None: RESPONSE.write(data.data) data = data.next return b''
def getHeaders(self, expr_context): """ Does this request match our predicate? If so, return a sequence of caching headers as ( key, value ) tuples. Otherwise, return an empty sequence. """ headers = [] if self._predicate(expr_context): mtime = self._mtime_func(expr_context) if type(mtime) is type(''): mtime = DateTime(mtime) if mtime is not None: mtime_flt = mtime.timeTime() mtime_str = rfc1123_date(mtime_flt) headers.append(('Last-modified', mtime_str)) control = [] if self._max_age_secs is not None: now = expr_context.vars['time'] exp_time_str = rfc1123_date(now.timeTime() + self._max_age_secs) headers.append(('Expires', exp_time_str)) control.append('max-age=%d' % self._max_age_secs) if self._no_cache: control.append('no-cache') if self._no_store: control.append('no-store') if self._must_revalidate: control.append('must-revalidate') if control: headers.append(('Cache-control', ', '.join(control))) if self.getVary(): headers.append(('Vary', self._vary)) return headers
def doCache(self, hours=10): """ set cache headers on this request """ if hours > 0: response = self.REQUEST.RESPONSE #now = DateTime() #then = now+float(hours/24.0) #response.setHeader('Expires', then.rfc822()) response.setHeader('Expires', rfc1123_date(time() + 3600*hours)) response.setHeader('Cache-Control', 'public,max-age=%d' % int(3600*hours))
def test_06_Check_LastModified_Header(self): """Checks that Last-Modified header set by caching policy manager is correctly filled with getModificationDate of content. This test check "unauthenticated" Policy installed by erp5_web: """ website = self.setupWebSite() website_url = website.absolute_url_path() response = self.publish(website_url) self.assertTrue(response.getHeader('x-cache-headers-set-by'), 'CachingPolicyManager: /erp5/caching_policy_manager') web_section_portal_type = 'Web Section' web_section = website.newContent(portal_type=web_section_portal_type) response = self.publish(web_section.absolute_url_path()) self.assertTrue(response.getHeader('x-cache-headers-set-by'), 'CachingPolicyManager: /erp5/caching_policy_manager') # unauthenticated document_portal_type = 'Text' document_module = self.portal.getDefaultModule(document_portal_type) document = document_module.newContent(portal_type=document_portal_type, reference='NXD-Document-TEXT.Cache') document.publish() self.tic() response = self.publish(website_url + '/NXD-Document-TEXT.Cache') last_modified_header = response.getHeader('Last-Modified') self.assertTrue(last_modified_header) from App.Common import rfc1123_date # Convert the Date into string according RFC 1123 Time Format modification_date = rfc1123_date(document.getModificationDate()) self.assertEqual(modification_date, last_modified_header) # Upload a presentation with 3 pages. upload_file = makeFileUpload('P-DMS-Presentation.3.Pages-001-en.odp') document = document_module.newContent(portal_type='Presentation', file=upload_file) reference = 'P-DMS-Presentation.3.Pages' document.edit(reference=reference) document.publish() self.tic() # Check we can access to the 3 drawings converted into images. # Those images can be accessible through extensible content # url : path-of-document + '/' + 'img' + page-index + '.png' policy_list = self.portal.caching_policy_manager.listPolicies() policy = [policy[1] for policy in policy_list\ if policy[0] == 'unauthenticated'][0] for i in xrange(3): path = '/'.join((website_url, reference, 'img%s.png' % i)) response = self.publish(path) policy_list = self.portal.caching_policy_manager.listPolicies() policy = [policy for policy in policy_list\ if policy[0] == 'unauthenticated'][0] self.assertEquals(response.getHeader('Content-Type'), 'image/png') self.assertEquals(response.getHeader('Cache-Control'), 'max-age=%s, public' % policy[1].getMaxAgeSecs())
def test_addPolicy( self ): mgr = self._makeOne() mgr._addPolicy( 'first', 'python:1', None, 0, 0, 0, 0 ) headers = mgr.getHTTPCachingHeaders( content=DummyContent(self._epoch) , view_method='foo_view' , keywords={} , time=self._epoch ) self.assertEqual( len( headers ), 3 ) self.assertEqual( headers[0][0].lower() , 'last-modified' ) self.assertEqual( headers[0][1] , rfc1123_date(self._epoch.timeTime()) ) self.assertEqual( headers[1][0].lower() , 'expires' ) self.assertEqual( headers[1][1] , rfc1123_date(self._epoch.timeTime()) ) self.assertEqual( headers[2][0].lower() , 'cache-control' ) self.assertEqual( headers[2][1], 'max-age=0' )
def __call__(self, *args, **kwargs): """ view.css """ self.request.RESPONSE.setHeader('content-type', 'text/css') expires = rfc1123_date((DateTime() + 365).timeTime()) self.request.RESPONSE.setHeader('Expires', expires) self.request.RESPONSE.setHeader('Cache-Control', 'max-age=%d' % self.duration) return self.get_content()
def __call__(self, *args, **kwargs): """ edit.js """ self.request.RESPONSE.setHeader('content-type', 'text/javascript') expires = rfc1123_date((DateTime() + 365).timeTime()) self.request.RESPONSE.setHeader('Expires', expires) self.request.RESPONSE.setHeader( 'Cache-Control', 'max-age=%d' % self.duration) return self.get_content()
def test_addPolicy( self ): mgr = self._makeOne() mgr._addPolicy( 'first', 'python:1', None, 0, 0, 0, 0, '' ) headers = mgr.getHTTPCachingHeaders( content=DummyContent(self._epoch) , view_method='foo_view' , keywords={} , time=self._epoch ) self.assertEqual( len( headers ), 3 ) self.assertEqual( headers[0][0].lower() , 'last-modified' ) self.assertEqual( headers[0][1] , rfc1123_date(self._epoch.timeTime()) ) self.assertEqual( headers[1][0].lower() , 'expires' ) self.assertEqual( headers[1][1] , rfc1123_date(self._epoch.timeTime()) ) self.assertEqual( headers[2][0].lower() , 'cache-control' ) self.assertEqual( headers[2][1], 'max-age=0' )
def test_empty( self ): policy = self._makePolicy( 'empty' ) context = self._makeContext() headers = policy.getHeaders( context ) self.assertEqual( len( headers ), 1 ) self.assertEqual( headers[0][0], 'Last-modified' ) self.assertEqual( headers[0][1] , rfc1123_date(self._epoch.timeTime()) )
def test_mtimeFunc(self): policy = self._makePolicy('mtimeFunc', mtime_func='string:2001/01/01') context = self._makeContext() headers = policy.getHeaders(context) self.assertEqual(len(headers), 1) self.assertEqual(headers[0][0], 'Last-modified') self.assertEqual(headers[0][1], rfc1123_date(ACCLARK.timeTime()))
def __call__(self): self.setup() # set caching headers last_modified = rfc1123_date(self.context.modified()) self.request.RESPONSE.setHeader('Cache-Control', 'public') self.request.RESPONSE.setHeader('Last-Modified', last_modified) # disable Diazo as it could insert invalid attributes in header tags self.request.RESPONSE.setHeader('X-Theme-Disabled', 'True') return self.index()
def test_lookupMatchFoo(self): mgr = self._makeOneWithPolicies() headers = mgr.getHTTPCachingHeaders(content=DummyContent(self._epoch), view_method='foo_view', keywords={'foo': 1}, time=self._epoch) self.assertEqual(len(headers), 1) self.assertEqual(headers[0][0].lower(), 'last-modified') self.assertEqual(headers[0][1], rfc1123_date(self._epoch.timeTime()))
def test_kwPredicate(self): policy = self._makePolicy('kwPredicate', predicate='python:"foo" in keywords.keys()') context = self._makeContext(foo=1) headers = policy.getHeaders(context) self.assertEqual(len(headers), 1) self.assertEqual(headers[0][0], 'Last-modified') self.assertEqual(headers[0][1], rfc1123_date(self._epoch.timeTime()))
def test_typePredicate( self ): policy = self._makePolicy( 'typePredicate' , predicate='python:object.Type() == "Dummy"' ) context = self._makeContext() headers = policy.getHeaders( context ) self.assertEqual( len( headers ), 1 ) self.assertEqual( headers[0][0] , 'Last-modified' ) self.assertEqual( headers[0][1] , rfc1123_date(self._epoch.timeTime()) )
def test_typePredicate(self): policy = self._makePolicy('typePredicate', predicate='python:content.Type() == "Dummy"') context = self._makeContext() headers = policy.getHeaders(context) self.assertEqual(len(headers), 1) self.assertEqual(headers[0][0], 'Last-modified') self.assertEqual(headers[0][1], rfc1123_date(self._epoch.timeTime()))
def setHeader(self): """Caching the stylesheet for 20 days """ setHeader = self.request.RESPONSE.setHeader setHeader('Content-Type', 'text/css;;charset=utf-8') duration = 20 # days seconds = float(duration) * 24.0 * 3600.0 setHeader('Expires', rfc1123_date((DateTime() + duration).timeTime())) setHeader('Cache-Control', 'max-age=%d' % int(seconds)) return
def test_viewPredicate(self): policy = self._makePolicy('viewPredicate', predicate='python:view == "foo_view"') context = self._makeContext() headers = policy.getHeaders(context) self.assertEqual(len(headers), 1) self.assertEqual(headers[0][0], 'Last-modified') self.assertEqual(headers[0][1], rfc1123_date(self._epoch.timeTime()))
def testCachingHeadersFromTool(self): self.tool.registerScript('ham') # Publish response = self.publish(self.toolpath+'/ham') now = DateTime() days = 7 soon = now + days self.assertEqual(response.getStatus(), 200) self.assertEqual(response.getHeader('Expires'), rfc1123_date(soon.timeTime())) self.assertEqual(response.getHeader('Cache-Control'), 'max-age=%d' % int(days*24*3600)) # Publish again response = self.publish(self.toolpath+'/ham') now = DateTime() days = 7 soon = now + days self.assertEqual(response.getStatus(), 200) self.assertEqual(response.getHeader('Expires'), rfc1123_date(soon.timeTime())) self.assertEqual(response.getHeader('Cache-Control'), 'max-age=%d' % int(days*24*3600))
def test_combined(self): policy = self._makePolicy('noStore', no_cache=1, no_store=1) context = self._makeContext() headers = policy.getHeaders(context) self.assertEqual(len(headers), 2) self.assertEqual(headers[0][0].lower(), 'last-modified') self.assertEqual(headers[0][1], rfc1123_date(self._epoch.timeTime())) self.assertEqual(headers[1][0].lower(), 'cache-control') self.assertEqual(headers[1][1], 'no-cache, no-store')
def test_mustRevalidate(self): policy = self._makePolicy('mustRevalidate', must_revalidate=1) context = self._makeContext() headers = policy.getHeaders(context) self.assertEqual(len(headers), 2) self.assertEqual(headers[0][0].lower(), 'last-modified') self.assertEqual(headers[0][1], rfc1123_date(self._epoch.timeTime())) self.assertEqual(headers[1][0].lower(), 'cache-control') self.assertEqual(headers[1][1], 'must-revalidate')
def __call__(self): response = self.request.response response.setHeader("Content-type", "text/css") response.setHeader('X-Theme-Disabled', 'True') duration = 7.0 seconds = duration * 24.0 * 3600.0 # 1 day cache duration response.setHeader('Expires', rfc1123_date((DateTime() + duration).timeTime())) response.setHeader('Cache-Control', 'max-age=%d' % int(seconds)) return self.generate_css()
def test_ETag(self): # With an empty etag_func, no ETag should be produced policy = self._makePolicy('ETag', etag_func='') context = self._makeContext() headers = policy.getHeaders(context) self.assertEqual(len(headers), 1) self.assertEqual(headers[0][0].lower(), 'last-modified') self.assertEqual(headers[0][1], rfc1123_date(self._epoch.timeTime())) policy = self._makePolicy('ETag', etag_func='string:foo') context = self._makeContext() headers = policy.getHeaders(context) self.assertEqual(len(headers), 2) self.assertEqual(headers[0][0].lower(), 'last-modified') self.assertEqual(headers[0][1], rfc1123_date(self._epoch.timeTime())) self.assertEqual(headers[1][0].lower(), 'etag') self.assertEqual(headers[1][1], 'foo')
def dav__init(self, request, response): # We are allowed to accept a url w/o a trailing slash # for a collection, but are supposed to provide a # hint to the client that it should be using one. # [WebDAV, 5.2] pathinfo = request.get('PATH_INFO', '') if pathinfo and pathinfo[-1] != '/': location = '%s/' % request['URL1'] response.setHeader('Content-Location', location) response.setHeader('Connection', 'close', 1) response.setHeader('Date', rfc1123_date(), 1)
def ZCache_set(self, ob, data, view_name, keywords, mtime_func): # Note the blatant ignorance of view_name and keywords. # Standard HTTP accelerators are not able to make use of this # data. mtime_func is also ignored because using "now" for # Last-Modified is as good as using any time in the past. REQUEST = ob.REQUEST RESPONSE = REQUEST.RESPONSE anon = 1 u = REQUEST.get('AUTHENTICATED_USER', None) if u is not None: if u.getUserName() != 'Anonymous User': anon = 0 phys_path = ob.getPhysicalPath() if phys_path in self.hit_counts: hits = self.hit_counts[phys_path] else: self.hit_counts[phys_path] = hits = [0, 0] if anon: hits[0] = hits[0] + 1 else: hits[1] = hits[1] + 1 if not anon and self.anonymous_only: return # Set HTTP Expires and Cache-Control headers seconds=self.interval cache_control_parameter = ['max-age=%d' %(seconds,)] expires=rfc1123_date(time.time() + seconds) if getattr(self, 'stale_if_error_interval', 0): cache_control_parameter.append("stale-if-error=%d" \ %(self.stale_if_error_interval)) if getattr(self, 'stale_while_revalidate_interval', 0): cache_control_parameter.append("stale-while-revalidate=%d" \ %(self.stale_while_revalidate_interval)) if getattr(self, 'public', 0): cache_control_parameter.append('public') if getattr(self, 'must_revalidate', 0): cache_control_parameter.append('must-revalidate') RESPONSE.setHeader('Last-Modified', rfc1123_date(time.time())) RESPONSE.setHeader('Cache-Control', ", ".join(cache_control_parameter)) RESPONSE.setHeader('Expires', expires)
def test_sMaxAge(self): policy = self._makePolicy('s_aged', s_max_age_secs=86400) context = self._makeContext() headers = policy.getHeaders(context) self.assertEqual(len(headers), 2) self.assertEqual(headers[0][0].lower(), 'last-modified') self.assertEqual(headers[0][1], rfc1123_date(self._epoch.timeTime())) self.assertEqual(headers[1][0].lower(), 'cache-control') self.assertEqual(headers[1][1], 's-maxage=86400') self.assertEqual(policy.getSMaxAgeSecs(), 86400)
def assertExpiresNotEqual(self, expires, moment): """Assert that the Expires header is NOT equal to a moment or one second earlier or later. There are some spurious test failures because 'now' is calculated, then a request is made and some headers are set, but this takes slightly too long and the resulting Expires header is one second after 'now'. - expires: usually response.getHeader('Expires') - moment: number of seconds, usually DateTime().timeTime(). NOT an rfc1123 date """ if expires != rfc1123_date(moment) and \ expires != rfc1123_date(moment + 1) and \ expires != rfc1123_date(moment - 1): return # We have a failure. Call the method that would originally be # called. self.assertNotEqual(expires, rfc1123_date(moment))
def test_public(self): policy = self._makePolicy('public', public=1) context = self._makeContext() headers = policy.getHeaders(context) self.assertEqual(len(headers), 2) self.assertEqual(headers[0][0].lower(), 'last-modified') self.assertEqual(headers[0][1], rfc1123_date(self._epoch.timeTime())) self.assertEqual(headers[1][0].lower(), 'cache-control') self.assertEqual(headers[1][1], 'public') self.assertEqual(policy.getPublic(), 1)
def test_noTransform(self): policy = self._makePolicy('noTransform', no_transform=1) context = self._makeContext() headers = policy.getHeaders(context) self.assertEqual(len(headers), 2) self.assertEqual(headers[0][0].lower(), 'last-modified') self.assertEqual(headers[0][1], rfc1123_date(self._epoch.timeTime())) self.assertEqual(headers[1][0].lower(), 'cache-control') self.assertEqual(headers[1][1], 'no-transform') self.assertEqual(policy.getNoTransform(), 1)
def test_304_response_from_cpm(self): # test that we get a 304 response from the cpm via this template mod_time = DateTime() cpm = DummyCachingManagerWithPolicy() getSiteManager().registerUtility(cpm, ICachingPolicyManager) script = self._makeOne('testSTX', 'testSTX.stx') script = script.__of__(self.app) self.REQUEST.environ['IF_MODIFIED_SINCE'] = '%s;' % rfc1123_date( mod_time + 3600) data = script(self.REQUEST, self.RESPONSE) self.assertEqual(data, '') self.assertEqual(self.RESPONSE.getStatus(), 304)