[Twisted-web] State and web2 (or, how to not follow REST)
Clark C. Evans
cce at clarkevans.com
Mon Nov 21 12:41:47 MST 2005
On IRC today, foom pointed out that my idea for distinguishing between
things that modify a request (a IRequestHandler) such as setting up a
session or authenticating a user, must also be able to happen between
IResources. The example given was /~user/bing/my-app/foo, where
authentication (and possibly setting up a session) happens:
/~user/bing/{HERE}my-app/foo
So, goal is to distinguish between Resources which should not be
modifying the request's context and RequestFilters which by definition
change the request. The glue can be done by having a ContextResource
that explicitly applies one or more RequestFilters on the current
request. We can then designate a syntax for asserting that the
application of a particular IRequestFilter has been done on the request.
Anyway, just consider this a random attempt to detail the idea....
class IRequestFilter(Interface):
"""
I am a filter that is applied to a given request, examples of
a RequestFilter are, a "SessionManager", "Authenticator", etc.
"""
def apply(self, request):
""" Perform necessary logic on the request, modifying the
request's context as necessary and/or raising HTTPError
as needed. Ideally only an IRequestFilter modifies a
request's context.
"""
class IResource:
# same as before, adding:
require = Attribute(
"A sequence of IRequestFilters which must have
been applied to a Request before this resource
is accessed")
class IRequest(Interface):
# same as before, adding:
filtered = Attribute(
"A sequence of IRequestFilters that have been applied.")
# since there are two objects that are so commonly used, I feel
# that they merit their own "slot" on the Request object:
session = Attribute("An optional ISession object added by the
ISessionRequestFilter.")
avatar = Attribute("An optional IAvatar object added by the
IAuthenticateRequestFilter, or other providers of
an IAvatar")
class ContextResource(Resource): # or SiteResource, or AppResource
"""
I am a application or site resource which modifies the
incoming request via a set of RequestFilters. Only
ContextResources should be doing this sort of thing.
"""
filter = None
def registerFilter(self, requestFilter):
if not self.filter:
self.filter = [requestFilter]
return
self.filter.append(requestFilter)
def locateChild(self, request, segments):
for filter in self.filter:
filter.apply(request)
request.filtered.append(filter)
Resource.locateChild(self, request, segments)
myapp = ContextResource()
myapp.registerFilter(SessionManager())
myapp.registerFilter(HTTPAuthHandler())
More information about the Twisted-web
mailing list