You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Kumar Kadiyala <ku...@yahoo.com> on 2010/03/25 17:53:57 UTC

tomcat PUT not working

Hi,

I have REST based web services some of which use the PUT method. The PUT method can contain a request body. The web service works fine with Websphere and is out in the field.

We are in the process of migrating to tomcat and I noticed that my web service which uses PUT is not able to get the request body anymore. I use HttpServletRequest's getInputStream and it always returns null. I did look at the forum topic "http://markmail.org/message/dxgvu6fhcvp22xbo" and I was wondering if there is a workaround I can use to get past this problem. Changing the method to POST will affect customers in the field and also breaks RESTful principles.

Thanks


      

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


Re: tomcat PUT not working

Posted by André Warnier <aw...@ice-sa.com>.
Michael,

Many thanks for your comments, clarifications and references.
I believe that these will help the Tomcat development team in their 
decision about implementing (or not) the getParameter family of methods 
on HTTP methods other than GET and POST.

I did indeed leave some aspects out of my own post (such as POST 
"parameters" encoded as multipart/form-data, the "path-info" etc.), in 
order to keep the general explanation more readable.
But even so, I appreciate your comments because they improve my own 
knowledge and will lead me to re-read these specs with hopefully a 
better level of understanding and precision.

 From the quality of your post, it sounds that you may be involved 
somehow in the HTTP RFC process. Is that a correct guess ?
If yes, would you mind if ask you a couple of additional HTTP-related 
questions, off-list ?


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


Re: tomcat PUT not working

Posted by Michael Wojcik <mw...@newsguy.com>.
Christopher Schultz wrote:
> On 3/28/2010 6:28 PM, Michael Wojcik wrote:
>> André Warnier wrote:
>>> For all these reasons, currently Tomcat does not support the
>>> getParameters() family of methods, when the request method is PUT.
>> This is a Tomcat limitation, not an HTTP one.
> 
> Again, Tomcat does not limit the developer in any way: Tomcat provides
> access to the "GET parameters" using the getParameter family of methods.
> It's just that Tomcat will not auto-parse any
> application/x-www-form-urlencoded request body and integrate the
> parameters into those coming from the URL.

Right. What I meant was that Tomcat's current getParameters method was
limited to extracting parameters from the query-string portion of the
Request-URI, and from an application/x-www-form-urlencoded
content-body for a POST request. In that sense it's a Tomcat
"limitation": the convenience method getParameters *could* parse an
x-www-form-urlencoded content-body supplied with a PUT request, but
doesn't.

But you're certainly correct that Tomcat doesn't prevent the
application from doing so. And given the meaning and presumed intent
of the PUT request, that's not really surprising. PUT doesn't imply
server-side application processing of the content-body the way POST does.

-- 
Michael Wojcik
Micro Focus
Rhetoric & Writing, Michigan State University


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


Re: tomcat PUT not working

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Michael,

On 3/28/2010 6:28 PM, Michael Wojcik wrote:
> André Warnier wrote:
>> For all these reasons, currently Tomcat does not support the
>> getParameters() family of methods, when the request method is PUT.
> 
> This is a Tomcat limitation, not an HTTP one. It's not a conformance
> issue, because RFC 2616 doesn't require the server do anything in
> particular with the query-string. But it does permit a query-string in
> a PUT Request-URI.

Again, Tomcat does not limit the developer in any way: Tomcat provides
access to the "GET parameters" using the getParameter family of methods.
It's just that Tomcat will not auto-parse any
application/x-www-form-urlencoded request body and integrate the
parameters into those coming from the URL.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkuw7pUACgkQ9CaO5/Lv0PBDgACgm8ilpdPDDW58O3ZcEVAf1XCd
F/IAn3MTE7o/IWA6wiq7V9BJttSyBK8y
=lgjh
-----END PGP SIGNATURE-----

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


Re: tomcat PUT not working

Posted by Michael Wojcik <mw...@newsguy.com>.
André Warnier wrote:
> 
> The area of contention here is whether a HTTP PUT request can or not
> have "parameters", and whether such parameters can or not be encoded as
> part of the HTTP body of a PUT request (or as part of the URL query
> string of the request).

