Re: [Twisted-web] [Twisted-Python] http.Request and JSON

On Tue, 30 Jun 2009 13:12:05 +0100, Reza Lotun <rlotun@gmail.com> wrote:
Hi,
On Tue, Jun 30, 2009 at 12:56 PM, Tristan Seligmann<mithrandi@mithrandi.net> wrote:
To be safer, I do a request.content.getvalue() since content is a cStringIO object and you can never be sure if somewhere along the chain of processing someone hasn't done a .read and forgot to do a .seek(0,0).
You should probably do the seek/read instead, since I don't believe this is guaranteed to be a cStringIO; it might be an actual file on disk, or something else.
If that's true then there really should be a .get_body() method on the request object.
Why can't you seek and read? Also, this discussion would be more appropriate on the twisted-web mailing list. Jean-Paul

On Tue, Jun 30, 2009 at 1:41 PM, Jean-Paul Calderone<exarkun@divmod.com> wrote:
If that's true then there really should be a .get_body() method on the request object.
Why can't you seek and read?
I can, but it's not "nice". I realize that on some level twisted.web is a bit low-level, but having to remember to do a seek then read is a bit annoying. I'm sure those of us using twisted.web to, say, implement a REST interface end up writing some sort of convenience method anyway to do it. Perhaps there are other complications I haven't considered, but why can't you add a get_body method? Cheers, Reza -- Reza Lotun +44 (0)7521 310 763 rlotun@gmail.com

Reza Lotun wrote:
On Tue, Jun 30, 2009 at 1:41 PM, Jean-Paul Calderone<exarkun@divmod.com> wrote:
If that's true then there really should be a .get_body() method on the request object. Why can't you seek and read?
I can, but it's not "nice". I realize that on some level twisted.web is a bit low-level, but having to remember to do a seek then read is a bit annoying. I'm sure those of us using twisted.web to, say, implement a REST interface end up writing some sort of convenience method anyway to do it.
Perhaps there are other complications I haven't considered, but why can't you add a get_body method?
A file-like is a python-esque idiom. You can pass it to all kinds of things e.g. JSON parsers, XML parsers. What if the body is a 1 gigabyte string? Do you want twisted to read the results in from the tempfile, instantiate a python string, and probably get killed due to an out-of-memory condition? I vote for the file-like.

Hi, On Tue, Jun 30, 2009 at 4:38 PM, Phil Mayers<p.mayers@imperial.ac.uk> wrote:
A file-like is a python-esque idiom. You can pass it to all kinds of things e.g. JSON parsers, XML parsers.
What if the body is a 1 gigabyte string? Do you want twisted to read the results in from the tempfile, instantiate a python string, and probably get killed due to an out-of-memory condition?
Ok, fair enough. I suppose what I was getting at as in general a nicer way to extract body content. I agree the file-like idiom is pythonic and probably better overall. I've just seen some annoying debugging sessions where seek wasn't being performed and reads yielding nothing - it's rather confusing when you get into that situation. I guess there's no magic bullet for that. In fact, I guess the real annoyance stems from the memory of finally figuring out that the body could be retrieved from request.content *in the first place* took far too long when I was learning twisted.web. But that's a different discussion entirely. Thanks, Reza -- Reza Lotun +44 (0)7521 310 763 rlotun@gmail.com

Is it just me, or do I not get the spirit of HTTPAuthSessionWrapper. Why does it have a render method? This is a wrapper, shouldn't it be calling the render of the avatar that it's fetching, not itself? Why isn't it just a mixin that can enforce HTTP auth for any arbitrary resource?

It seems to be completely broken for wrapping a child resource. You can wrap the site root resource, but not a child? What am I missing here? -----Original Message----- From: twisted-web-bounces@twistedmatrix.com [mailto:twisted-web-bounces@twistedmatrix.com] On Behalf Of Jared Gisin Sent: Tuesday, June 30, 2009 3:33 PM To: Twisted Web World Subject: [Twisted-web] HTTPAuthSessionWrapper render Is it just me, or do I not get the spirit of HTTPAuthSessionWrapper. Why does it have a render method? This is a wrapper, shouldn't it be calling the render of the avatar that it's fetching, not itself? Why isn't it just a mixin that can enforce HTTP auth for any arbitrary resource? _______________________________________________ Twisted-web mailing list Twisted-web@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web

