Reputation: 4295
I'm trying to send a POST using Groovy HTTPBuilder but the data I want to send is already URL-encoded so I want HTTPBuilder to POST it as is. I tried the following:
def validationString = "cmd=_notify-validate&" + postData
def http = new HTTPBuilder(grailsApplication.config.grails.paypal.server)
http.request(Method.POST) {
uri.path = "/"
body = validationString
requestContentType = ContentType.TEXT
response.success = { response ->
println response.statusLine
}
}
But it gives me a NullPointerException:
java.lang.NullPointerException
at groovyx.net.http.HTTPBuilder$RequestConfigDelegate.setBody(HTTPBuilder.java:1200)
Upvotes: 3
Views: 7387
Reputation: 160191
Since you're using pre-encoded form values you cannot use the default map-based content type encoder. You must specify the content type so the EncoderRegistry
knows how to handle the body.
You may create the HttpBuilder with a content type that specifies the body is a URL-encoded string:
def http = new HTTPBuilder(url, ContentType.URLENC)
Or make the request passing the content type explicitly:
http.request(Method.POST, ContentType.URLENC) {
// etc.
For reference, here's how I figured it out--I didn't know before I read the question.
request
method's API docs to see what the closure was expected to contain. I've used HTTPBuilder
only in passing, so I wanted to see what, specifically, the body
"should" be, or "may" be, and if the two were different. RequestConfigDelegate
class and said the options were discussed in its docs.RequestConfigDelegate.setBody
method, which is what the body
setter is, states the body "[...] may be of any type supported by the associated request encoder. That is, the value of body
will be interpreted by the encoder associated with the current request content-type."EncoderRegistry
class. It has an encode_form
method taking a string and states it "assumes the String is an already-encoded POST string". Sounds good.HttpBuilder
inner class method, RequestConfigDelegate.getRequestContentType
, which in turn had a link to the ContentType
enum.URLENC
value that led me to believe it'd be the best first guess.HTTPBuilder
ctor taking a content type, and that worked.request
methods and noticed there's a version also taking a content type.I'd guess the total time was ~5-10 minutes, much shorter than it took to type up what I did. Hopefully it'll convince you, though, that finding this kind of stuff out is possible via the docs, in relatively short order.
IMO this is a critical skill for developers to groom, and make you look like a hero. And it can be fun.
Upvotes: 6