How to get complete request body of a POST request?

3,749 views
Skip to first unread message

NikK

unread,
Jan 21, 2011, 10:41:25 AM1/21/11
to Gaelyk
Hi,
I'm struggling to get hold of the complete request body as a single
string in my groovlet. The request body is supposed to contain a JSON-
string like:

{"aField":"A value","AnotherField":123247}

I have tried to user the method described in this blog post:
http://ice09.wordpress.com/2010/02/01/resting-with-json-in-gaelyk/


def requestComplete = new StringBuilder();
while ((line = request.getReader().readLine()) != null) {
requestComplete.append(line);
}


Sending a post request to the groovlet with the code above will
however produce the following error:
Error: GroovyServlet Error: script: '/WEB-INF/groovy/
sparaPlats.groovy': Script processing
failed.STREAMEDorg.mortbay.jetty.Request.getReader(Request.java:935)

Is there another way to get hold of the request body as a single
string? I'm using the latest version of gaelyk template project
(0.6.1)

Thanks in advance,
Niklas

Benjamin Muschko

unread,
Jan 21, 2011, 4:53:44 PM1/21/11
to Gaelyk
Hi Niklas,

Instead of trying to read the request body you could simply set your
JSON in a request parameter. Reading the value would be as simply as
this in your Groovlet:

def jsonString = params.<jsonParamName>

There's a JSON plugin available for Gaelyk that makes it easy for you
to parse the value and map it to an object for example. Check out the
examples: http://bit.ly/cf0Cir.

Hope this helps,

Ben

Niklas Konstenius

unread,
Jan 24, 2011, 1:56:47 AM1/24/11
to gae...@googlegroups.com
Thanks for your answer Ben,
Unfortunately I can't change the request schema to assigning the json to a request parameter as you suggest as this will break existing clients.

I have managed to get my code to work though. I turned out that I accidently posted a request to the page with incorrect content-type header: "application/x-www-form-urlencoded". This should of course be "application/json". 

Changing content type in the request magically solved the problem. I'm not sure why though.

Btw, I'll check out the plugin you linked to. Thanks.

/niklas 

--
You've received this message because you've subscribed to the Gaelyk Google Group.
To send an email to the group, please write to: gae...@googlegroups.com
To unsuscribe from this group: gaelyk+un...@googlegroups.com
To show more options: http://groups.google.fr/group/gaelyk?hl=en

Guillaume Laforge

unread,
Jan 27, 2011, 5:15:53 AM1/27/11
to gae...@googlegroups.com
Hi Niklas,

Have you tried also something simpler like:

def jsonPayload = request.reader.text

Guillaume

> --
> You've received this message because you've subscribed to the Gaelyk Google Group.
> To send an email to the group, please write to: gae...@googlegroups.com
> To unsuscribe from this group: gaelyk+un...@googlegroups.com
> To show more options: http://groups.google.fr/group/gaelyk?hl=en
>

--
Guillaume Laforge
Groovy Project Manager
Head of Groovy Development at SpringSource
http://www.springsource.com/g2one

Guillaume Laforge

unread,
Jan 27, 2011, 5:52:17 AM1/27/11
to gae...@googlegroups.com
Just tried locally with a groovlet containing:

out << request.reader.text

And I also got the error message:

GroovyServlet Error: script: '/receivejson.groovy': Script
processing failed.STREAMEDorg.mortbay.jetty.Request.getReader(Request.java:935)

Hmmm....

Guillaume

Guillaume Laforge

unread,
Jan 27, 2011, 5:56:02 AM1/27/11
to gae...@googlegroups.com
Same error in production as well.

Guillaume Laforge

unread,
Jan 27, 2011, 6:07:24 AM1/27/11
to gae...@googlegroups.com
Have you found anything new on the topic?
Nothing obvious jumps to mind so far for me.

Guillaume

Guillaume Laforge

unread,
Jan 27, 2011, 6:18:23 AM1/27/11
to gae...@googlegroups.com
Okay, actually, I just found something...

I was not properly "posting" my json payload to my groovlet.

Whether it's behind a URL route or not, doesn't matter, in both cases
I managed to make things work, without getting that ugly exception.

Soooo without further ado.

In my groovlet, I have that content:

def content = request.reader.text
System.out.println "Content: $content"

That way, I can see in the console the content I receive.
You can also use request.inputStream.text, and it works, but because
of possible encoding issues, it's better to use the reader instead, as
it should try its best to use the proper encoding.

Then, from the command-line, with curl, I do:

curl -v -H "Content-Type: application/json" -X POST -d
'{"screencast":{"subject":"tools"}}'
http://localhost:8080/receivejson.groovy

And I properly receive the content, and it's printed on the console,
so all's working fine.

I think it all depends on how you send your payload to the groovlet.
I'm not a curl expert, but I found some help on StackOverflow, with
one of the various options folks had submitted:
http://stackoverflow.com/questions/813487/how-to-post-json-to-php-with-curl

Guillaume

Guillaume Laforge

unread,
Jan 27, 2011, 6:20:44 AM1/27/11
to gae...@googlegroups.com
And I've also tested this in production, and it's working properly there too.

Hope this helps.

Guillaume

Niklas Konstenius

unread,
Jan 27, 2011, 7:42:40 AM1/27/11
to gae...@googlegroups.com
Thanks for your help Guillaume,
as I wrote in an earlier mail I also found out that I have to post the content with the correct content-type header, namely "application/json" instead of the default "application/x-www-form-urlencoded".
I guess something else is consuming the data from the input stream when content-type exuals "application/x-www-form-urlencoded"?


Thanks for the tip of how to get the content:

def content = request.reader.text

That will make my code much more groovy.. :.-)

/niklas

Guillaume Laforge

unread,
Jan 27, 2011, 8:11:40 AM1/27/11
to gae...@googlegroups.com
On Thu, Jan 27, 2011 at 13:42, Niklas Konstenius
<niklas.k...@gmail.com> wrote:
> Thanks for your help Guillaume,
> as I wrote in an earlier mail I also found out that I have to post the
> content with the correct content-type header, namely "application/json"
> instead of the default "application/x-www-form-urlencoded".
> I guess something else is consuming the data from the input stream when
> content-type exuals "application/x-www-form-urlencoded"?

I suspect (but not sure 100%) that it's the blobstore filter that does
this, as uploaded files for the blobstore are submitted through forms.
So it certainly calls the getInputStream() to see if there's an
uploaded file, and the magic key expected by the filter (when we
create an upload url).
And then, when you call the reader on the request, too bad, the input
stream had already been acquired, so you can't open the reader
afterwards, and you get that very unhelpful error from Jetty.

> Thanks for the tip of how to get the content:
> def content = request.reader.text
> That will make my code much more groovy.. :.-)

Yeah, I like to teach some cool shortcuts, that makes the code much
more readable and more maintainable in the long run!

Guillaume

Reply all
Reply to author
Forward
0 new messages