On Tue, 30 Jun 2009 15:38:46 -0700, Jared Gisin <jared.gisin@isilon.com> wrote:
It seems to be completely broken for wrapping a child resource. You can wrap the site root resource, but not a child? What am I missing here?
Its render method only ever raises NotImplementedError. This is because it isn't ever supposed to be invoked. If the code is working correctly, then the only thing which will ever happen to an HTTPAuthSessionWrapper is that some child of it will be requested. That child may be rendered. If you're seeing HTTPAuthSessionWrapper.render get invoked, then it may be due to a bug in Twisted or due to a bug in how your code uses the wrapper. Can you provide more details about what you're doing? Perhaps we can track down the cause of the behavior you're observing. Jean-Paul

I guess the problem that I have is that there's an example for it, where you wrap the root object that gets passed into a twisted.web.server.Site() instantiation. My application doesn't require auth for every thing in the site; only certain subtrees of the Resource hierarchy, so how in the world in a Resource's __init__(self): would I hook this up to something that I'd pass into self.putChild() Here, I've modified the realm to hand back the Resource object passed in upon authentication. site = server.Site( guard.HTTPAuthSessionWrapper(Portal(APIRealm(Root()), CRED_CHECKERS), CRED_FACTORIES)) But suppose I have under Root() a resource V1, then the following doesn't work: class Root(Resource): def __init__(self): Resource.__init__(self) self.putChild('1', guard.HTTPAuthSessionWrapper( Portal(APIRealm(V1()), CRED_CHECKERS), CRED_FACTORIES)) Self.putChild('', self) What winds up happening is that it things an instance of HTTPAuthSessionWrapper is the child of Root, and when I access a URI such as /1?blah, which I expect to render something, it winds up calling the render method of that HTTPAuthSessionWrapper, which is wrong. It needs to call render of V1(), not it's wrapper. What do I have wrong? -Jared -----Original Message----- From: twisted-web-bounces@twistedmatrix.com [mailto:twisted-web-bounces@twistedmatrix.com] On Behalf Of Jean-Paul Calderone Sent: Tuesday, June 30, 2009 5:17 PM To: Twisted Web World Subject: Re: [Twisted-web] HTTPAuthSessionWrapper render On Tue, 30 Jun 2009 15:38:46 -0700, Jared Gisin <jared.gisin@isilon.com> wrote:
It seems to be completely broken for wrapping a child resource. You can wrap the site root resource, but not a child? What am I missing here?
Its render method only ever raises NotImplementedError. This is because it isn't ever supposed to be invoked. If the code is working correctly, then the only thing which will ever happen to an HTTPAuthSessionWrapper is that some child of it will be requested. That child may be rendered. If you're seeing HTTPAuthSessionWrapper.render get invoked, then it may be due to a bug in Twisted or due to a bug in how your code uses the wrapper. Can you provide more details about what you're doing? Perhaps we can track down the cause of the behavior you're observing. Jean-Paul _______________________________________________ Twisted-web mailing list Twisted-web@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web

On Wed, 1 Jul 2009 07:12:25 -0700, Jared Gisin <jared.gisin@isilon.com> wrote:
I guess the problem that I have is that there's an example for it, where you wrap the root object that gets passed into a twisted.web.server.Site() instantiation. My application doesn't require auth for every thing in the site; only certain subtrees of the Resource hierarchy, so how in the world in a Resource's __init__(self): would I hook this up to something that I'd pass into self.putChild()
Here, I've modified the realm to hand back the Resource object passed in upon authentication.
site = server.Site( guard.HTTPAuthSessionWrapper(Portal(APIRealm(Root()), CRED_CHECKERS), CRED_FACTORIES))
But suppose I have under Root() a resource V1, then the following doesn't work:
class Root(Resource):
def __init__(self): Resource.__init__(self)
self.putChild('1', guard.HTTPAuthSessionWrapper( Portal(APIRealm(V1()), CRED_CHECKERS), CRED_FACTORIES))
Self.putChild('', self)
What winds up happening is that it things an instance of HTTPAuthSessionWrapper is the child of Root, and when I access a URI such as /1?blah, which I expect to render something, it winds up calling the render method of that HTTPAuthSessionWrapper, which is wrong. It needs to call render of V1(), not it's wrapper. What do I have wrong?
That sounds like a reasonable thing to be doing, in which case what you said about HTTPAuthSessionWrapper.render passing through to the avatar sounds like the right behavior. Can you file a ticket in the issue tracker for this? Jean-Paul

