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
9
10
11
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
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
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
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 """
55 self.finishAction = finishAction
56 self.contentBuffer = []
57
58 - def addContent(self, data):
59 self.contentBuffer.append(data)
60
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
106 return finishAction
107