Re: RESTful applications
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() famility of methods when the HTTP request method is PUT? It just supports GET and HEAD (is required to support these methods). If so, the problem is Jetty, not cocoon. 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? [1] http://osdir.com/ml/users-tomcat.apache.org/2010-03/msg01410.html [2] http://marc.info/?l=tomcat-userm=127382305322732w=2 On 09/19/2010 05:42 PM, Andre Juffer wrote: Let me just add some additional information. I use Dojo 1.5 (www.dojotoolkit.org) on the client (browser). No dojo on the server. I've created a few blocks (one of them is called 'equipment' and another one is called 'webapp') according to the cocoon 2.2 documentation. No extra configuration was done. I do not use CForms at all. At some point, on the client (firefox) a form is processed that results in a HTTP PUT request. The request is assembled with dojo.xhrPut(), a Dojo function. With Firebug 1.5.4, I see that the following request is submitted (cut and pasted from the Firebug console): PUT http://localhost:/equipment Parameters (application/x-www-form-urlencoded) categoryTest descriptionTesting purposes manufacturerTester Ltd. nameTest ownerId3375104 taskTesting So far, so good. There is nothing special about this request. Jetty receives the request (jetty was started with mvn jetty:run from the webapp block). The sitemap in the equipment block contains: map:match pattern=* map:call function=equipmentHandler /map:match So, all requests are handled by the function 'equipmentHandler()' (for now at least). This function subsequently calls upon cocoon.request.getMethod() to find out what the HTTP request method is and proceeds accordingly. The cocoon.request.getMethod() always returns GET. I tested this with java.lang.System.out.println(cocoon.request.getMethod()). As a matter of fact, none of the parameters listed above ever reach the equipmentHandler() function. Each cocoon.request.getParameter(..) calls returns null. Could this be an encoding issue? I went through http://cocoon.apache.org/2.2/1366_1_1.html. Thanks for your help, André On 09/18/2010 08:52 PM, Andre Juffer wrote: Hi, I am building a RESTful application with cocoon 2.2. I need to be able to identify the request method. It appears that in the sitemap, {request:method}, or in flow, cocoon.request.getMethod(), the HTTP method value always is GET. I need to be able to distinguish between GET, PUT, OPTIONS, etc in order to handle the request accordingly. If the method value is always GET, then I won't be able to do so. I've tested this all with a tool called RESTClient from WizTools at http://rest-client.googlecode.com/. Could one of you (not) confirm my observation? What to do if indeed the request method is always set to GET? Thanks, -- Andre H. Juffer | Phone: +358-8-553 1161 Biocenter Oulu and | Fax: +358-8-553-1141 Department of Biochemistry | Email: andre.juf...@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-unsubscr...@cocoon.apache.org For additional commands, e-mail: users-h...@cocoon.apache.org
Re: RESTful applications
Just a another follow up. It appears that the whole issue is indeed caused by the servlet engine. According to the sevlet specification, a PUT request will not necessary be parsed for extracting request parameters to make them available through the getParameters() family of methods. It is actually up to the servlet engine whether or not it will do so. In contract, a POST request should (if certain conditions are met). For a PUT request, it seems that Tomcat 6 is -not- parsing the request for extracting parameters [1], while I found some vague statements that Jetty (version unclear) will extract the parameters even for a PUT request. I will try to confirm this all later today. I would appreciate some response in this matter... [1] http://marc.info/?l=tomcat-userm=127005757912988w=2 On 09/20/2010 01:34 PM, 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() famility of methods when the HTTP request method is PUT? It just supports GET and HEAD (is required to support these methods). If so, the problem is Jetty, not cocoon. 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? [1] http://osdir.com/ml/users-tomcat.apache.org/2010-03/msg01410.html [2] http://marc.info/?l=tomcat-userm=127382305322732w=2 On 09/19/2010 05:42 PM, Andre Juffer wrote: Let me just add some additional information. I use Dojo 1.5 (www.dojotoolkit.org) on the client (browser). No dojo on the server. I've created a few blocks (one of them is called 'equipment' and another one is called 'webapp') according to the cocoon 2.2 documentation. No extra configuration was done. I do not use CForms at all. At some point, on the client (firefox) a form is processed that results in a HTTP PUT request. The request is assembled with dojo.xhrPut(), a Dojo function. With Firebug 1.5.4, I see that the following request is submitted (cut and pasted from the Firebug console): PUT http://localhost:/equipment Parameters (application/x-www-form-urlencoded) categoryTest descriptionTesting purposes manufacturerTester Ltd. nameTest ownerId3375104 taskTesting So far, so good. There is nothing special about this request. Jetty receives the request (jetty was started with mvn jetty:run from the webapp block). The sitemap in the equipment block contains: map:match pattern=* map:call function=equipmentHandler /map:match So, all requests are handled by the function 'equipmentHandler()' (for now at least). This function subsequently calls upon cocoon.request.getMethod() to find out what the HTTP request method is and proceeds accordingly. The cocoon.request.getMethod() always returns GET. I tested this with java.lang.System.out.println(cocoon.request.getMethod()). As a matter of fact, none of the parameters listed above ever reach the equipmentHandler() function. Each cocoon.request.getParameter(..) calls returns null. Could this be an encoding issue? I went through http://cocoon.apache.org/2.2/1366_1_1.html. Thanks for your help, André On 09/18/2010 08:52 PM, Andre Juffer wrote: Hi, I am building a RESTful application with cocoon 2.2. I need to be able to identify the request method. It appears that in the sitemap, {request:method}, or in flow, cocoon.request.getMethod(), the HTTP method value always is GET. I need to be able to distinguish between GET, PUT, OPTIONS, etc in order to handle the request accordingly. If the method value is always GET, then I won't be able to do so. I've tested this all with a tool called RESTClient from WizTools at http://rest-client.googlecode.com/. Could one of you (not) confirm my observation? What to do if indeed the request method is always set to GET? Thanks, -- Andre H. Juffer | Phone: +358-8-553 1161 Biocenter Oulu and | Fax: +358-8-553-1141 Department of Biochemistry | Email: andre.juf...@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-unsubscr...@cocoon.apache.org For additional commands, e-mail: users-h...@cocoon.apache.org
Re: RESTful applications
-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. 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* 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. 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. All Tomcat versions should behave this way, as the servlet specification has been (relatively) consistent across the versions covered by Tomcat implementations. Your first problem, though, was that request.getMethod was always returning GET even when the method should be PUT, right? 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? - -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-unsubscr...@cocoon.apache.org For additional commands, e-mail: users-h...@cocoon.apache.org
Re: RESTful applications
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 encodingUTF-8/encoding /map:serializer map:serializer name=xml mime-type=text/xml src=org.apache.cocoon.serialization.XMLSerializer encodingUTF-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
Re: RESTful applications
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Andre, On 9/20/2010 3:06 PM, Andre Juffer wrote: The source of my problem is therefore clear. Absolutely. 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. So, does that mean that you'd be more amenable to switching from PUT to POST, or are you interested in getting PUT to work in one way or another? Note that adding a Filter to make PUT work for you doesn't violate any standards at all: it implements behavior your application requires. The only thing you could say is that is does something /other/ than what the servlet specification requires. Also note that parsing PUT bodies does not violate the servlet spec: it's simply not required by it, and therefore Tomcat doesn't implement it. Based upon this thread and the others you've probably read, I've filed an enhancement request against Tomcat: https://issues.apache.org/bugzilla/show_bug.cgi?id=49964 Feel free to comment on this bug if you'd like. [The DefaultServlet has a] 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. Exactly: DefaultServlet was written to implement PUT as specified in the HTTP specification, and knows nothing about your REST stuff. 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. Good. We try to be helpful :) I use the sitemap that was generated during block creation with Maven, as documented on the cocoon website. [snip] 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 Hmm... I've never worked with functions as you have above, but I definitely use the request matcher. Here's what I have in one of my pipelines, and it definitely works when nested inside map:transform: map:parameter name=requestScheme value={request:scheme} / map:parameter name=requestServerName value={request:serverName} / map:parameter name=requestServerPort value={request:serverPort} / It's possible that whatever map:call does isn't a real request and is always modeled as a GET. Someone much more familiar with Cocoon will have to comment on this. The equipmentHandler() function is basically implemented as (stripped version) function equipmentHandler() { var request = cocoon.request; Is cocoon.request how you get information from Cocoon? If you can get the request from cocoon.request, then why do you need the method parameter to your function call? Why not just do cocoon.request.method or request.getMethod()? Something doesn't seem right, here, though I'll admit that I know absolutely nothing about how to use Javascript functions inside Cocoon. Just make sure you are using the right syntax to get your function parameter from the Cocoon pipeline, or that you are using the right syntax to grab the request method from the request. It's also possible that the implementation of map:call does something that makes everything look like GET, as I theorized above. 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. Tomcat certainly doesn't do such a thing, and I'd be surprised if Jetty does it. But, Cocoon might be doing it. - -chris -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.10 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkyXxk8ACgkQ9CaO5/Lv0PCoYACdFU3QSyAv7DIgru4agBY5kKbP TD8AnR98/mgxelI3Hzt2Jg4tVMYepebi =XBsh -END PGP SIGNATURE- - To unsubscribe, e-mail: users-unsubscr...@cocoon.apache.org For additional commands, e-mail: users-h...@cocoon.apache.org