Sending POST with groovy and data is already URL-encoded
encoding, groovy, http
Solution
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.
- Looked at the `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.
- The four-arg version of the request method links to the `RequestConfigDelegate` class and said the options were discussed in its docs.
- The `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."
- The request encoder link is to the `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.
- The request content-type link was to an `HttpBuilder` inner class method, `RequestConfigDelegate.getRequestContentType`, which in turn had a link to the `ContentType` enum.
- That enum has a `URLENC` value that led me to believe it'd be the best first guess.
- I tried the `HTTPBuilder` ctor taking a content type, and that worked.
- Circled back to the `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.
Problem
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) ```