cache.client
This commit is contained in:
@@ -1 +1 @@
|
|||||||
Version 2.4.2-stable+timestamp.2013.03.10.11.05.31
|
Version 2.4.2-stable+timestamp.2013.03.10.11.13.44
|
||||||
|
|||||||
+87
-3
@@ -27,6 +27,8 @@ import thread
|
|||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
import hashlib
|
||||||
|
import datetime
|
||||||
try:
|
try:
|
||||||
import settings
|
import settings
|
||||||
have_settings = True
|
have_settings = True
|
||||||
@@ -241,7 +243,7 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
|
|
||||||
This is implemented as a shelve object and it is shared by multiple web2py
|
This is implemented as a shelve object and it is shared by multiple web2py
|
||||||
processes (and threads) as long as they share the same filesystem.
|
processes (and threads) as long as they share the same filesystem.
|
||||||
The file is locked wen accessed.
|
The file is locked when accessed.
|
||||||
|
|
||||||
Disk cache provides persistance when web2py is started/stopped but it slower
|
Disk cache provides persistance when web2py is started/stopped but it slower
|
||||||
than `CacheInRam`
|
than `CacheInRam`
|
||||||
@@ -376,7 +378,6 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
self._close_shelve_and_unlock()
|
self._close_shelve_and_unlock()
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
class CacheAction(object):
|
class CacheAction(object):
|
||||||
def __init__(self, func, key, time_expire, cache, cache_model):
|
def __init__(self, func, key, time_expire, cache, cache_model):
|
||||||
self.__name__ = func.__name__
|
self.__name__ = func.__name__
|
||||||
@@ -436,6 +437,89 @@ class Cache(object):
|
|||||||
# been accounted for
|
# been accounted for
|
||||||
logger.warning('no cache.disk (AttributeError)')
|
logger.warning('no cache.disk (AttributeError)')
|
||||||
|
|
||||||
|
def client(self, time_expire=DEFAULT_TIME_EXPIRE, cache_model=None,
|
||||||
|
prefix=None, session=False, vars=True, lang=True,
|
||||||
|
user_agent=False, public=True, valid_statuses=None,
|
||||||
|
quick=None):
|
||||||
|
"""
|
||||||
|
Experimental!
|
||||||
|
Currently only HTTP 1.1 compliant
|
||||||
|
reference : http://code.google.com/p/doctype-mirror/wiki/ArticleHttpCaching
|
||||||
|
time_expire: same as @cache
|
||||||
|
cache_model: same as @cache
|
||||||
|
prefix: add a prefix to the calculated key
|
||||||
|
session: adds response.session_id to the key
|
||||||
|
vars: adds request.env.query_string
|
||||||
|
lang: adds T.accepted_language
|
||||||
|
user_agent: if True, adds is_mobile and is_tablet to the key.
|
||||||
|
Pass a dict to use all the needed values (uses str(.items())) (e.g. user_agent=request.user_agent())
|
||||||
|
used only if session is not True
|
||||||
|
public: if False forces the Cache-Control to be 'private'
|
||||||
|
valid_statuses: by default only status codes starting with 1,2,3 will be cached.
|
||||||
|
pass an explicit list of statuses on which turn the cache on
|
||||||
|
quick: Session,Vars,Lang,User-agent,Public,duration:
|
||||||
|
fast overrides with initial strings, e.g. 'SVLP' or 'VLP', or 'VLP'
|
||||||
|
"""
|
||||||
|
from gluon import current
|
||||||
|
def wrap(func):
|
||||||
|
def wrapped_f():
|
||||||
|
if current.request.env.request_method == 'GET':
|
||||||
|
if time_expire:
|
||||||
|
cache_control = 'max-age=%(time_expire)s, s-maxage=%(time_expire)s' % dict(time_expire=time_expire)
|
||||||
|
if quick:
|
||||||
|
session_ = True if 'S' in quick else False
|
||||||
|
vars_ = True if 'V' in quick else False
|
||||||
|
lang_ = True if 'L' in quick else False
|
||||||
|
user_agent_ = True if 'U' in quick else False
|
||||||
|
public_ = True if 'P' in quick else False
|
||||||
|
else:
|
||||||
|
session_, vars_, lang_, user_agent_, public_ = session, vars, lang, user_agent, public
|
||||||
|
if not session_ and public_:
|
||||||
|
cache_control += ', public'
|
||||||
|
expires = (current.request.utcnow + datetime.timedelta(seconds=time_expire)).strftime('%a, %d %b %Y %H:%M:%S GMT')
|
||||||
|
vary = None
|
||||||
|
else:
|
||||||
|
cache_control += ', private'
|
||||||
|
expires = 'Fri, 01 Jan 1990 00:00:00 GMT'
|
||||||
|
if cache_model:
|
||||||
|
cache_key = [current.request.env.path_info, current.response.view]
|
||||||
|
if session_:
|
||||||
|
cache_key.append(current.response.session_id)
|
||||||
|
elif user_agent_:
|
||||||
|
if user_agent_ is True:
|
||||||
|
cache_key.append("%(is_mobile)s_%(is_tablet)s" % current.request.user_agent())
|
||||||
|
else:
|
||||||
|
cache_key.append(str(user_agent_.items()))
|
||||||
|
if vars_:
|
||||||
|
cache_key.append(current.request.env.query_string)
|
||||||
|
if lang_:
|
||||||
|
cache_key.append(current.T.accepted_language)
|
||||||
|
cache_key = hashlib.md5('__'.join(cache_key)).hexdigest()
|
||||||
|
if prefix:
|
||||||
|
cache_key = prefix + cache_key
|
||||||
|
rtn = cache_model(cache_key, lambda : func(), time_expire=time_expire)
|
||||||
|
else:
|
||||||
|
rtn = func()
|
||||||
|
send_headers = False
|
||||||
|
if isinstance(valid_statuses, list):
|
||||||
|
if current.response.status in valid_statuses:
|
||||||
|
send_headers = True
|
||||||
|
elif valid_statuses is None:
|
||||||
|
if str(current.response.status)[0] in '123':
|
||||||
|
send_headers = True
|
||||||
|
if send_headers:
|
||||||
|
current.response.headers['Pragma'] = None
|
||||||
|
current.response.headers['Expires'] = expires
|
||||||
|
current.response.headers['Cache-Control'] = cache_control
|
||||||
|
if cache_model and not send_headers:
|
||||||
|
cache_model.clear(cache_key)
|
||||||
|
return rtn
|
||||||
|
return func()
|
||||||
|
wrapped_f.__name__ = func.__name__
|
||||||
|
wrapped_f.__doc__ = func.__doc__
|
||||||
|
return wrapped_f
|
||||||
|
return wrap
|
||||||
|
|
||||||
def __call__(self,
|
def __call__(self,
|
||||||
key=None,
|
key=None,
|
||||||
time_expire=DEFAULT_TIME_EXPIRE,
|
time_expire=DEFAULT_TIME_EXPIRE,
|
||||||
@@ -469,7 +553,7 @@ class Cache(object):
|
|||||||
refresh.
|
refresh.
|
||||||
|
|
||||||
If the function `f` is an action, we suggest using
|
If the function `f` is an action, we suggest using
|
||||||
`request.env.path_info` as key.
|
@cache.client instead
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def tmp(func, cache=self, cache_model=cache_model):
|
def tmp(func, cache=self, cache_model=cache_model):
|
||||||
|
|||||||
Reference in New Issue
Block a user