HTTPBuilder HTTP Post url encoded parameters and accept xml response? - grails

Hi there i am wondering how i can post a urlencoded string and read in an xml response using HTTPBuilder? I would like to use this inside a Grails application. The REST plugin is no option. I tried the examples given on http://groovy.codehaus.org/modules/http-builder/doc/post.html but this gives me no xml response to read in.

You can try something like this:
def httpBuilder = new HTTPBuilder("http://webite.url")
httpBuilder.request(Method.POST, URLENC){req->
headers.accept = "application/xml"
body = [ YOUR URL ENCODED POST]
response.success = {resp,xml->
//read xml response.
}
}

Related

Rest Assured - Send POST Request (Content-Type : multipart/form-data) with Static JSON Payload and Files to be uploaded

I want to send a POST Request where -
Content Type is "multipart / form-data".
In "Body" section, I have 2 params -> body - {static JSON Payload}, files - {any file, say .log file}
In Rest Assured Code, I am able to get the Static JSON Payload in String format with below code -
String jsonFilePath = "<<Path to JSON File>>/Test_new.json";
String response = given().log().all().header("X-AUTH-TOKEN",res).body(new String(Files.readAllBytes(Paths.get(jsonFilePath)))).
when().post("<<POST RESOURCE URL>>").
then().log().body().assertThat().statusCode(200).extract().response().asString();
When running this code, only with Static JSON Payload, I am getting "415" error code.
Questions -
How can we successfully make this kind of call in Rest Assured?
When I want to upload files as well with this call, how to do that?
You need to use multiPart() methods for uploading files, not body() method. For example:
File json = new File("src/test/resources/test_new.json");
File file = new File("src/test/resources/debug.log");
given().log().all()
.multiPart("files", file)
.multiPart("body", json, "application/json")
.post("your_url");

Proxying MultiPart form requests in Grails

I have a Grails controller that receives a DefaultMultipartHttpServletRequest like so:
def myController() {
DefaultMultipartHttpServletRequest proxyRequest = (DefaultMultipartHttpServletRequest) request
}
This controller acts as a proxy by taking pieces of this request and then resends the request to another destination.
For non-multipart requests, this worked fine, I did something like:
IProxyService service = (IProxyService) clientFactory.create()
Response response = service.doPOST(proxyRequest.getRequestBody())
Where proxyRequest.getRequestBody() contains a JSON block containing the request payload.
However, I do not know how to get this to work with multipart request payload, since the request body is no longer a simple block of JSON, but something like the following (taken from Chrome devtools):
How can I can pass this request payload through using my proxy service above, where doPost takes a String?
Have you tried
def parameterValue = request.getParameter("parameterName")
to get the parameter value?
If you see the method signatures for DefaultMultipartHttpServletRequest you will see there are methods for getting the files and other parameters separately because the request body is getting used to both upload the file and to pass in other parameters.

HttpRequest GET with sendData as query parameters?

This question is kind of a duplicate of HTTPRequest.request with sendData, can't seem to get this to work, but I've got some more information now. The goal here is to send a GET request with query parameters attached. I initially tried to send my request as such:
HttpRequest request = new HttpRequest();
request.open("GET", _url, async:true);
request.onError.listen(_onLoadError, onError: _onLoadError);
request.send(sendData);
Where sendData is a String following the normal format for query parameters (?myVariable=2&myOtherVariable=a, etc), since this is the ultimate goal here. The request gets sent, but I never see any additional data (sendData) go with it in any monitoring tools (I'm using Charles). I then tried:
HttpRequest request = new HttpRequest();
request.open("GET", _url + sendData, async:true);
request.onError.listen(_onLoadError, onError: _onLoadError);
request.send();
So now I'm just attaching the query string to the url itself. This works as intended, but is far from elegant. Is there a better solution?
On a GET request you always add the query string to the URL?
When you create the Uri you can pass in a map with the query parameters if you find this more elegant.
Map query = {'xx':'yy', 'zz' : 'ss'};
String url = "http://localhost:8080/myapp/signinService";
Uri uri = new Uri(path: url, queryParameters : query);
HttpRequest.getString(uri.toString().then((HttpRequest req) ...
According to the W3 XMLHttpRequest Specification:
(In the send() method) The argument is ignored if request method is GET or HEAD.
So simple answer to this question is no. sendData cannot be appended to a GET request, this is by XMLHttpRequest specification and not a limitation of Dart.
That said, for requests like this it may be more readable and idiomatic to use HttpRequest.getString
HttpRequest.getString(_url + sendData).then((HttpRequest req) {
// ... Code here
}).catchError(_onLoadError);
If you want to generate a valid URL from url (String) + query parameters (Map) , you can do the following :
Uri uri = Uri.parse(url).replace(queryParameters: parameters);
String finalURL = uri.toString();
url is a String and parameters is a Map

Send JSON data as post method from rails controller to a web service

I am trying to send some json data from my controller written in rails to a java webservice.
On form submission i take all the input fields data do some procession on it and convert it into json object using to_json.
But how can i send it to java webservice
http://localhost:8080/exim/jsonToMapService?jsonData={"key":"value"}
You can use net/http. (as #Pierre wrote, you should create a class in lib folder, and put there your function)
url = URI.parse(service_url)
headers = {"host" => URL }
req = Net::HTTP::Post.new(url.path)
req["Content-Type"] = "application/json"
req["Accept"] = "application/json"
req.body = JSON.generate(some_data)
con = Net::HTTP.new(url.host, url.port)
# ssl for https
if full_url.include?("https")
con.use_ssl = true
con.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
res = con.start {|http| http.request(req) }
To do things like this I suggest using either RestClient or Faraday. Howeve I strongly suggest not doing the HTTP call in your controller.
Using RestClient, it would look like this:
RestClient.get('http://localhost:8080/exim/jsonToMapService', { key: :value })
You should create a class to extract this logic in the lib folder for example.
As #eightbitraptor mentioned it, when performing HTTP request like above, you should avoid blocking by performing them in a background process like Delayed Job, Resque or Sideqik.

Convert Rails Net::HTTP request to MD5 Hex Digest

In order to use a third-party API, I need to encode the Net::HTTP::Post request as an MD5 hex digest, which is then used as part of the signature. However, when I try to simply Digest::MD5.hexdigest(req), it throws a "Cannot convert to string error", and when I explicitly req.to_s, it just gives the MD5 of #<Net::HTTP::Post:0x112a0eef8>
I'm simply:
request = Net::HTTP::Post.new(url.path)
request.body = {
"key" => "val"
}.to_json
# later...
hexDigest = Digest::MD5.hexdigest(request)
which is the documented spec, I think: "[with the] JSON body containing the new information."
This is the relevant sample Java code they supply:
ByteArrayOutputStream requestOutputStream = new ByteArrayOutputStream();
httpMethod.getEntity().writeTo(requestOutputStream);
DigestUtils.md5Hex(requestOutputStream.toByteArray()).toLowerCase();
Any ideas?
Thanks!
Try to call 'to_s' method explicitly, it should help:
hexDigest = Digest::MD5.hexdigest(request.to_s)
The equivalent ruby code for those lines is:
OpenSSL::Digest::MD5.hexdigest(request.body)
httpMethod.getEntity() will return the json defined as the request body.
requestOutputStream.toByteArray() will return the array of bytes corresponding to the request body.

Resources