How to parse RequestBody in Play Framework (Java) - java

I need to parse the RequestBody of a POST, currently I am doing the following:
public static Result createMessages(){
RequestBody body = request().body();
return ok("Got body: " + body);
}
This results in the following being returned to the browser:
Got body: DefaultRequestBody(None,None,None,None,None,Some(MultipartFormData(Map(from -> List(Hello), message -> List(World), subject -> List(Test)),List(),List(),List())),false)
I need to get the MultipartFormData from this output as you can see it has the posted values, but unsure how to do this in Java Play

Handling multipart forms is nice documented at Play's docs
For other form fields you can easily use ie. DynamicForm

Related

Request body is being printed out in the console but not the response

I am trying to build a Rest API automation based on Java, RestAssured, and Cucumber. I ' trying to hit an endpoint via POST. The problem is when I am converting the response as string and when I print the response, it is printing the XML file contents but not the response. I also see the status code as 200. I'm not sure what is going wrong in here. Below is the sample snippet from my codebase.
I am trying to hit a WebService (SOAP WSDL).
// required imports
public class Service_Steps {
Response xmlResponse;
#When("I create a POST request for RCP for endpoint using XML")
public void i_create_a_post_request_for_endpoint_using_xml() {
// xml Request body
String path = "pah_to_xml_file";
File file = new File(path);
xmlResponse = RestAssured.given().when().relaxedHTTPSValidation().accept(ContentType.XML).header(<headers>)
.body(file)
.post(url);
String xmlResponseAsString = xmlResponse.then().extract().body().asString();
}
Not sure why I am seeing this ambiguity. Sometimes it is printing the response, and sometimes it is printing the XML file (request body) contents.
After checking with developers I came to know that the SOAP EndPoint is sending out the responses in two different ways, randomly!
Try this one:
xmlResponse = RestAssured.given().log().all().when().relaxedHTTPSValidation().accept(ContentType.XML).header(<headers>)
.body(file)
.post(url)
.then()
.log().all()
.extract()
.response();
This will print out all the request & response stuff

Java littleproxy mitm: getting response body

I am trying to use littleproxy-mitm to inspect traffic. I have access to the headers and can easily read them. However, I cant find the body of a response consitently. To see if I can get the body I am using this testing my app by visiting https://www.google.com/humans.txt, but the wanted body is no where to be found. But when I visit other sites like google, facebook and twitter I seem to get gibberish(encoded body gzip most prob) and sometimes html.
Here is the filter:
#Override
public HttpObject serverToProxyResponse(HttpObject httpObject) {
if(httpObject instanceof FullHttpResponse){
System.out.println("FullHttpResponse ----------------------------------------");
FullHttpResponse response = (FullHttpResponse) httpObject;
CompositeByteBuf contentBuf = (CompositeByteBuf) response.content();
String contentStr = contentBuf.toString(CharsetUtil.UTF_8);
System.out.println(contentStr);
}
return httpObject;
}
Any idea why I am unable to get body from https://www.google.com/humans.txt ?
To answer my own question.
This code snippet works and will print the whole response. But the reason I was not getting the body response is either the header "Modified-since.." or the "Cache-control: public".

Rest assured, how to extract generated token from response body after POST request and set it to header

Performing any request, I need to perform Authentication with POST request with body {username:"somename", password:"somepass"},
header Content-Type:application.json which gives me a response with generated token, which I need to paste as a second header, smth like Authorization:generated-tokenkjhsdkjfvjbwjbQ== for further requests.
Could you help me with it, please.
Variant which worked for me:
String token = given()
.contentType("application/json")
.body(new User("someuser" , "123"))
.when()
.post(RestConfig.baseUrl+"/authentication-url")
.then().extract().response().as(TokenResponse.class).getToken();
given()
.contentType("application/json")
.header("Authorization", token)
.get(RestConfig.baseUrl+"/some-path")
.then()
.statusCode(200)...
I had a similar requirement, where I had to pass the auth token back and forth, but this was spring rest template not rest assured. For that purpose, I used client filter, which captured the token on response and set it as a header on request. You can search if there is something similar in rest assured, which can do the job.
Here is a sample, https://github.com/rest-assured/rest-assured/wiki/Usage
Custom Authentication
Rest Assured allows you to create custom authentication providers. You do this by implementing the io.restassured.spi.AuthFilter interface (preferably) and apply it as a filter. For example let's say that your security consists of adding together two headers together in a new header called "AUTH" (this is of course not secure). Then you can do that like this (Java 8 syntax):
given().
filter((requestSpec, responseSpec, ctx) -> {
String header1 = requestSpec.getHeaders().getValue("header1");
String header2 = requestSpec.getHeaders().getValue("header2");
requestSpec.header("AUTH", header1 + header2);
return ctx.next(requestSpec, responseSpec);
}).
when().
get("/customAuth").
then().
statusCode(200);
The reason why you want to use a AuthFilter and not Filter is that AuthFilters are automatically removed when doing given().auth().none(). ...
I could be misunderstanding the question, but from what I am getting from it, I think something like this should work:
String token =
given().
header("Content-Type", "application/json").
body(/* body content goes here */).
when().
post(/* route goes here */).
then().
extract().path("token").toString()
// the above path arg depends on the response you get from the call.
Then the next call would be something like:
given().
header("Content-Type", "application/json").
header("Authorization", token).
when()...etc.
Some of the specifics will depend on the API, but I use this format all the time. Often getting a response of a user ID, or a token, etc. and using it for future calls.
More info on extracting in the rest assured docs: https://github.com/rest-assured/rest-assured/wiki/Usage#extracting-values-from-the-response-after-validation
If you want to extract one parameter from response then this should work:
String jsonBody= ( enter request payload here )
ValidatableResponse response = RestAssured.given().baseUri(baseURL)
.accept("application/json")
.header("Content-Type","application/json")
.body(jsonBody).when().post("/auth")
.then().assertThat().statusCode(200)
.log().all();
String token=response.extract().path("token");

POST request fails (rest-assured test)

I have problem with making POST request with rest-assured.
This code works:
given().contentType(ContentType.JSON).body("{\"key\": \"val\"}").
when().post(url + resource).then().assertThat().statusCode(200).body("otherVal", equalTo(otherVal));
But I was trying to use param() or parameter() methods like that:
This one gives:
given().parameter("key", "val").
when().post(url + resource).then().assertThat().statusCode(200);
Expected status code <200> doesn't match actual status code <415>.
This:
given().parameter("key", "val").
when().post(url + resource).then().assertThat().body("otherVal", equalTo(otherVal));
java.lang.IllegalStateException: Expected response body to be verified as JSON, HTML or XML but no content-type was defined in the response.
Try registering a default parser using:
RestAssured.defaultParser(<parser type>);
And This:
RestAssured.defaultParser = Parser.JSON;
given().parameter("key", "val").
when().post(url + resource).then().assertThat().body("otherVal", equalTo(otherVal));
java.lang.IllegalArgumentException: The JSON input text should neither be null nor empty
I have run out of ideas whats wrong.
What I'm trying to do is to avoid writing full jsons for all test, it will be faster if I could skip all "" and {}.
Is my approach correct?
Let's look at your first example:
given().contentType(ContentType.JSON).body("{\"key\": \"val\"}").
when().post(url + resource).then().assertThat().statusCode(200).body("otherVal", equalTo(otherVal));
What happens here is that you put { "key" : "val" } (as text) into the body of the request. This text happens to be JSON. From REST Assured's perspective you might as well could have put { "key" : "val" which is not valid JSON. Your server responds correctly since the server requires and understands JSON. It understands that the body should be JSON since you passing JSON as content-type.
So let's look at your second example:
given().parameter("key", "val").
when().post(url + resource).then().assertThat().statusCode(200);
Here your service returns 415 because you're missing the JSON content-type. What happens when you use param or parameter with POST is that you create form parameters. Form parameters are also sent in the request body BUT form parameters are not JSON! Specifying "key" and "val" as form parameter like you do will be the same as this:
given().contentType("x-www-form-urlencoded").body("key=val").when().url + resource).then().assertThat().statusCode(200);
So in your second example there's actually two problems:
You're not sending JSON
You have the wrong content-type
And because of (2) you get 415 from the server
Moving on to your third example:
given().parameter("key", "val").
when().post(url + resource).then().assertThat().body("otherVal", equalTo(otherVal));
What (probably) happens here is that your server doesn't contain a response body because it expects the request to include "application/json" as content-type. So there is no body to assert (the request is wrong)! The response only contains the 415 status (line) as a header.
Which leads us to your last example:
RestAssured.defaultParser = Parser.JSON;
given().parameter("key", "val").
when().post(url + resource).then().assertThat().body("otherVal", equalTo(otherVal));
Here you instruct REST Assured to treat a missing content-type as JSON but the problem (again) is that your server doesn't return any response body at all so this won't help.
Solution:
You should put a supported JSON object-mapping framework (Jackson, Faster Jackson, Simple JSON or Gson) in your classpath (for example jackson-databind) and just create a map as described in the documentation:
Map<String, Object> jsonAsMap = new HashMap<>();
map.put("key", "val");
given().
contentType(ContentType.JSON).
body(jsonAsMap).
when().
post(url + resource).
then().
statusCode(200).
body("otherVal", equalTo(otherVal));
Since creating maps in Java is quite verbose I usually do something like this if I have nested maps:
given().
contentType(ContentType.JSON).
body(new HashMap<String,Object>() {{
put("key1, "val1");
put("key2, "val2");
put("key3", asList("val3", "val4"));
put("nested", new HashMap<String,String>() {{
put("key4", "val4");
put("key5", "val5");
}});
}}).
when().
post(url + resource).
then().
statusCode(200).
body("otherVal", equalTo(otherVal));
Or you create a DTO representation of your data and just pass an object to REST Assured:
MyDTO myDTO = new MyDTO(...);
given().
contentType(ContentType.JSON).
body(myDTO).
when().
post(url + resource).
then().
statusCode(200).
body("otherVal", equalTo(otherVal));
You can read more in the object-mapping documentation.
I was looking for answer and I figured it out too ..
add a file to your src/test/resouces folder and add this code to your test . Should be all good
URL file = Resources.getResource("ModyNewFieldsReq.json");
String myRequest = Resources.toString(file,Charsets.UTF_8);
Response fieldResponse = given ()
.header("Authorization", AuthrztionValue)
.header("X-App-Client-Id", XappClintIDvalue)
.contentType("application/vnd.api+json")
.body(myRequest).with()
.when()
.post(dataPostUrl)
.then()
.assertThat()
.log().ifError()
.statusCode(200)
.extract().response();
Assert.assertFalse(fieldResponse.asString().contains("isError"));

Process Post response in Play Framework

I'm at a loss for how to process results from a post in play framework. The following code works to process a GET response:
WSRequestHolder request = WS.url(myURL);
return async(
request.get().map(
new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
String json = response.getBody();
System.out.println("Json response: " + json);
//Do stuff
return ok(json);
}
}
)
);
I thought I'd just be able to replace .get() with post(myvalue). However, this does not work. What is the proper way to process a POST response in Play Framework?
WSRequestHolder.post(...) accepts 4 different types as a parameter: java.io.File, java.io.InputStream, JsonNode and String. You can replace .get() with .post(myvalue), depending on what myvalue is and what Content-Type myURL is expecting.
POSTing with those types will set the Content-Type header appropriate to the type. Passing a JsonNode will automatically set the Content-Type to application/json, for example. However, when passing a String you will likely have to set the Content-Type yourself, as Play isn't going to know whether that String is supposed to be JSON or a form.
From the Play Documentation:
If you're sending a form:
request.setContentType("application/x-www-form-urlencoded").post("key1=value1&key2=value2") ...
Or posting JSON as a String:
request.setContentType("application/json").post(jsonString) ...
If you're having other compile errors, please post them.

Categories

Resources