As far as I can tell, this is a Tomcat issue, not an HTTP one.

Technically, HTTP requests do not have "parameters", regardless of the
HTTP method (GET, POST, etc). HTTP requests have a Request-URI, which
can have a query-string part; headers; and in some cases a
content-body (aka "entity"). The server and anything it delegates the
request to can make use of any of those in determining how to handle
the request. But RFC 2616 does not define request "parameters". That
is an informal concept, as far as HTTP is concerned.

Since the HTTP/1.1 specification (RFC 2616) lets a PUT request include
a query-string as part of its Request-URI (see below), if a
query-string can be treated as "parameters", then a PUT request can
have parameters. The same argument applies to the request headers and
content-body of a PUT request.

(Note that request headers are commonly used to convey metadata about
the content-body to server-side application code; but they're not
restricted to that purpose.)

> Basically (and roughly),
> - for a GET (which does not have a body), such request parameters are
> encoded as part of the request URL "query string" part

True, though it would be more accurate to say that since a GET request
cannot include a content-body, its only channels for notional
"parameters" are the query-string and the request headers.

> - for a POST request (which has a body), the parameters are encoded the
> same way, but are contained in the HTTP body of the request.

Any HTTP request method other than CONNECT, including a POST request,
can include a query-string in its Request-URI. See 2616 3.2, 5.1.2, and 9.

Also, the other parts of the Request-URI can be treated as application
parameters. See for example the definition of "path-info" in the
CGI/1.1 specification: the CGI program is identified by the part of
the abs_path that includes the actual name of an executable (as
defined by the server), but the abs_path can contain additional
components after that which are made available to the program
(possibly after transformation by the server) via the environment.

And the "parameters" in the content-body of a POST request do not need
to be URL-encoded. Some HTTP applications, such as HTML, do define
POST entities that are URL-encoded - notably HTML's use of
URL-encoding for form name/value pairs. But the POST request
content-body can be any stream of octets, and its interpretation is
left to whatever processes the request.

> For PUT requests however, there is no mention anywhere (in the
> applicable specs) of parameters.

2616 9.6 says that a PUT request includes a Request-URI. 5.1.2 says
that will be an absoluteURI or an abs_path. (A PUT request must refer
to a resource, so "*" is not allowed; and the fourth option, an
authority, is only allowed for the CONNECT request method.) And 3.2.2
includes the query string as part of an http_URL.

(RFC 2616 *is* somewhat sloppy in this regard, because 3.2.2
incorrectly separates abs_path and query, which suggests that eg a GET
request cannot be made using an abs_path with a query string - ie,
that it would have to be made using an absoluteURI in order to a query
string. There are various proposed fixes for this; see eg i58 in the
HTTP rfc2616bis issues list at [1].)

> In fact, the HTTP RFC definition of a PUT request seems to indicate that
> the body contains the "resource" that the client wants the server to
> store at the location corresponding to the indicated request URL.

Correct. The intention of the PUT request is to ask the origin server
to store an entity; the content-body contains the entity, and the
Request-URI names it.

> For all these reasons, currently Tomcat does not support the
> getParameters() family of methods, when the request method is PUT.

This is a Tomcat limitation, not an HTTP one. It's not a conformance
issue, because RFC 2616 doesn't require the server do anything in
particular with the query-string. But it does permit a query-string in
a PUT Request-URI.

> It is possible that other servlet engines support this, but in that case
> it has to be considered as an optional add-on, not as something that is
> required by the HTTP RFC nor the Servlet Spec.

Agreed.

> But the crux of the matter is, that if a (REST) web application would
> depend on that feature to be available in an HTTP server or a Servlet
> Engine, then that application is not portable, because the applicable
> specifications do not mention this as a mandatory feature of either of
> them.

Agreed. Of course, even if you limit yourself to conforming HTTP
servers, it can be difficult to be completely portable; HTTP/1.1
doesn't have all that many requirements. A conforming HTTP/1.1 server
only has to support GET and HEAD, for example (5.1.1).


