-
Notifications
You must be signed in to change notification settings - Fork 0
/
page
423 lines (359 loc) · 15.7 KB
/
page
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:rdfe="http://redfoot.net/3.0/rdf#"
xmlns:code="http://redfoot.net/3.0/code#"
xmlns:server="http://redfoot.net/3.0/server#"
>
<rdfe:RDFXMLDocument rdf:about="">
<rdfs:label>Redfoot Kernel RDF/XML</rdfs:label>
</rdfe:RDFXMLDocument>
<server:Handler rdf:about="#handler">
<rdfs:label>Default handler</rdfs:label>
<server:display_support rdf:resource="#display_support"/>
<code:python rdf:datatype="http://www.w3.org/2001/XMLSchema#string"><![CDATA[
SERVER = redfoot.namespace("http://redfoot.net/3.0/server#")
# Support tunneling requests for any resource through a server
if request.path.startswith("/;"):
request.uri = URIRef(request.uri.split(";", 1)[-1])
# This was needed to fix a bug that happens fronting redfoot with apache via mod_proxy
if not "://" in request.uri:
request.uri = URIRef(request.uri.replace(":/", "://"))
method = request.method.lower()
if method=="get" or method=="head":
from twisted.web.http import datetimeToString, stringToDatetime, NOT_MODIFIED
if request.user_id:
# TODO: ETag support -- so we can support conditional GETs for
# pages when user is logged in.
valid = False
# set to date in past so that we don't return a 304 for the
# page when the user logs out.
response.setHeader("Last-Modified", datetimeToString(0))
else:
modified_since = request.getHeader('if-modified-since')
if modified_since:
try:
modified_since = stringToDatetime(modified_since)
except:
modified_since = None
last_modified = redfoot.value(request.uri, SERVER.last_modified)
if last_modified:
try:
last_modified = int(float(last_modified))
except:
last_modified = None
if last_modified:
response.setHeader("Last-Modified", datetimeToString(last_modified))
valid = modified_since and last_modified and last_modified <= modified_since
if valid:
response.setStatus(NOT_MODIFIED, "Not Modified")
response.finish()
else:
handler = URIRef("#get_handler", base=__uri__)
redfoot.execute(handler, context=globals())
elif method=="put":
handler = URIRef("#put_handler", base=__uri__)
redfoot.execute(handler, request=request, response=response)
elif method=="post":
handler = URIRef("#get_handler", base=__uri__)
redfoot.execute(handler, request=request, response=response)
else:
response.setStatus(405, "Method Not Allowed")
response.setHeader("ACCEPT", "HEAD")
response.finish()
]]>
</code:python>
</server:Handler>
<server:Handler rdf:about="#get_handler">
<rdfs:label>Default GET handler</rdfs:label>
<server:page_handler rdf:resource="templates/classic#page"/>
<server:page_handler rdf:resource="#RDFXMLDocumentPageHandler"/>
<server:supported_content_types>application/xhtml+xml, application/rdf+xml</server:supported_content_types>
<server:display_support rdf:resource="#display_support"/>
<code:python rdf:datatype="http://www.w3.org/2001/XMLSchema#string">
<![CDATA[
from rdflib.Namespace import Namespace
_logger = redfoot.getLogger(__uri__)
from twisted.internet.threads import deferToThread
from twisted.web.http import datetimeToString
from time import time
KERNEL = Namespace(URIRef("http://redfoot.net/3.0/kernel#"))
SERVER = redfoot.namespace("http://redfoot.net/3.0/server#")
site = URIRef("/data#Site", base=request.host)
request.site = site
if (site, None, None) not in redfoot:
data = redfoot.get_context(redfoot.context_id(site, context_id="context"))
data.add((site, RDF.type, SERVER.Site))
data.add((site, SERVER.allow, URIRef("%s/data#Admin" % request.host)))
install = URIRef("http://redfoot.net/3.0/aspect#install")
#redfoot.check(URIRef("aspects/list", base=redfoot.uri)) # since we're doing other init bits
auth = URIRef("aspects/auth#aspect", base=redfoot.uri)
redfoot.execute(install, aspect=auth , base=request.host)
def lookup(property, default=None):
return request.lookup(property) or redfoot.value(__uri__, property) or default
referer = request.headers.get("referer")
if referer:
REFERER = redfoot.namespace("http://redfoot.net/3.0/referer#")
referer = URIRef(referer)
c = redfoot.get_context(URIRef("referers", base=request.host), creator=__uri__)
if not (c.identifier, RDFS.label, None) in redfoot:
c.add((c.identifier, RDFS.label, Literal("Referers")))
c.add((c.identifier, RDFS.comment, Literal("A context used to keep track of HTTP Referers")))
if not request.uri.startswith(request.host):
if (request.uri, REFERER.referer, referer) not in redfoot:
c.add((request.uri, REFERER.referer, referer))
xmpp = redfoot.xmpp
if xmpp:
xmpp.send(KERNEL.Admin, "Found new referer %s for page %s" % (referer, request.uri))
page_handler = None
content_type = request.parameters.get("content-type")
_logger.debug("content_type: '%s'" % content_type)
if not content_type:
# TODO: is this how we want to determine supported content types?
supported_content_types = lookup(SERVER.supported_content_types)
if supported_content_types:
supported = list()
for type in supported_content_types.split(","):
supported.append(type.strip())
accept = request.headers.get("accept")
if not accept:
accept = "*/*"
_logger.debug("headers: %s" % request.headers)
mimeparse = redfoot.module(URIRef("mimeparse#module", base=redfoot.uri))
try:
content_type = mimeparse.best_match(supported, accept)
except Exception, e:
_logger.exception("While trying to find best_match(%s, %s): %s" % (supported, accept, e))
content_type = mimeparse.best_match(supported, "*/*")
if content_type:
content_type = Literal(content_type)
_logger.debug("supported: %s accept: %s best_match: %s" % (supported, accept, content_type))
else:
content_type = None
for handler in request.objects(SERVER.page_handler):
redfoot.check(handler)
if content_type:
handler_content_type = redfoot.value(handler, SERVER.content_type)
if handler_content_type is None:
_logger.error("handler '%s' must have a content_type. request.uri: %s" % (handler, request.uri))
if handler_content_type == content_type:
page_handler = handler
break
else:
page_handler = handler
break
if page_handler is None:
for handler in redfoot.objects(__uri__, SERVER.page_handler):
redfoot.check(handler)
if content_type:
handler_content_type = redfoot.value(handler, SERVER.content_type)
if handler_content_type is None:
_logger.error("handler '%s' must have a content_type. request.uri: %s" % (handler, request.uri))
if handler_content_type == content_type:
page_handler = handler
break
else:
page_handler = handler
break
if page_handler is None:
response.setStatus(404, "Not Found")
response.write("No page handler found")
response.finish()
else:
response.cache_body = True # So that server's request.finish will add content-length, Content-MD5 and ETag headers
# TODO: if resource has last-modified then say so...
#response.setHeader("last-modified", datetimeToString(now))
# TODO: do at end of request processing?
response.setHeader("Cache-Control", "s-maxage=0, must-revalidate")
response.setHeader("Expires", datetimeToString(time()))
#response.setHeader("Vary", "Accept-Encoding")
context = redfoot.execute(lookup(SERVER.display_support),
request=request, response=response, page_handler=page_handler)
display_page = context.get("display_page")
long_running = redfoot.value(request.uri, SERVER.long_running) or redfoot.value(page_handler, SERVER.long_running)
if str(long_running)=="true": # TODO:
def finish(_):
response.finish()
def safe_display_page():
"version of display_page that catches all exceptions"
try:
display_page(page_handler)
except Exception, e:
_logger.exception(e)
response.setStatus(500, "Internal Server Error -- this is hopefully a temporary issue.")
d = deferToThread(safe_display_page)
d.addCallbacks(callback=finish)
else:
display_page(page_handler)
response.finish()
]]>
</code:python>
</server:Handler>
<code:Code rdf:ID="display_support"> <!-- TODO: type-->
<rdfs:label>display support</rdfs:label>
<code:python rdf:datatype="http://www.w3.org/2001/XMLSchema#string">
<![CDATA[
# TODO: this is a bit out of hand :(
_logger = redfoot.getLogger(__uri__)
from rdflib import BNode
SERVER = redfoot.namespace("http://redfoot.net/3.0/server#")
KID = redfoot.namespace("http://redfoot.net/3.0/kid#")
kid_module = redfoot.module(URIRef("kid#module", base=redfoot.uri))
# redefine lookup
def lookup(property, default=None, uri=None):
return request.lookup(property, uri=uri) or redfoot.value(page_handler, property) or default
auth = redfoot.module(URIRef("auth#module", base=redfoot.uri))
def allow(uri):
return auth.allow(request, uri)
def display_page(uri, output=None, **args):
_logger.debug("display_page: %s" % uri)
if not allow(request.uri):
response.setStatus(403, "Forbidden")
redfoot.check(uri)
content_type = redfoot.value(uri, SERVER.content_type) or 'text/html; charset=UTF-8'
if content_type=="application/xhtml+xml":
content_type = "text/html" # For now don't worry about xhtml
if "text/html" in content_type:
output = "html-strict"
else:
output = "xml"
response.setHeader('Content-Type', content_type)
display(uri, fragment=False, output=output, **args)
mod_context = globals()
mod_context["BNode"] = BNode # no longer global
from kid import XML
from StringIO import StringIO
def kid_display(uri, **args):
"""
Due to the way kid works we can not serialize a template within a
template directly to the output stream. Instead we have to return
it as an element stream to the template it appears within. Hence
the create_display level of complexity.
See Also: http://www.kid-templating.org/trac/ticket/29
"""
sio = StringIO()
_w = response.write
response.write = sio.write
is_kid = (uri, KID.template, None) in redfoot
if is_kid:
direct_display = kid_direct_display
else:
direct_display = py_direct_display
direct_display(uri, **args)
response.write = _w
return XML(sio.getvalue())
def kid_direct_display(uri, **args):
context = dict(mod_context)
context.update(args)
value = redfoot.value(uri, KID.template)
if value:
mod = kid_module.get_kid_template(uri, value)
context["display"] = kid_display
t = mod.Template(**context)
try:
t.write(response, encoding="utf-8",
fragment=context.get("fragment") or True, output=context.get("output") or "xml")
except Exception, e:
_logger.exception("While handling request for '%s' and trying to display %s (%s) the following exception occurred:\n" % (request.uri, redfoot.label(uri), uri))
def py_direct_display(uri, **args):
context = dict(mod_context)
context.update(args)
redfoot.execute(uri, **context)
def display(uri, **args):
if uri:
redfoot.check(uri)
if not allow(uri):
uri = lookup(SERVER.unauthorized_content_handler)
assert uri, "No 'unauthorized_content' found for: %s" % uri
request.sources.append(uri)
disp = lookup(SERVER.display, uri=uri)
if disp is None:
raise Exception("%s had no SERVER.display" % uri)
context = dict(mod_context)
context.update(args)
redfoot.execute(disp, context, page_part_uri=uri)
# is_kid = (uri, KID.template, None) in redfoot
# if is_kid:
# direct_display = kid_direct_display
# else:
# direct_display = py_direct_display
# direct_display(uri, **args)
request.sources.pop()
]]>
</code:python>
</code:Code>
<server:PageHandler rdf:about="#rdfxml_handler">
<rdfs:label>Default RDF/XML handler</rdfs:label>
<server:content_type>application/rdf+xml</server:content_type>
<code:python rdf:datatype="http://www.w3.org/2001/XMLSchema#string">
<![CDATA[
#response.setHeader('Content-Type', 'application/rdf+xml')
#cid = request.uri.abstract()
#if (cid, RDF.type, REDFOOT.Context) in redfoot:
# base = None
#else:
# cid = redfoot.context_id(request.uri) # default context
# #base = redfoot.context_id(cid, context_id="") # TODO: basically defrag... need better way
# base = request.uri
cid = redfoot.context_id(request.uri) # default context
base = request.uri
context = redfoot.get_context(cid)
context.serialize(destination=response, base=base)
# NOTE: serialize calls close on response. So we should not call: response.finish()
]]>
</code:python>
</server:PageHandler>
<server:Handler rdf:about="#put_handler">
<rdfs:label>Default GET handler</rdfs:label>
<server:display_support rdf:resource="#display_support"/>
<code:python rdf:datatype="http://www.w3.org/2001/XMLSchema#string">
<![CDATA[
from rdflib.Namespace import Namespace
KERNEL = Namespace(URIRef("http://redfoot.net/3.0/kernel#"))
auth = redfoot.module(URIRef("auth#module", base=redfoot.uri))
uid = auth.authenticate(request)
if uid and (uid, RDF.type, KERNEL.Admin) in redfoot:
#acid = request.uri.abstract()
#if (acid, RDF.type, KERNEL.Context) in redfoot:
# cid = redfoot.context_id(acid) # default context
#else:
# cid = redfoot.context_id(request.uri) # default context
cid = redfoot.context_id(request.uri) # default context
#redfoot.remove_context(cid)
context = redfoot.get_context(cid, creator=uid)
context.remove((None, None, None))
context.add((cid.defrag, RDF.type, URIRef("http://redfoot.net/3.0/rdf#RDFXMLDocument")))
base = redfoot.context_id(cid, context_id="") # TODO: basically defrag... need better way.
context.parse(request.content, publicID=base)
else:
response.setStatus(401, "Not Authorized")
response.setHeader("WWW-Authenticate", "Basic realm='default'")
response.finish()
]]>
</code:python>
</server:Handler>
<server:PageHandler rdf:ID="RDFXMLDocumentPageHandler">
<rdfs:label>RDFXMLDocument PageHandler</rdfs:label>
<server:content_type>application/rdf+xml</server:content_type>
<code:python rdf:datatype="http://www.w3.org/2001/XMLSchema#string">
<![CDATA[
document = request.uri
from rdflib.Graph import Graph
g = Graph(namespace_manager=redfoot.namespace_manager)
prefix = "%s#" % document
for s, p, o in redfoot:
if s==document or (isinstance(s, unicode) and s.startswith(prefix)):
g.add((s, p, o))
##
# This was nice for somethings, but in the case of trying to round
# trip an Ontology via HTTP PUT / GET from an editor... we end up
# with instances from other contexts. Trying without for now.
#if o==document or (isinstance(o, unicode) and o.startswith(prefix)):
# g.add((s, p, o))
response.setHeader('Content-Type', 'application/rdf+xml')
g.serialize(destination=response)#, base=document)
]]>
</code:python>
</server:PageHandler>
</rdf:RDF>