Commit 5134943e authored by Aurel's avatar Aurel

implement RFC-5861 in CachingPolicyManager

parent b5735cfc
......@@ -76,6 +76,7 @@ from Products.ERP5Type.patches import _transaction
from Products.ERP5Type.patches import default_zpublisher_encoding
from Products.ERP5Type.patches import DCWorkflowGraph
from Products.ERP5Type.patches import AceEditorZMI
from Products.ERP5Type.patches import CachingPolicyManager
# These symbols are required for backward compatibility
from Products.ERP5Type.patches.PropertyManager import ERP5PropertyManager
......
<dtml-var manage_page_header>
<dtml-var manage_tabs>
<dtml-in listPolicies>
<dtml-if sequence-start>
<h2> Edit Caching Policies </h2>
<table>
</dtml-if>
<dtml-let policy_id=sequence-key
policy=sequence-item
>
<tr valign="top">
<td align="left">
<form action="&dtml-absolute_url;">
<dtml-with policy>
<dtml-let nc_checked="getNoCache() and 'checked' or ''"
ns_checked="getNoStore() and 'checked' or ''"
mr_checked="getMustRevalidate() and 'checked' or ''"
pr_checked="getProxyRevalidate() and 'checked' or ''"
pub_checked="getPublic() and 'checked' or ''"
priv_checked="getPrivate() and 'checked' or ''"
nt_checked="getNoTransform() and 'checked' or ''"
e304_checked="getEnable304s() and 'checked' or ''"
s_max_age_secs="getSMaxAgeSecs() is not None and getSMaxAgeSecs() or ''"
last_modified_checked="getLastModified() and 'checked' or ''"
pre_check="getPreCheck() is not None and getPreCheck() or ''"
post_check="getPostCheck() is not None and getPostCheck() or ''">
<input type="hidden" name="policy_id" value="&dtml-getPolicyId;">
<input type="hidden" name="no_cache:default:int" value="0">
<input type="hidden" name="no_store:default:int" value="0">
<input type="hidden" name="must_revalidate:default:int" value="0">
<input type="hidden" name="proxy_revalidate:default:int" value="0">
<input type="hidden" name="public:default:int" value="0">
<input type="hidden" name="private:default:int" value="0">
<input type="hidden" name="no_transform:default:int" value="0">
<input type="hidden" name="enable_304s:default:int" value="0">
<input type="hidden" name="last_modified:default:int" value="0">
<table>
<tr valign="top">
<th align="right"> Policy ID </th>
<td>
&dtml-getPolicyId;
</td>
</tr>
<tr valign="top">
<th align="right"> Predicate </th>
<td>
<input type="text"
name="predicate"
value="&dtml-getPredicate;"
size="40">
</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr valign="top">
<th align="right"> Mod. Time </th>
<td>
<input type="text"
name="mtime_func"
value="&dtml-getMTimeFunc;"
size="40">
</td>
<th align="right">Last-Modified?</th>
<td>
<input type="checkbox"
name="last_modified:int"
value="1" &dtml-last_modified_checked;>
</td>
</tr>
<tr valign="top">
<th align="right"> No-cache? </th>
<td>
<input type="checkbox" name="no_cache:int"
value="1" &dtml-nc_checked;>
</td>
<th align="right"> No-store? </th>
<td>
<input type="checkbox" name="no_store:int"
value="1" &dtml-ns_checked;>
</td>
</tr>
<tr valign="top">
<th align="right"> Max age (secs) </th>
<td>
<input type="text"
name="max_age_secs:int"
value="&dtml-getMaxAgeSecs;">
</td>
<th align="right"> Must-revalidate? </th>
<td>
<input type="checkbox" name="must_revalidate:int"
value="1" &dtml-mr_checked;>
</td>
</tr>
<tr valign="top">
<th align="right"> Stale While Revalidate (secs) </th>
<td>
<input type="text"
name="stale_revalidate_secs:int"
value="&dtml-getStaleWhileRevalidateSecs;">
</td>
<th align="right"> Stale If Error (secs) </th>
<td>
<input type="text"
name="stale_error_secs:int"
value="&dtml-getStaleIfErrorSecs;">
</td>
</tr>
<tr valign="top">
<th align="right"> Max proxy cache age (secs) </th>
<td>
<input type="text"
name="s_max_age_secs"
value="&dtml-s_max_age_secs;">
</td>
<th align="right"> Proxy-revalidate? </th>
<td>
<input type="checkbox" name="proxy_revalidate:int"
value="1" &dtml-pr_checked;>
</td>
</tr>
<tr valign="top">
<th align="right"> Pre-check (secs) </th>
<td>
<input type="text"
name="pre_check"
value="&dtml-pre_check;">
</td>
<th align="right"> Post-check (secs) </th>
<td>
<input type="text"
name="post_check"
value="&dtml-post_check;">
</td>
</tr>
<tr valign="top">
<th align="right"> Vary </th>
<td>
<input type="text"
name="vary"
value="&dtml-getVary;"
size="40">
</td>
<th align="right"> Public? </th>
<td>
<input type="checkbox" name="public:int"
value="1" &dtml-pub_checked;>
</td>
</tr>
<tr valign="top">
<th align="right"> ETag </th>
<td>
<input type="text"
name="etag_func"
value="&dtml-getETagFunc;"
size="40">
</td>
<th align="right"> Private? </th>
<td>
<input type="checkbox" name="private:int"
value="1" &dtml-priv_checked;>
</td>
</tr>
<tr valign="top">
<th align="right"> Enable 304s? </th>
<td>
<input type="checkbox" name="enable_304s:int"
value="1" &dtml-e304_checked;>
</td>
<th align="right"> No-transform? </th>
<td>
<input type="checkbox" name="no_transform:int"
value="1" &dtml-nt_checked;>
</td>
</tr>
<tr valign="top">
<td><br /></td>
<td colspan="3">
<input type="submit" name="updatePolicy:method" value=" Change ">
<input type="submit" name="removePolicy:method" value=" Delete ">
<input type="submit" name="movePolicyUp:method" value=" Up ">
<input type="submit" name="movePolicyDown:method" value=" Down ">
</td>
</tr>
</table>
</dtml-let>
</dtml-with>
</form>
</td>
<td> <br> </td>
</tr>
</dtml-let>
<dtml-if sequence-end>
</table>
</dtml-if>
</dtml-in>
<h2> Add Caching Policy </h2>
<table>
<tr valign="top">
<td align="left">
<form action="&dtml-absolute_url;">
<input type="hidden" name="last_modified:default:int" value="0">
<input type="hidden" name="no_cache:default:int" value="0">
<input type="hidden" name="no_store:default:int" value="0">
<input type="hidden" name="must_revalidate:default:int" value="0">
<input type="hidden" name="proxy_revalidate:default:int" value="0">
<input type="hidden" name="public:default:int" value="0">
<input type="hidden" name="private:default:int" value="0">
<input type="hidden" name="no_transform:default:int" value="0">
<input type="hidden" name="enable_304s:default:int" value="0">
<table>
<tr valign="top">
<th align="right"> Policy ID </th>
<td>
<input type="text" name="policy_id">
</td>
</tr>
<tr valign="top">
<th align="right"> Predicate </th>
<td>
<input type="text" name="predicate" size="40">
</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr valign="top">
<th align="right"> Mod. time </th>
<td>
<input type="text" name="mtime_func" size="40">
</td>
<th align="right"> Last-Modified? </th>
<td>
<input type="checkbox" name="last_modified:int" value="1">
</td>
</tr>
<tr>
<th align="right"> No-cache? </th>
<td>
<input type="checkbox" name="no_cache:int" value="1">
</td>
<th align="right"> No-store? </th>
<td>
<input type="checkbox" name="no_store:int" value="1">
</td>
</tr>
<tr valign="top">
<th align="right"> Max age (secs) </th>
<td>
<input type="text" name="max_age_secs:int" value="0">
</td>
<th align="right"> Must-revalidate? </th>
<td>
<input type="checkbox" name="must_revalidate:int"
value="1">
</td>
</tr>
<tr valign="top">
<th align="right"> Stale While Revalidate (secs) </th>
<td>
<input type="text" name="stale_revalidate_secs:int" value="0">
</td>
<th align="right"> Stale If Error (secs) </th>
<td>
<input type="text" name="stale_error_secs:int" value="0">
</td>
</tr>
<tr valign="top">
<th align="right"> Max proxy cache age (secs) </th>
<td>
<input type="text"
name="s_max_age_secs"
value="">
</td>
<th align="right"> Proxy-revalidate? </th>
<td>
<input type="checkbox" name="proxy_revalidate:int"
value="1">
</td>
</tr>
<tr valign="top">
<th align="right"> Pre-check (secs) </th>
<td>
<input type="text"
name="pre_check"
value="">
</td>
<th align="right"> Post-check (secs) </th>
<td>
<input type="text"
name="post_check"
value="">
</td>
</tr>
<tr valign="top">
<th align="right"> Vary </th>
<td>
<input type="text" name="vary" size="40">
</td>
<th align="right"> Public? </th>
<td>
<input type="checkbox" name="public:int"
value="1">
</td>
</tr>
<tr valign="top">
<th align="right"> ETag </th>
<td>
<input type="text" name="etag_func" size="40">
</td>
<th align="right"> Private? </th>
<td>
<input type="checkbox" name="private:int"
value="1">
</td>
</tr>
<tr valign="top">
<th align="right"> Enable 304s? </th>
<td>
<input type="checkbox" name="enable_304s:int"
value="1">
</td>
<th align="right"> No-transform? </th>
<td>
<input type="checkbox" name="no_transform:int"
value="1">
</td>
</tr>
<tr valign="top">
<td><br /></td>
<td>
<input type="submit" name="addPolicy:method" value=" Add ">
</td>
</tr>
</table>
</form>
</td>
</tr>
</table>
<dtml-var manage_page_footer>
from Products.CMFCore.CachingPolicyManager import CachingPolicy, \
CachingPolicyManager
from App.special_dtml import DTMLFile
from Products.CMFCore.Expression import Expression
from App.Common import rfc1123_date
from DateTime.DateTime import DateTime
from Products.ERP5Type import _dtmldir
# Path CachingPolicy to add stale-if-error & stale-while-revalidate
# from RFC 5861
def __init__( self
, policy_id
, predicate=''
, mtime_func=''
, max_age_secs=None
, stale_revalidate_secs=None
, stale_error_secs=None
, no_cache=0
, no_store=0
, must_revalidate=0
, vary=''
, etag_func=''
, s_max_age_secs=None
, proxy_revalidate=0
, public=0
, private=0
, no_transform=0
, enable_304s=0
, last_modified=1
, pre_check=None
, post_check=None
):
if not predicate:
predicate = 'python:1'
if not mtime_func:
mtime_func = 'object/modified'
if max_age_secs is not None:
if str(max_age_secs).strip() == '':
max_age_secs = None
else:
max_age_secs = int( max_age_secs )
if s_max_age_secs is not None:
if str(s_max_age_secs).strip() == '':
s_max_age_secs = None
else:
s_max_age_secs = int( s_max_age_secs )
if pre_check is not None:
if str(pre_check).strip() == '':
pre_check = None
else:
pre_check = int(pre_check)
if post_check is not None:
if str(post_check).strip() == '':
post_check = None
else:
post_check = int(post_check)
self._policy_id = policy_id
self._predicate = Expression( text=predicate )
self._mtime_func = Expression( text=mtime_func )
self._max_age_secs = max_age_secs
self._s_max_age_secs = s_max_age_secs
self._no_cache = int( no_cache )
self._no_store = int( no_store )
self._must_revalidate = int( must_revalidate )
self._proxy_revalidate = int( proxy_revalidate )
self._public = int( public )
self._private = int( private )
self._no_transform = int( no_transform )
self._vary = vary
self._etag_func = Expression( text=etag_func )
self._enable_304s = int ( enable_304s )
self._last_modified = int( last_modified )
self._pre_check = pre_check
self._post_check = post_check
self._stale_if_error_secs = stale_error_secs
self._stale_while_revalidate_secs = stale_revalidate_secs
def getStaleIfErrorSecs( self ):
"""
"""
return getattr(self, '_stale_if_error_secs', 0)
def getStaleWhileRevalidateSecs( self ):
"""
"""
return getattr(self, '_stale_while_revalidate_secs', 0)
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.testPredicate( expr_context ):
if self.getLastModified():
mtime = self._mtime_func( expr_context )
if type( mtime ) is type( '' ):
mtime = DateTime( mtime )
if mtime is not None:
mtime_str = rfc1123_date(mtime.timeTime())
headers.append( ( 'Last-modified', mtime_str ) )
control = []
if self.getMaxAgeSecs() 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.getStaleWhileRevalidateSecs():
control.append( 'stale-while-revalidate=%d' % (
self.getStaleWhileRevalidateSecs(),))
if self.getStaleIfErrorSecs():
control.append( 'stale-if-error=%d' % (
self.getStaleIfErrorSecs(),))
if self.getSMaxAgeSecs() is not None:
control.append( 's-maxage=%d' % self._s_max_age_secs )
if self.getNoCache():
control.append( 'no-cache' )
# The following is for HTTP 1.0 clients
headers.append(('Pragma', 'no-cache'))
if self.getNoStore():
control.append( 'no-store' )
if self.getPublic():
control.append( 'public' )
if self.getPrivate():
control.append( 'private' )
if self.getMustRevalidate():
control.append( 'must-revalidate' )
if self.getProxyRevalidate():
control.append( 'proxy-revalidate' )
if self.getNoTransform():
control.append( 'no-transform' )
pre_check = self.getPreCheck()
if pre_check is not None:
control.append('pre-check=%d' % pre_check)
post_check = self.getPostCheck()
if post_check is not None:
control.append('post-check=%d' % post_check)
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 updatePolicy( self
, policy_id
, predicate # TALES expr (def. 'python:1')
, mtime_func # TALES expr (def. 'object/modified')
, max_age_secs # integer, seconds (def. 0)
, stale_revalidate_secs # integer, seconds (def, 0)
, stale_error_secs # integer, seconds (def, 0)
, no_cache # boolean (def. 0)
, no_store # boolean (def. 0)
, must_revalidate # boolean (def. 0)
, vary # string value
, etag_func # TALES expr (def. '')
, REQUEST=None
, s_max_age_secs=None # integer, seconds (def. 0)
, proxy_revalidate=0 # boolean (def. 0)
, public=0 # boolean (def. 0)
, private=0 # boolean (def. 0)
, no_transform=0 # boolean (def. 0)
, enable_304s=0 # boolean (def. 0)
, last_modified=1 # boolean (def. 1)
, pre_check=0 # integer, default=None
, post_check=0 # integer, default=None
):
"""
Update a caching policy.
"""
if max_age_secs is None or str(max_age_secs).strip() == '':
max_age_secs = None
else:
max_age_secs = int(max_age_secs)
if stale_revalidate_secs is None or str(stale_revalidate_secs).strip() == '':
stale_revalidate_secs = None
else:
stale_revalidate_secs = int(stale_revalidate_secs)
if stale_error_secs is None or str(stale_error_secs).strip() == '':
stale_error_secs = None
else:
stale_error_secs = int(stale_error_secs)
if s_max_age_secs is None or str(s_max_age_secs).strip() == '':
s_max_age_secs = None
else:
s_max_age_secs = int(s_max_age_secs)
if pre_check is None or str(pre_check).strip() == '':
pre_check = None
else:
pre_check = int(pre_check)
if post_check is None or str(post_check).strip() == '':
post_check = None
else:
post_check = int(post_check)
self._updatePolicy( policy_id
, predicate
, mtime_func
, max_age_secs
, stale_revalidate_secs
, stale_error_secs
, no_cache
, no_store
, must_revalidate
, vary
, etag_func
, s_max_age_secs
, proxy_revalidate
, public
, private
, no_transform
, enable_304s
, last_modified
, pre_check
, post_check
)
if REQUEST is not None:
REQUEST[ 'RESPONSE' ].redirect( self.absolute_url()
+ '/manage_cachingPolicies'
+ '?manage_tabs_message='
+ 'Policy+updated.'
)
def _updatePolicy( self
, policy_id
, predicate
, mtime_func
, max_age_secs
, stale_revalidate_secs
, stale_error_secs
, no_cache
, no_store
, must_revalidate
, vary
, etag_func
, s_max_age_secs=None
, proxy_revalidate=0
, public=0
, private=0
, no_transform=0
, enable_304s=0
, last_modified=1
, pre_check=None
, post_check=None
):
"""
Update a policy in our registry.
"""
if policy_id not in self._policy_ids:
raise KeyError, "Policy %s does not exist!" % policy_id
self._policies[ policy_id ] = CachingPolicy( policy_id
, predicate
, mtime_func
, max_age_secs
, stale_revalidate_secs
, stale_error_secs
, no_cache
, no_store
, must_revalidate
, vary
, etag_func
, s_max_age_secs
, proxy_revalidate
, public
, private
, no_transform
, enable_304s
, last_modified
, pre_check
, post_check
)
CachingPolicy.__init__ = __init__
CachingPolicy.getStaleIfErrorSecs = getStaleIfErrorSecs
CachingPolicy.getStaleWhileRevalidateSecs = getStaleWhileRevalidateSecs
CachingPolicy.getHeaders = getHeaders
CachingPolicyManager.updatePolicy = updatePolicy
CachingPolicyManager._updatePolicy = _updatePolicy
CachingPolicyManager.manage_cachingPolicies = DTMLFile( 'cachingPolicies', _dtmldir )
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