[1] http://www.w3.org/Protocols/HTTP/1.1/rfc2616bis/issues/


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


Re: tomcat PUT not working

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

André,

On 3/28/2010 10:23 AM, André Warnier wrote:
> For GET and POST requests, both the HTTP RFC and the Servlet Spec
> provide some answers and describe how it is done.
> Basically (and roughly),
> - for a GET (which does not have a body), such request parameters are
> encoded as part of the request URL "query string" part
> - for a POST request (which has a body), the parameters are encoded the
> same way, but are contained in the HTTP body of the request.

... and, for completeness, POST requests may also have GET-style URL
parameters which are merged-together with those gathered from the POST
body so the servlet doesn't have to consult two different "places" for
parameter values.

> In fact, the HTTP RFC definition of a PUT request seems to indicate that
> the body contains the "resource" that the client wants the server to
> store at the location corresponding to the indicated request URL.

+1

> Reading the PUT request body yourself, and parsing it into parameters
> yourself, is on the other hand perfectly supported and should work
> anywhere.

Yup: also, you might be able to write a filter that changes the request
method from PUT to POST in order to trick Tomcat into parsing the
request body for you. That's an ugly hack, but at least you don't have
to go parsing your own request bodies to do that.

On the other hand, using PUT to pass parameters in the body doesn't
sound like it matches any well-known specification, recommendation, or
proposal.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkuwrxYACgkQ9CaO5/Lv0PA3ywCeMqOtAF0tQKqJTDYUhaspz+iJ
gToAnROaNvDj1NFDRCoBby0VqP52gPqd
=GB6v
-----END PGP SIGNATURE-----

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


Re: tomcat PUT not working

