Package gavo :: Package web :: Module caching
[frames] | no frames]

Source Code for Module gavo.web.caching

  1  """ 
  2  A simple caching system for nevow pages. 
  3   
  4  The basic idea is to monkeypatch the request object in order to 
  5  snarf content and headers. 
  6  """ 
  7   
  8  #c Copyright 2008-2019, the GAVO project 
  9  #c 
 10  #c This program is free software, covered by the GNU GPL.  See the 
 11  #c COPYING file in the source distribution. 
 12   
 13   
 14  import time 
 15   
 16  from nevow import compression 
 17  from nevow import inevow 
 18  from nevow import rend 
 19   
 20  from gavo import utils 
 21   
 22   
23 -def instrumentRequestForCaching(request, finishAction):
24 """changes request such that finishAction is called with the request and 25 the content written for a successful page render. 26 """ 27 request = inevow.IRequest(request) 28 # For now, we don't cache compressed responses 29 if isinstance(request, compression.CompressingRequestWrapper): 30 return 31 32 builder = CacheItemBuilder(finishAction) 33 origWrite, origFinishRequest = request.write, request.finishRequest 34 35 def write(content): 36 builder.addContent(content) 37 return origWrite(content)
38 39 def finishRequest(success): 40 if success: 41 builder.finish(request) 42 return origFinishRequest(success) 43 44 request.write = write 45 request.finishRequest = finishRequest 46 47
48 -class CacheItemBuilder(object):
49 """an aggregator for web pages as they are written. 50 51 On successful page generation an function is called with 52 the request and the content written as arguments. 53 """
54 - def __init__(self, finishAction):
55 self.finishAction = finishAction 56 self.contentBuffer = []
57
58 - def addContent(self, data):
59 self.contentBuffer.append(data)
60
61 - def finish(self, request):
62 if request.code==200: 63 self.finishAction(request, "".join(self.contentBuffer))
64 65
66 -class CachedPage(rend.Page):
67 """A piece of cached content. 68 69 This is built with the content to return, the headers, and a 70 unix timestamp for the last modification time (as applicable). 71 This is enough for it to work as a nevow resource (i.e., run 72 a renderHTTP method. 73 74 For cache management, this has a lastUsed unix timestamp that is bumped 75 for each renderHTTP call, and a size attribute that gives the length 76 of the content. 77 """
78 - def __init__(self, content, headers, lastModified):
79 self.content = content 80 self.size = len(content) 81 self.creationStamp = time.time() 82 headers["x-cache-creation"] = str(self.creationStamp) 83 self.changeStamp = self.lastModified = lastModified 84 if "last-modified" in headers: 85 del headers["last-modified"] 86 self.headers = headers.items() 87 self.lastUsed = None
88
89 - def renderHTTP(self, ctx):
90 self.lastUsed = time.time() 91 request = inevow.IRequest(ctx) 92 if self.lastModified: 93 request.setLastModified(self.lastModified) 94 for key, value in self.headers: 95 request.setHeader(key, value) 96 request.setHeader('date', utils.formatRFC2616Date()) 97 return self.content
98 99
100 -def enterIntoCacheAs(key, destDict):
101 """returns a finishAction that enters a page into destDict under key. 102 """ 103 def finishAction(request, content): 104 destDict[key] = CachedPage(content, request.headers, 105 request.lastModified)
106 return finishAction 107