users@grizzly.java.net

Re: HTTPServlet InputStream/Reader return EOF for POST requests

From: Oleksiy Stashok <oleksiy.stashok_at_oracle.com>
Date: Sat, 25 Aug 2012 09:27:50 +0200

Hi Matt,

this might be related (from Servlet spec):

"When Parameters Are Available
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.
If the conditions are not met and the post form data is not included in
the parameter
set, the post data must still be available to the servlet via the
request object’s input
stream. If the conditions are met, post form data will no longer be
available for
reading directly from the request object’s input stream.
"

WBR,
Alexey.

On 08/25/2012 12:21 AM, Matthew Swift wrote:
> Hi there,
>
> Please accept my humble apologies if this is a dumb HTTP newbie
> mistake I am making.
>
> I have written a Servlet using Grizzly 2.2.14 and 2.3 which implements
> all basic HTTP methods. Unfortunately, I'm hitting a problem in my
> implementation of the POST method. I issue two requests: one PUT and
> one POST containing the same content, only differing slightly on the
> URL. Here's the PUT using curl with debugging enabled:
>
> $ curl -v --request PUT
> "http://localhost:18890/example/managed/users/1?_pretty-print=true&_debug=true"
> --data
> '{"userName":"charlie","employeeNumber":3141,"email":"charles_at_example.com
> <mailto:charles_at_example.com>"}'
> * About to connect() to localhost port 18890 (#0)
> * Trying 127.0.0.1... connected
> > PUT /example/managed/users/1?_pretty-print=true&_debug=true HTTP/1.1
> > User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0
> OpenSSL/1.0.1 zlib/1.2.3.4 <http://1.2.3.4> libidn/1.23 librtmp/2.3
> > Host: localhost:18890
> > Accept: */*
> > Content-Length: 74
> > Content-Type: application/x-www-form-urlencoded
> >
> * upload completely sent off: 74out of 74 bytes
> < HTTP/1.1 200 OK
> < Content-Type: application/json;charset=UTF-8
> < server: grizzly/2.3
> < ETag: "1"
> < Date: Fri, 24 Aug 2012 21:52:36 GMT
> < Transfer-Encoding: chunked
> <
> {
> "userName" : "charlie",
> "employeeNumber" : 3141,
> "email" : "charles_at_example.com <mailto:charles_at_example.com>",
> "_id" : "1",
> "_rev" : "1"
> * Connection #0 to host localhost left intact
> * Closing connection #0
>
>
> And here's the POST which differs only in the URL and the method:
>
> $ curl -v --request POST
> "http://localhost:18890/example/managed/users?_pretty-print=true&_debug=true"
> --data
> '{"userName":"charlie","employeeNumber":3141,"email":"charles_at_example.com
> <mailto:charles_at_example.com>"}'
> * About to connect() to localhost port 18890 (#0)
> * Trying 127.0.0.1... connected
> > POST /example/managed/users?_pretty-print=true&_debug=true HTTP/1.1
> > User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0
> OpenSSL/1.0.1 zlib/1.2.3.4 <http://1.2.3.4> libidn/1.23 librtmp/2.3
> > Host: localhost:18890
> > Accept: */*
> > Content-Length: 74
> > Content-Type: application/x-www-form-urlencoded
> >
> * upload completely sent off: 74out of 74 bytes
> < HTTP/1.1 500 java.io.EOFException: No content to map to Object
> due to end of input
> < server: grizzly/2.3
> < Date: Fri, 24 Aug 2012 21:55:46 GMT
> < Connection: close
> < Content-Length: 0
> <
> * Closing connection #0
>
>
> At the point where the POST fails both method implementations have
> done the exact same processing, however the POST implementation fails
> to read anything from the HTTP request's InputStream (it's already at
> EOF). I verified using Wireshark that curl is not doing anything
> sneaky for POST operations and it isn't. However, when I dump the HTTP
> request's headers from within the servlet, I see something strange in
> the POST parameters:
>
> Aug 25, 2012 12:15:25 AM
> org.glassfish.grizzly.servlet.WebappContext log
> *INFO: [example] Method=PUT*
> Header user-agent=curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0
> OpenSSL/1.0.1 zlib/1.2.3.4 <http://1.2.3.4> libidn/1.23 librtmp/2.3
> Header host=localhost:18890
> Header accept=*/*
> Header content-length=74
> Header content-type=application/x-www-form-urlencoded
> RequestURI=/example/managed/users/1
> ContextPath=/example
> ServletPath=/managed
> PathInfo=/users/1
> QueryString=_pretty-print=true&_debug=true
> Parameter _pretty-print=[true]
> Parameter _debug=[true]
>
>
> Aug 25, 2012 12:16:01 AM
> org.glassfish.grizzly.servlet.WebappContext log
> *INFO: [example] Method=POST*
> Header user-agent=curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0
> OpenSSL/1.0.1 zlib/1.2.3.4 <http://1.2.3.4> libidn/1.23 librtmp/2.3
> Header host=localhost:18890
> Header accept=*/*
> Header content-length=74
> Header content-type=application/x-www-form-urlencoded
> RequestURI=/example/managed/users
> ContextPath=/example
> ServletPath=/managed
> PathInfo=/users
> QueryString=_pretty-print=true&_debug=true
> Parameter _pretty-print=[true]
> Parameter _debug=[true]
> *Parameter
> {"userName":"charlie","employeeNumber":3141,"email":"charles_at_example.com
> <mailto:charles_at_example.com>"}=[]*
>
>
> If the request content has been parsed as a header then it's no wonder
> that the input stream is already at EOF when I want to read from it.
> Is this expected behavior?
>
> I've tried with Grizzly 2.2.x as well as the 2.3 SNAPSHOT and
> combinations of Servlet 2.5 and 3.0.1 but to no avail.
>
> Cheers,
>
> Matt
>