Posted by André Warnier <aw...@ice-sa.com>.
Kumar Kadiyala wrote:
> Chris,
> 
> I see the content when I read the InputStream. Thanks for your help. 
> 
Hi.
It seems that you are helped, and that is the essential part.
Maybe to balance a bit with the subject of your post ("Tomcat PUT not 
working"), I just want to provide some additional information here, as 
to why what is happening is happening, and maybe stress that this is not 
a case of "PUT not working". It is working as it should; it just happens 
that it is not maybe how you expected it to work.

Much of what follows is already included in the thread which you 
mentioned earlier, but that thread was a bit "stressed" at times due to 
the vocabulary and tone of the original poster, so here is a summary :

Tomcat is at the same time a Servlet Engine and a HTTP server.
For Servlet Engines, the official reference is the Java Servlet 
Specification.  For the HTTP protocol, the official reference is 
RFC2616.  Tomcat tries to respect both of these specifications when 
applicable.

REST is not an Internet protocol. It is an application layer, built on 
top of HTTP (or on top of another protocol).
Tomcat is a not a REST server, and does not pretend to be.
You can build a REST application on top of Tomcat, but it is the job of 
that REST application then, to handle the aspects that are specific to 
REST and are not part of the HTTP protocol or of the Servlet Spec.

The area of contention here is whether a HTTP PUT request can or not 
have "parameters", and whether such parameters can or not be encoded as 
part of the HTTP body of a PUT request (or as part of the URL query 
string of the request).

For GET and POST requests, both the HTTP RFC and the Servlet Spec 
provide some answers and describe how it is done.
Basically (and roughly),
- for a GET (which does not have a body), such request parameters are 
encoded as part of the request URL "query string" part
- for a POST request (which has a body), the parameters are encoded the 
same way, but are contained in the HTTP body of the request.

In both cases, Tomcat allows an application to retrieve these parameters 
via calls like HttpServletRequest.getParameters().  These calls 
automatically decode and parse the request parameters and return them to 
the application in a neatly usable format.
For a POST request, you are also free to read the request body yourself, 
and then parse the parameters yourself.

For PUT requests however, there is no mention anywhere (in the 
applicable specs) of parameters.
In fact, the HTTP RFC definition of a PUT request seems to indicate that 
the body contains the "resource" that the client wants the server to 
store at the location corresponding to the indicated request URL.
The best example of that is probably the DAV application (available as 
an add-on application under both Tomcat and Apache httpd), which allows 
a client to "upload" files to the server at a specific location, so that 
these files can then later be retrieved (via for example a GET request) 
using the same URL as the one used for the upload.
(So basically, it is not that parameters are forbidden for a PUT; it is 
just that they are not mentioned).


For all these reasons, currently Tomcat does not support the 
getParameters() family of methods, when the request method is PUT.

It is possible that other servlet engines support this, but in that case 
it has to be considered as an optional add-on, not as something that is 
required by the HTTP RFC nor the Servlet Spec.

I believe that because of that previous thread, a "request for 
enhancement" was filed to ask the Tomcat developers to provide such 
support in the future, but I don't know the status of it.

But the crux of the matter is, that if a (REST) web application would 
depend on that feature to be available in an HTTP server or a Servlet 
Engine, then that application is not portable, because the applicable 
specifications do not mention this as a mandatory feature of either of them.

Reading the PUT request body yourself, and parsing it into parameters 
yourself, is on the other hand perfectly supported and should work anywhere.



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


Re: tomcat PUT not working

Posted by Kumar Kadiyala <ku...@yahoo.com>.
Chris,

I see the content when I read the InputStream. Thanks for your help. 

Kumar

--- On Fri, 3/26/10, Christopher Schultz <ch...@christopherschultz.net> wrote:

> From: Christopher Schultz <ch...@christopherschultz.net>
> Subject: Re: tomcat PUT not working
> To: "Tomcat Users List" <us...@tomcat.apache.org>
> Date: Friday, March 26, 2010, 10:33 AM
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Kumar,
> 
> On 3/25/2010 4:34 PM, Kumar Kadiyala wrote:
> > I have REST based web services some of which use the
> PUT method. The 
> > PUT method can contain a request body. The web service
> works fine 
> > with Websphere and is out in the field.
> > 
> > We are in the process of migrating to tomcat and I
> noticed that my 
> > web service which uses PUT is not able to get the
> request body 
> > anymore. I use HttpServletRequest's getInputStream and
> it always 
> > returns null.
> 
> No exception, but you get NULL instead? Strange.
> 
> > What is the Content-Type of the request?
> > KK >> The Content-Type is text/xml.
> 
> If the Content-Type is text/xml, you should probably be
> using
> HttpServletRequest.getReader, but maybe not if you want the
> raw bytes to
> provide to an XML parser.
> 
> > Changing the method to POST will affect customers in
> the field and
> > also breaks RESTful principles.
> 
> I am not suggesting that you switch to POST.
> 
> > Yes, It does seem like the request body is empty.
> 
> Empty request body != null. Which is it? Can you verify
> with a packet
> sniffer that the request body is actually non-null? What's
> the
> Content-Length?
> 
> > I misspoke earlier. The InputStream is not null but
> the method
> > available() on the InputStream is returning 0. If I
> change the method
> > to POST, InputStream's avialable() is returning a
> value > 0.
> 
> InputStream.available returns the number of bytes readable
> without
> blocking, not how many bytes can eventually be read by the
> caller.
> 
> Try actually reading from the InputStream and see what
> happens.
> 
> - -chris
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (MingW32)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
> 
> iEYEARECAAYFAkus4e0ACgkQ9CaO5/Lv0PDDAACffWKdhyFzbDmY3KNi4+8s+Wjy
> WGIAoIuW5Lo6MK0qEkqHeYVOUhM7oWNo
> =TpUQ
> -----END PGP SIGNATURE-----
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 
> 


      

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


Re: tomcat PUT not working

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Kumar,

On 3/25/2010 4:34 PM, Kumar Kadiyala wrote:
> I have REST based web services some of which use the PUT method. The 
> PUT method can contain a request body. The web service works fine 
> with Websphere and is out in the field.
> 
> We are in the process of migrating to tomcat and I noticed that my 
> web service which uses PUT is not able to get the request body 
> anymore. I use HttpServletRequest's getInputStream and it always 
> returns null.

No exception, but you get NULL instead? Strange.

> What is the Content-Type of the request?
> KK >> The Content-Type is text/xml.

If the Content-Type is text/xml, you should probably be using
HttpServletRequest.getReader, but maybe not if you want the raw bytes to
provide to an XML parser.

> Changing the method to POST will affect customers in the field and
> also breaks RESTful principles.

I am not suggesting that you switch to POST.

> Yes, It does seem like the request body is empty.

Empty request body != null. Which is it? Can you verify with a packet
sniffer that the request body is actually non-null? What's the
Content-Length?

> I misspoke earlier. The InputStream is not null but the method
> available() on the InputStream is returning 0. If I change the method
> to POST, InputStream's avialable() is returning a value > 0.

InputStream.available returns the number of bytes readable without
blocking, not how many bytes can eventually be read by the caller.

Try actually reading from the InputStream and see what happens.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkus4e0ACgkQ9CaO5/Lv0PDDAACffWKdhyFzbDmY3KNi4+8s+Wjy
WGIAoIuW5Lo6MK0qEkqHeYVOUhM7oWNo
=TpUQ
-----END PGP SIGNATURE-----

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


Re: tomcat PUT not working

Posted by Kumar Kadiyala <ku...@yahoo.com>.
Hi Chris,

On 3/25/2010 12:53 PM, Kumar Kadiyala wrote:
I have REST based web services some of which use the PUT method. The 
PUT method can contain a request body. The web service works fine 
with Websphere and is out in the field.

We are in the process of migrating to tomcat and I noticed that my 
web service which uses PUT is not able to get the request body 
anymore. I use HttpServletRequest's getInputStream and it always 
returns null.

What is the Content-Type of the request?
KK >> The Content-Type is text/xml.

Changing the method to POST will affect customers in the field and
also breaks RESTful principles.

You shouldn't have to switch to POST. In fact, the problem in your
reference message was that the OP wanted to use POST-style semantics,
that is, use a application/x-www-form-urlencoded body in a PUT, which is
not really appropriate.

Are you saying that you are using PUT and don't have access to your
request body? That definitely should not be happening, unless some other
component is consuming the request body.

KK >> Yes, It does seem like the request body is empty.

Is the InputStream null, or does it just not appear to contain any data?

KK >> I misspoke earlier. The InputStream is not null but the method available() on the InputStream is returning 0. If I change the method to POST, InputStream's avialable() is returning a value > 0.






      

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


Re: tomcat PUT not working

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Kumar,

On 3/25/2010 12:53 PM, Kumar Kadiyala wrote:
> I have REST based web services some of which use the PUT method. The 
> PUT method can contain a request body. The web service works fine 
> with Websphere and is out in the field.
> 
> We are in the process of migrating to tomcat and I noticed that my 
> web service which uses PUT is not able to get the request body 
> anymore. I use HttpServletRequest's getInputStream and it always 
> returns null.

What is the Content-Type of the request?

> Changing the method to POST will affect customers in the field and
> also breaks RESTful principles.

You shouldn't have to switch to POST. In fact, the problem in your
reference message was that the OP wanted to use POST-style semantics,
that is, use a application/x-www-form-urlencoded body in a PUT, which is
not really appropriate.

Are you saying that you are using PUT and don't have access to your
request body? That definitely should not be happening, unless some other
component is consuming the request body.

Is the InputStream null, or does it just not appear to contain any data?

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkuru3AACgkQ9CaO5/Lv0PA1XQCgoicJ8PcmaxCTOuEb8FN3m/I5
qLgAni3INqZJCxNDFOpSMBK0zWsevclX
=X+Cv
-----END PGP SIGNATURE-----

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


Re: tomcat PUT not working

Posted by Konstantin Kolinko <kn...@gmail.com>.
2010/3/25 Kumar Kadiyala <ku...@yahoo.com>:
>
> We are in the process of migrating to tomcat and I noticed that my web service which uses PUT is not able to get the request body anymore. I use HttpServletRequest's getInputStream and it always returns null.

It should be something in your application.

Note, that e.g. Tomcat Manager application
(o.a.catalina.manager.ManagerServlet) uses PUT for some requests (e.g.
when called from Ant tasks). So it definitely does work.



Best regards,
Konstantin Kolinko

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