Merge pull request #86 from niphlod/feature/cache.action
cache.action now works with actions raising HTTP internally
This commit is contained in:
+81
-49
@@ -461,60 +461,92 @@ class Cache(object):
|
|||||||
fast overrides with initial strings, e.g. 'SVLP' or 'VLP', or 'VLP'
|
fast overrides with initial strings, e.g. 'SVLP' or 'VLP', or 'VLP'
|
||||||
"""
|
"""
|
||||||
from gluon import current
|
from gluon import current
|
||||||
|
from gluon.http import HTTP
|
||||||
def wrap(func):
|
def wrap(func):
|
||||||
def wrapped_f():
|
def wrapped_f():
|
||||||
if current.request.env.request_method == 'GET':
|
if current.request.env.request_method != 'GET':
|
||||||
if time_expire:
|
return func()
|
||||||
cache_control = 'max-age=%(time_expire)s, s-maxage=%(time_expire)s' % dict(time_expire=time_expire)
|
if time_expire:
|
||||||
if quick:
|
cache_control = 'max-age=%(time_expire)s, s-maxage=%(time_expire)s' % dict(time_expire=time_expire)
|
||||||
session_ = True if 'S' in quick else False
|
if quick:
|
||||||
vars_ = True if 'V' in quick else False
|
session_ = True if 'S' in quick else False
|
||||||
lang_ = True if 'L' in quick else False
|
vars_ = True if 'V' in quick else False
|
||||||
user_agent_ = True if 'U' in quick else False
|
lang_ = True if 'L' in quick else False
|
||||||
public_ = True if 'P' in quick else False
|
user_agent_ = True if 'U' in quick else False
|
||||||
else:
|
public_ = True if 'P' in quick else False
|
||||||
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:
|
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:
|
||||||
|
#figure out the correct cache key
|
||||||
|
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
|
||||||
|
try:
|
||||||
|
#action returns something
|
||||||
|
rtn = cache_model(cache_key, lambda : func(), time_expire=time_expire)
|
||||||
|
http, status = None, current.response.status
|
||||||
|
except HTTP, e:
|
||||||
|
#action raises HTTP (can still be valid)
|
||||||
|
rtn = cache_model(cache_key, lambda : e.body, time_expire=time_expire)
|
||||||
|
http, status = HTTP(e.status, rtn, **e.headers), e.status
|
||||||
|
else:
|
||||||
|
#action raised a generic exception
|
||||||
|
http = None
|
||||||
|
else:
|
||||||
|
#no server-cache side involved
|
||||||
|
try:
|
||||||
|
#action returns something
|
||||||
rtn = func()
|
rtn = func()
|
||||||
send_headers = False
|
http, status = None, current.response.status
|
||||||
if isinstance(valid_statuses, list):
|
except HTTP, e:
|
||||||
if current.response.status in valid_statuses:
|
#action raises HTTP (can still be valid)
|
||||||
send_headers = True
|
status = e.status
|
||||||
elif valid_statuses is None:
|
http = HTTP(e.status, e.body, **e.headers)
|
||||||
if str(current.response.status)[0] in '123':
|
else:
|
||||||
send_headers = True
|
#action raised a generic exception
|
||||||
|
http = None
|
||||||
|
send_headers = False
|
||||||
|
if http and isinstance(valid_statuses, list):
|
||||||
|
if status in valid_statuses:
|
||||||
|
send_headers = True
|
||||||
|
elif valid_statuses is None:
|
||||||
|
if str(status)[0] in '123':
|
||||||
|
send_headers = True
|
||||||
|
if send_headers:
|
||||||
|
headers = {
|
||||||
|
'Pragma' : None,
|
||||||
|
'Expires' : expires,
|
||||||
|
'Cache-Control' : cache_control
|
||||||
|
}
|
||||||
|
current.response.headers.update(headers)
|
||||||
|
if cache_model and not send_headers:
|
||||||
|
#we cached already the value, but the status is not valid
|
||||||
|
#so we need to delete the cached value
|
||||||
|
cache_model(cache_key, None)
|
||||||
|
if http:
|
||||||
if send_headers:
|
if send_headers:
|
||||||
current.response.headers['Pragma'] = None
|
http.headers.update(current.response.headers)
|
||||||
current.response.headers['Expires'] = expires
|
raise http
|
||||||
current.response.headers['Cache-Control'] = cache_control
|
return rtn
|
||||||
if cache_model and not send_headers:
|
|
||||||
cache_model(cache_key, None)
|
|
||||||
return rtn
|
|
||||||
return func()
|
|
||||||
wrapped_f.__name__ = func.__name__
|
wrapped_f.__name__ = func.__name__
|
||||||
wrapped_f.__doc__ = func.__doc__
|
wrapped_f.__doc__ = func.__doc__
|
||||||
return wrapped_f
|
return wrapped_f
|
||||||
|
|||||||
Reference in New Issue
Block a user