users@grizzly.java.net

HTTPServlet InputStream/Reader return EOF for POST requests

From: Matthew Swift <matthew.swift_at_gmail.com>
Date: Sat, 25 Aug 2012 00:21:27 +0200

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"}'
* 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 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",
  "_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"}'
* 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 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 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 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"}=[]*


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