Yes, I can file a bug. Is there a reason why this HTTPAuthSessionWrapper isn't a mixin for resource.Resource? I've shoehorned it into my own custom subclass of resource.Resource that could easily be done as a mixin (though not Ideal due to MRO problem if it's in the wrong order). Better would be to provide a proper HTTPAuthResource that does it. Thoughts? -Jared -----Original Message----- From: twisted-web-bounces@twistedmatrix.com [mailto:twisted-web-bounces@twistedmatrix.com] On Behalf Of Jean-Paul Calderone Sent: Wednesday, July 01, 2009 7:49 AM To: Twisted Web World Subject: Re: [Twisted-web] HTTPAuthSessionWrapper render On Wed, 1 Jul 2009 07:12:25 -0700, Jared Gisin <jared.gisin@isilon.com> wrote:
I guess the problem that I have is that there's an example for it, where you wrap the root object that gets passed into a twisted.web.server.Site() instantiation. My application doesn't require auth for every thing in the site; only certain subtrees of the Resource hierarchy, so how in the world in a Resource's __init__(self): would I hook this up to something that I'd pass into self.putChild()
Here, I've modified the realm to hand back the Resource object passed in upon authentication.
site = server.Site( guard.HTTPAuthSessionWrapper(Portal(APIRealm(Root()), CRED_CHECKERS), CRED_FACTORIES))
But suppose I have under Root() a resource V1, then the following doesn't work:
class Root(Resource):
def __init__(self): Resource.__init__(self)
self.putChild('1', guard.HTTPAuthSessionWrapper( Portal(APIRealm(V1()), CRED_CHECKERS), CRED_FACTORIES))
Self.putChild('', self)
What winds up happening is that it things an instance of HTTPAuthSessionWrapper is the child of Root, and when I access a URI such as /1?blah, which I expect to render something, it winds up calling the render method of that HTTPAuthSessionWrapper, which is wrong. It needs to call render of V1(), not it's wrapper. What do I have wrong?
That sounds like a reasonable thing to be doing, in which case what you said about HTTPAuthSessionWrapper.render passing through to the avatar sounds like the right behavior. Can you file a ticket in the issue tracker for this? Jean-Paul _______________________________________________ Twisted-web mailing list Twisted-web@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web

On Wed, 1 Jul 2009 13:34:41 -0700, Jared Gisin <jared.gisin@isilon.com> wrote:
Yes, I can file a bug.
Is there a reason why this HTTPAuthSessionWrapper isn't a mixin for resource.Resource?
As a mixin, what functionality would it be providing? The functionality it provides now is that arbitrary resources can be protected by HTTP authentication without being modified. I can't quite see how a mixin achieve that goal.
I've shoehorned it into my own custom subclass of resource.Resource that could easily be done as a mixin (though not Ideal due to MRO problem if it's in the wrong order). Better would be to provide a proper HTTPAuthResource that does it. Thoughts?
I'm not really sure what you mean here. You actually mixed HTTPAuthSessionWrapper into a Resource subclass and got it to do something? That's surprising, and not the intended use. :) Jean-Paul

