[Grok-dev] Re: Using POST request

Uli Fouquet uli at gnufix.de
Tue Mar 25 09:59:45 EDT 2008

Hi there,

Martijn Faassen wrote:
> Uli Fouquet wrote:
> [snip: ':action' form fields require appropriate methods]

> I'm trying to understand the reasoning here. Why would a view named 
> file_upload be required in order to process this field? What would be 
> trying to access this file_upload view? There's after all only a single 
> multipart/form-data POST request being made - do you think setuptools is 
> sending another request?

No, sorry for being unclear. The whole request is handled by an
'file_upload' method/view/callable - if it exists 'inside' an 'eggs'
object. I meanwhile tried my example from the last post and it works.

> Perhaps zope's publisher machinery somehow fails badly on something in 
> this form, and as a result an exception gets raised that inadvertantly 
> is translated into a 404 error. The 'name=":action"' bit looks pretty 
> weird, though you'd think you'd simply get a request.form[':action'] 
> field as a result.

The ``:action`` field is in fact the reason for the strange behaviour. I
digged a bit deeper, to understand what's happening here.

As you know, you can tell the publisher to treat form fields specially
using a '<key>:<type>' syntax. Such you can send a form field named
``myval:int`` to get myval as an integer (and not a string).

Similarily you can tell the publisher to let the request be processed by
a certain method using ``<name-of-method>:action`` syntax. I'm sure, you
already knew that, but for the archives and other people that get stuck
with strange 'action' fields behaviour, I might explain that in detail.

The code in ``zope.publisher.browser.BrowserRequest.__processItem()``::

    def __processItem(self, item):
        """Process item in the field storage."""
        # [...]
        key = item.name
        # [...]
        while key:
            pos = key.rfind(":")
            key, type_name = key[:pos], key[pos + 1:]
            # [...]
            # find the right type converter
            c = get_converter(type_name, None)
            if c is not None:
                converter = c
                flags |= CONVERTED
            # [...]
            elif (type_name == 'method' or type_name == 'action'):
                if key:
                    self.__meth = key
                    self.__meth = item
            # [...]

This code is executed, before the traverser starts and ``__meth`` will
be appended to the traverser path. So in an HTML-form you such can say::

  <input type="hidden" name=":action" value="myhandler" />

(note the leading colon in the name attribute) or::

  <input type="hidden" name="myhandler:action" />

to let the posted request be handled by a `myhandler` method.

Now, given we have an object 'eggs' which should normally handle the
request and which is reachable vie URL `localhost:8080/eggs`, we now,
with the ':action' field set to 'file_upload' let the traverser look for
'eggs/file_upload' instead of just 'eggs'. You send the request to
`localhost:8080/eggs` but the traverser will in fact look for
`localhost:8080/eggs/file_upload`, find nothing and return a 404.

With the appropriate view (i.e. one that is named 'file_upload') you can
handle this. But what about REST now?

Hope that helps.

Kind regards,


-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 191 bytes
Desc: Dies ist ein digital signierter Nachrichtenteil
Url : http://mail.zope.org/pipermail/grok-dev/attachments/20080325/0b1132c0/attachment.bin

More information about the Grok-dev mailing list