[Grok-dev] Re: HTTP PUT and HTTP DELETE security support
Philipp von Weitershausen
philipp at weitershausen.de
Wed May 23 06:07:58 EDT 2007
Martijn Faassen wrote:
> Hey Philipp,
> Thanks for the feedback!
> Before I go into your reply, I must remark that there's another issue
> surrounding this I just found out I need your guidance on: our Grok
> traversers don't work in the case of PUT, because they're registered for
> IBrowserRequest. Changing them to work for IHTTPRequest fixes this in my
> case, but can you think of any problems with that?
Well, traversers are also responsible for looking up views in case
object graph traversal (e.g. container[subitem]) doesn't yield anything.
This looking up views is different in the HTTP-only world than in the
> Philipp von Weitershausen wrote:
>> Martijn Faassen wrote:
>> [snip discussion of various approaches to implementing a PUT view]
>> I would suggest introducing a grok.REST class:
>> class MammothREST(grok.REST):
>> def PUT(self):
>> def DELETE(self):
>> def ANY_HTTP_VERB(self):
> Doing this makes it harder to have one bit of code that adds PUT to an
> object, and another bit of code that adds DELETE. I don't think this is
> a problem though - something that's going to support PUT probably should
> support DELETE right along anyway.
Yes. Also, it's not said that you couldn't override DELETE. You would
just implement a new grok.REST subclass with just a DELETE method:
# new implementation of DELETE, the rest from the old
# implementation stays
How's that possible? Because each HTTP verb handler is its own adapter.
So that grok.REST subclass would be registered once for each verb method
that it implements.
>> Naturally, we'll have to come up with a decent interpretation of the
>> GET/POST case. By default, GET/POST are interpreted as browser
>> requests and the browser publication looks up a default view ('index')
>> when your GETting or POSTing to a resource (/herd/manfred ends up
>> really being /herd/manfred/index). Perhaps if there's no such 'index'
>> view, Grok's browser publication will fall back to the REST adapter
>> and lookup the "GET" view (or "POST view, respectively):
> Actually both PUT and POST are supposed to return something as well.
> While POST will likely do something special, PUT, as far as I understand
> is, actually is defined to return whatever GET would return. This means
> you'd like an index view to be there that PUT falls back on when it's
> done PUTting.
> The alternative would be to say that people should just implement a GET
> method in this case.
>> class Herd(grok.Container):
>> class HerdREST(grok.REST):
>> def POST(self, item_name, name='Manfred'):
>> self.context[item_name] = mammoth = Mammoth(name)
>> We could also do it the other way around, like you suggest, and look
>> for the REST handlers for GET/POST first, before falling back to
>> 'index' browser pages.
> Let's summarize this idea as it stands now:
> GET - use REST handler, otherwise fall back on index view
> POST - use REST handler, otherwise fall back on index view
> PUT - use REST handler, for results then run normal index view (as with GET)
Unless the PUT method returns something other that None. In that case
that return value is returned to the client.
> DELETE - use REST handler. Need to research what result is expected, but
> I think that's a special HTTP status.
Sounds good otherwise. We could also think about a default fallback.
Let's say I want my POST handler to become active only in a certain
case, otherwise I want to fall back on the index view. We could indicate
this by returning None or non-None:
def POST(self, body=''):
self.context.body = body
return something_thats_not_None # or redirect
return None # not necessary
So, if body is missing from the request or empty, this method will
return None and the publication will proceed to the index view.
By the way, I've been wondering... grok.JSON, grok.XMLRPC, grok.REST are
all views. grok.View is a browser page and also a view. Perhaps it
should be grok.Page or even grok.BrowserPage instead of grok.View, just
for the symmetry of things?
>>> It will take a bit of work to make this happen though, as I don't
>>> think the zope 3 publisher supports doing this out of the box.
>> The Zope 3 publisher supports everything out-of-the-box :). That is to
>> say that the actual policy is in the publication (what happens when,
>> which views to look up, etc.).
> Okay, I should say the Zope 3 publication doesn't support this out of
> the box. After a few years of bashing my head against that code I'm
> finally getting some idea of how it works, but I'm sure I'll forget it
> again soon. :)
For my training I drew neat little pictures that I'll try to include in
a future edition of the book.
>>> Comments? Ideas? Eager Zope 3 publisher hackers volunteering to start
>>> building this? :)
>> I've long been wanting to build a saner publication than
>> zope.app.publication. With as many modifications as we're planning, it
>> might make sense to start from scratch...
> I'm motivated by a Real World Project (tm) so this will have to have
> somebody else driving it. I am hoping I can start making what we've
> sketched out here work (one way or another) in the Grok core next week.
> If you think we can write a new publication machinery in a few days then
> I'd be happy to help.
I might be able to round up some time next week.
>> Btw, I suppose we've now settled on the idea of making Grok explicitly
>> *not* compatible with traditional Zope 3 browser pages defined via
>> <browser:page />, right?
> What do you mean by not compatible? I think it should remain possible to
> add a traditional <browser:page> to a Grok model. That's our "mutual
> compatibility principle". Would there be a benefit towards breaking such
I thought we wanted to rid ourselves from the Zope 3-induced "ZMI"
views? Perhaps I misunderstood. I agree that the Mutual compatibility
principle is a good thing.
http://worldcookery.com -- Professional Zope documentation and training
More information about the Grok-dev