IResource compatibility layer breaks on leaf resources with pre/postpath manipulation
exarkun opened this issue · comments
If an IResource is placed into a NevowSite resource hierarchy and there is a resource beneath it with isLeaf = True
and which also shuffles segments between prepath
and postpath
then OldResourceAdapter
mangles prepath
and postpath
in a way that ruins them as information letting the leaf resource determine what the request was and where it lives in the resource hierarchy during rendering.
This exact combination of behavior is what you get if you try to use twisted.web.guard
inside a Nevow resource hierarchy. Guard provides HTTPAuthSessionWrapper
which returns isLeaf = True
children by way of its use of twisted.web.util.DeferredResource
. It also takes the last element of prepath
and moves it back to the beginning of postpath
to "unconsume" one segment of the URL. The ideis that HTTPAuthSessionWrapper
is a transparent wrapper around a sub-tree of the resource hierarchy and does not represent any resource in the hierarchy itself.
The offending Nevow code can be seen here:
def renderHTTP(self, ctx):
request = inevow.IRequest(ctx)
if self.real_prepath_len is not None:
request.postpath = request.prepath[self.real_prepath_len:]
del request.prepath[self.real_prepath_len:]
result = defer.maybeDeferred(self.original.render, request).addCallback(
self._handle_NOT_DONE_YET, request)
return result
Unfortunately there are no unit tests for this behavior and the comment for real_prepath_len
doesn't clearly (to me) explain why this behavior is implemented or what problem it solves.
My best guess is that the intent is the restoration of prepath
and postpath
to their values at the time the leaf was encountered. The implementation is correct as long as the two lists aren't mutated outside of the control of Nevow but it fails if they are.