Source code for wheezy.http.cache

""" ``cache`` module
"""

from zlib import crc32

from wheezy.http.cacheprofile import none_cache_profile
from wheezy.http.comp import b
from wheezy.http.comp import md5


def response_cache(profile=None):
[docs] """ Decorator that applies cache profile strategy to the wrapping handler. """ if not profile: profile = none_cache_profile def decorate(handler): if not profile.enabled: return handler cache_policy_func = profile.cache_policy if profile.request_vary: if profile.etag_func: etag_func = profile.etag_func def etag(request, *args, **kwargs): response = handler(request, *args, **kwargs) response.cache_profile = profile response.cache_policy = cache_policy_func() response.cache_policy.http_etag = etag_func( response.buffer) return response return etag else: def cache(request, *args, **kwargs): response = handler(request, *args, **kwargs) response.cache_profile = profile response.cache_policy = cache_policy_func() return response return cache else: def no_cache(request, *args, **kwargs): response = handler(request, *args, **kwargs) response.cache_profile = None response.cache_policy = cache_policy_func() return response return no_cache return decorate def wsgi_cache(profile):
[docs] """ Decorator that wraps wsgi app and set cache profile. """ def decorate(wsgi_app): if not profile.enabled: return wsgi_app def wsgi_wrapper(environ, start_response): environ['wheezy.http.cache_profile'] = profile return wsgi_app(environ, start_response) return wsgi_wrapper return decorate def make_etag(hasher):
[docs] """ Build etag function based on `hasher` algorithm. """ def etag(buf): h = hasher() for chunk in buf: h.update(chunk) return '"' + h.hexdigest() + '"' return etag etag_md5 = make_etag(md5)
def make_etag_crc32(hasher):
[docs] """ Build etag function based on `hasher` algorithm and crc32. """ def etag(buf): h = hasher() for chunk in buf: h.update(chunk) return '"%08x"' % (crc32(b(h.hexdigest())) & 0xFFFFFFFF) return etag etag_md5crc32 = make_etag_crc32(md5)
class SurfaceResponse(object):
[docs] """ WSGI wrapper that returns ``response`` headers and buffer. """ __slots__ = ('inner',) def __init__(self, response): """ Initializes response. """ self.inner = response def __call__(self, start_response): """ WSGI call processing. """ start_response('200 OK', self.inner.headers) return self.inner.buffer class NotModifiedResponse(object):
[docs] """ Not modified cachable response. """ status_code = 304 __slots__ = ('headers',) def __init__(self, response): """ Initializes not modified cachable response. """ self.headers = [h for h in response.headers if h[0] != 'Content-Length'] def __call__(self, start_response): """ WSGI call processing. """ start_response('304 Not Modified', self.headers) return [] class CacheableResponse(object):
[docs] """ Cachable response. """ status_code = 200 last_modified = None etag = None def __init__(self, response): """ Initializes cachable response. """ def capture_headers(status, headers): self.headers = [h for h in headers if h[0] != 'Set-Cookie'] self.buffer = tuple(response(capture_headers)) cache_policy = response.cache_policy if cache_policy: self.last_modified = cache_policy.modified self.etag = cache_policy.http_etag def __call__(self, start_response): """ WSGI call processing. """ start_response('200 OK', self.headers) return self.buffer