cocoon-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andre Juffer <ajuf...@sun3.oulu.fi>
Subject Re: RESTful applications
Date Mon, 20 Sep 2010 19:06:07 GMT
On 09/20/2010 08:25 PM, Christopher Schultz wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Andre,
>
> On 9/20/2010 6:34 AM, Andre Juffer wrote:
>> Could it be true that Jetty (the one that comes with cocoon is 6.1.7, a
>> rather old one) is actually not supporting the getParameters() family
>> of methods when the HTTP request method is PUT?
>
> This almost certainly the case: the servlet specification only requires
> that getParameter handle request-body data under certain conditions.
> - From the 2.5 version of the spec, section SRV.3.1.1:
>
> "
> The following are the conditions that must be met before post form data
> will
> be populated to the parameter set:
> 1. The request is an HTTP or HTTPS request.
> 2. The HTTP method is POST.
> 3. The content type is application/x-www-form-urlencoded.
> 4. The servlet has made an initial call of any of the getParameter
> family of methods on the request object.
> "
>
> So, when you use PUT, you don't get parameters in the usual way: you'll
> have to parse them yourself in some way.

Yes, this is exactly right. The discussion you refer to is the one that 
I also have read. The source of my problem is therefore clear.

>
> You might want to refer to this thread on the Tomcat-User mailing list
> for an extended discussion: http://markmail.org/thread/kinlccrweiaesqoh
>
> Note that parameters placed into the URL are always available via
> request.getParameter*

Also correct. I've experimented with this already.

>
> There are several ways you could get your server to extract request-body
> PUT parameters and make them available via the getParameter* family of
> methods. One such way (which would avoid having to do anything nasty
> within Cocoon itself) would be to write a request Filter that overrides
> getParameter* and parses a request body if it is a PUT request.
>
> I have philosophical issues against doing such a thing because I feel
> that PUT was designed to put a copy of the entire request body into the
> URL used to access it, not to pass some complex set of "parameters" in
> the body itself to do something else. But, that's not really for me to
> decide on your behalf: if you want POST behavior from PUT, you'll likely
> have to code it yourself in some way. I can give you some suggestions if
> you would like to take this route.

PUT and POST have somewhat different meanings to RESTful applications 
and I intend to stick to that. On the tomcat list, it was indeed also 
suggested to change a PUT request into a POST request using a Filter. I 
prefer to keep things compatible with standards and specifications.

>
>> I came across some comments that Tomcat (did not mention which version
>> of Tomcat) is also not supporting the getParameters() famility of
>> methods [1]. Tomcat can actually handle PUT, POST etc requests, but
>> blocks them by default [2].
>>
>> Anyone can confirm this?
>
> I can: Tomcat's DefaultServlet (the servlet that responds to all request
> that aren't otherwise handled by other servlets) rejects PUT (and POST)
> requests, but you don't want the DefaultServlet to accept them anyway:
> you want your REST-processing code to handle them. Tomcat will not
> interfere with any servlet that expects to accept a PUT request.

The is indeed the readonly parameter in web.xml to change this behavior, 
but indeed this would not have any impact since the request is handled 
by my cocoon2.2-based servlet.
>
> All Tomcat versions should behave this way, as the servlet specification
> has been (relatively) consistent across the versions covered by Tomcat
> implementations.

Yes, I got to the same conclusion, again from the Tomcat list. That list 
was in fact extremely helpful to understand what is going on.

>
> Your first problem, though, was that request.getMethod was always
> returning "GET" even when the method should be "PUT", right?

Correct.

>
> Can you show us how you have configured your pipepine (including how you
> extract the "method" from the request) and also how you are declaring
> and then using the method in your XSLT?

I use the sitemap that was generated during block creation with Maven, 
as documented on the cocoon website. I've added the following:

<map:serializers>
   <map:serializer name="json" mime-type="application/json; 
charset=UTF-8" src="org.apache.cocoon.serialization.TextSerializer">
     <encoding>UTF-8</encoding>
   </map:serializer>
   <map:serializer name="xml" mime-type="text/xml"
                   src="org.apache.cocoon.serialization.XMLSerializer">
     <encoding>UTF-8</encoding>
   </map:serializer>
</map:serializers>

The pipeline that handles the request is really extremely simple:

<map:match pattern="*">
   <map:call function="equipmentHandler">
     <map:parameter name="method" value="{request:method}" />
   </map:call>
</map:match>

So, all requests are forwarded to a single function (for now). The 
map:parameter is just there to test the value of the request method, as 
I did not get the expected response. I actually do not use it in any 
XSLT. I will remove this line as soon as I get the right request method 
value in the equipmentHandler() function.

The equipmentHandler() function is basically implemented as (stripped 
version)

function equipmentHandler()
{
     var request = cocoon.request;
     var method = request.getMethod();
     // var method = cocoon.parameters.method;
     if ( method == "GET" )
     {
       var id = ....  // From request.
       // get equipment from database.
       var equipment = ...;
     } else if (method == "PUT")
     {
       // Extract all parameters like:
       var name = request.getParameter("name");
       ...
       // Store in database.
       equipment = ...
     } else
	// Illegal request.
     ...
     // Create response.
     var format = request.getParameter("format");  // Only JSON or XML.
     var response = cocoon.response;
     response.setStatus(...);
     cocoon.sendPage("equipments." + format,
     {
       "equipment" : equipment
     });
}

This function communicates with a Facade to manage equipment resources 
stored in a postgres database. Equipment is returned as DTO objects, 
which that is/are then converted to XML or JSON. This all works without 
any problem, except of course that the request method is always GET 
instead PUT or some other value.

The code is pretty much standard and as far as I can see is not 
interfering at all with the actual request. The only thing that is not 
yet clear to me why the request method is always GET. I am wondering now 
if Jetty or Tomcat are converting a PUT request simply into a GET request.

>
> - -chris
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (MingW32)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
>
> iEYEARECAAYFAkyXmPgACgkQ9CaO5/Lv0PD58ACguAHmp+VXpHeSwCHmdjGDz/95
> 4FwAoLkyYpHW3gxn0alEdEeNEtjYyFEz
> =j9hU
> -----END PGP SIGNATURE-----
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@cocoon.apache.org
> For additional commands, e-mail: users-help@cocoon.apache.org
>


-- 
Andre H. Juffer              | Phone: +358-8-553 1161
Biocenter Oulu and           | Fax: +358-8-553-1141
Department of Biochemistry   | Email: andre.juffer@oulu.fi
University of Oulu, Finland  | WWW: www.biochem.oulu.fi/Biocomputing/
StruBioCat                   | WWW: www.strubiocat.oulu.fi
NordProt                     | WWW: www.nordprot.org
Triacle Biocomputing         | WWW: www.triacle-bc.com

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@cocoon.apache.org
For additional commands, e-mail: users-help@cocoon.apache.org


Mime
View raw message