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.
Related
There are some other longer solutions I found, but I was wondering if the following works as well:
I have HttpExchange message, that is a POST request that is passed in, and write String jsonPayload = new String(message.getRequestBody().readAllBytes());. Would this turn the request body's json to a string?
I am consuming a legacy rest service that receives xml text in the body but is sent as json as shown in the following image
Postman source request
I have done the process to transform the previous request to a request that receives a JSON in normal format
New JSON request
And then I transform it into the format that asks me for the source request, my problem is that I do not know how to send my string request because I get the following error when I try to send it
Request error new http request
I get the same error when I sent in my source request in plain text format
Plain text error legacy http request
however in code I already transformed this text into JSON format but probably incorrectly,in the following sample code the http entity is the xml string object required by the legacy service
#Value("${client.medExpInsuranceQuotation.uri}")
private String clientUri;
#Autowired
#Qualifier("restTemplategetPolicyWs")
private RestTemplate restTemplate;
#Override
public Object callMedicalExpenseInsuranceQuotation(MedicalExpenseInsuranceQuotationRequestClient requestClient) {
Gson gson = new Gson();
Object json = gson.toJson(requestClient.getXml(), String.class);
System.out.println("Object: "+json);
HttpEntity<Object> entity = new HttpEntity<>(json);
log.info(requestClient.getXml());
ResponseEntity<ResponseBean<Object>> responseEntity = restTemplate.exchange(clientUri, HttpMethod.POST, entity, new ParameterizedTypeReference<ResponseBean<Object>>() {
});
return responseEntity.getBody().getPayload();
}
Notes:
The legacy service only receives the body in the format indicated in image 1 (Postman source request)
if I try to send the body in traditional json format with an attribute identifier
attemp send normal json format
I get the following error without information
{
"Message": "An error has occurred."
}
I hope you can help me greetings
That rest service is consuming json format. Note the double quotes at the start and the end of the payload - this makes it json string. Not json object, or json array, but json string. You need to transform the xml payload into json string and send the correct content type header - application/json.
Edit: To get json string first you need the xml as a string(it's already a string, i know that sounds strange, but can't explain it better). Then you call toJson() on that xml. Something similar to this:
String xml = "<xml><tag></tag></xml>";
String jsonString = gson.toJson(xml);
System.out.println(jsonString);
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".
Am new to API testing. I wanted to validated the response body of the GET method. But it is returning the io.restassured.internal.RestAssuredResponseImpl#35adf623 with the below code. Please let me know how can I resolve this. With POST Method, it works fine. Failing with GET method provided am passing all other values correct.
public static Response getResponseWithGetMethod() throws Exception {
Response response = RequestInvoker.invokeGET();
return response;
}
Output :
io.restassured.internal.RestAssuredResponseImpl#35adf623
Expected output is :
{
"path1": true,
"path2": true,
"path3": true
}
Use the body() method to get access to the body of the response.
Response object has multiple fields in it like, body, headers, status code, cookies etc.,
Check out the complete java doc here.
Answer to your code is to call getResponseWithGetMethod().body() or getResponseWithGetMethod().asString(); later one might be appropriate for you.
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"));