-----Original Message----- From: twisted-web-bounces@twistedmatrix.com [mailto:twisted-web-bounces@twistedmatrix.com] On Behalf Of Jean-Paul Calderone Sent: Wednesday, July 01, 2009 2:20 PM To: Twisted Web World Subject: Re: [Twisted-web] HTTPAuthSessionWrapper render On Wed, 1 Jul 2009 13:34:41 -0700, Jared Gisin <jared.gisin@isilon.com> wrote:
Yes, I can file a bug.
Is there a reason why this HTTPAuthSessionWrapper isn't a mixin for resource.Resource?
As a mixin, what functionality would it be providing? [JG]: It would be providing resource authentication. You mix it into any subclass of resource.Resource and it makes that resource require HTTPAuth of some sort. The functionality it provides now is that arbitrary resources can be protected by HTTP authentication without being modified. I can't quite see how a mixin achieve that goal. [JG]: Which in my experience (lack of proper documentation) doesn't work for anything other than what you pass in as the root to site.Site(). Try appending a Child resource wrapped in HTTPAuthSessionWrapper and it fails to properly call .render() on the wrapped resource. The parent find the HTTPAuthSessionWrapper and calls render on that thing, which return an Unimplemented, which is my complaint.
I've shoehorned it into my own custom subclass of resource.Resource that could easily be done as a mixin (though not Ideal due to MRO problem if it's in the wrong order). Better would be to provide a proper HTTPAuthResource that does it. Thoughts?
I'm not really sure what you mean here. You actually mixed HTTPAuthSessionWrapper into a Resource subclass and got it to do something? That's surprising, and not the intended use. :) [JG]: I didn't mix it in as I copied the functions directly and adapted them to work directly in my resource.Resource subclass. I refactored my mixin to be a custom resource.Resource that does what I want. It seemed to me that HTTP Auth should be provided at the per-resource level. As resource.Resource creates a hierarchy of resources, what I want to do is mark a particular leaf as requiring HTTP Auth. I might also want to mark an entire subtree as requiring auth by setting a flag on the parent resource. Then, as the twisted starts parsing thru the URI resource children from the root Resource, as soon as it hits a resource that requires HTTP Auth, it would go off and perform the HTTP header inspection and authentication processing, creating a Portal on the fly with the avatar returned by the realm set to the next child. When the login calls return, the getChildWithDefault continues on with the next child avatar that was passed in to the realm when the requirement for Authentication was hit while walking the resource tree for the incoming URI. It seems hokey to "wrap" a resource in another resource, when in reality, all it's doing is inserting a resource in the hierarchy. Parent -> Child becomes Parent -> Wrapper -> Child. IT would seem wiser to have a mixin or a proper HTTPAuthResource class that includes this functionality without this extra "wrapper" layer. Such a properly designed resource could include instantiation parameters that define the type of authentication to be performed, passing in cred checkers, a realm, portal, whatever is required for that resource. I'm probably starting to mix in too much stuff into the base functionality, which as I can see is why nevow implements a totally different resource model to fit the needs of a web application. Likely I'm just as well off to roll my own type of resources that behaves as I see fit for my purposes just as nevow did. Either way, better documentation describing how the this thing is indented to work would have saved me lots of trouble. I would imagine that the core functionality of twisted would be designed to support many different uses cases, not a single, undocumented use case. _______________________________________________ Twisted-web mailing list Twisted-web@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web

On Mon, 6 Jul 2009 10:37:39 -0700, Jared Gisin <jared.gisin@isilon.com> wrote:
[snip]
[JG]: I didn't mix it in as I copied the functions directly and adapted them to work directly in my resource.Resource subclass. I refactored my mixin to be a custom resource.Resource that does what I want. It seemed to me that HTTP Auth should be provided at the per-resource level. As resource.Resource creates a hierarchy of resources, what I want to do is mark a particular leaf as requiring HTTP Auth. I might also want to mark an entire subtree as requiring auth by setting a flag on the parent resource. Then, as the twisted starts parsing thru the URI resource children from the root Resource, as soon as it hits a resource that requires HTTP Auth, it would go off and perform the HTTP header inspection and authentication processing, creating a Portal on the fly with the avatar returned by the realm set to the next child. When the login calls return, the getChildWithDefault continues on with the next child avatar that was passed in to the realm when the requirement for Authentication was hit while walking the resource tree for the incoming URI. It seems hokey to "wrap" a resource in another resource, when in reality, all it's doing is inserting a resource in the hierarchy. Parent -> Child becomes Parent -> Wrapper -> Child. IT would seem wiser to have a mixin or a proper HTTPAuthResource class that includes this functionality without this extra "wrapper" layer. Such a properly designed resource could include instantiation parameters that define the type of authentication to be performed, passing in cred checkers, a realm, portal, whatever is required for that resource. I'm probably starting to mix in too much stuff into the base functionality, which as I can see is why nevow implements a totally different resource model to fit the needs of a web application. Likely I'm just as well off to roll my own type of resources that behaves as I see fit for my purposes just as nevow did. Either way, better documentation describing how the this thing is indented to work would have saved me lots of trouble. I would imagine that the core functionality of twisted would be designed to support many different uses cases, not a single, undocumented use case.
The gist of this seems to be that you prefer inheritance to composition, whereas I (and many other Twisted developers) prefer composition over inheritance. :) Aside from the bug which started this conversation, I think HTTPAuthResource can provide all of the functionality you're interested in. Jean-Paul
participants (4)
-
Jared Gisin
-
Jean-Paul Calderone
-
Phil Mayers
-
Reza Lotun