How to pass response body field to other request's body (Gatling) - scala

I have two end point.
-/authenticate
-/authenticate/verification
/authenticate return guid field on response body.
and /authenticate/verification requires that field on request body.
I have tried to get guid like this :
jsonPath("$..guid").saveAs("verificationGuid")
and pass it to other body :
.body(StringBody(s"{\"guid\":${verificationGuid}, \"code\":\"123456\"}"))
this is the code block:
def login = {
exec(http("Authenticate")
.post("/authenticate")
.body(StringBody(userString))
.headers(headerLogin)
.check(status is 200)
.check(jsonPath("$..guid").saveAs("verificationGuid"))
)
.exec(http( "Authenticate verify")
.post("/authenticate/verify")
.headers(headerLogin)
.body(StringBody(s"{\"guid\":${verificationGuid}, \"code\":\"123456\"}"))
.check(status is 200)
)
}
But it doesnt work, how can I do this?

Remove s from s"{\"guid\":${verificationGuid}, \"code\":\"123456\"}"). If s is in front of string every ${something} placeholder will be treated as Scala built in string interpolation and compiler will try to replace it with Scala variable, which in your case does not exist. Without s it will be treated as literal string and than caught by Gatling EL Parser and replaced with previously saved Gatling session attribute.

Related

Swagger - Why is Swagger creating a request body field when I have not written an annotation for one?

I have written a swagger ui for a GET request that doesn't need a request body. I haven't used the #RequestBody annotation so why is Swagger bringing up a request body field on the ui? Even if I leave it empty, it is causing my API requests to fail with the following error: TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.
I understand why this error exists, the curl that swagger creates has a -d option. But how can I switch this off?
The only annotations I've used are #Get, #Path, #Operation, #ApiResponses, and #Parameters.
Put simply, how can I tell swagger that I don't need a request body?
If you hadn't annotated some parameter of your method it is automatically considered request body. If you don't want it to, you have to explicitly annotate it as something else or annotate it to ignore param with something like #ApiParam(hidden = true):
// example usage of Swagger with Akka HTTP
#ApiOperation(
httpMethod = "GET",
response = classOf[ApiResponseX],
value = "docs"
)
#ApiImplicitParams(
Array(
new ApiImplicitParam(
name = "id",
dataType = "string",
paramType = "query",
value = "id docs"
)
)
)
def fetchX(
// even if this value has custom handling I have to explicitly ignore it,
// to not make it into a request body
#ApiParam(hidden = true) id: UUID
): Route = ...

RestAssured response validation using body and array as parameter

I am trying to validate a REST response. Is it possible to use an array as parameter to containsonly?
Ex:
String values[] = line.split(",");
given().
when().
then().
statusCode(200).
body("value", containsOnly(values));
Also, can we use variables as parameters to other methods like HasItems, equalTo etc?
Ex: body(HasItems(values))
Yes, You could use any appropriate matcher to check whole body or just part of it. Just take attention on a object type returned by pecified path - first argument of body().
Try this :
Response resp = RestAssured.given()
.header("Content-Type", "application/vnd.dpd.public.v1+json")
.body(FixtureHelpers.fixture("request/request.json"))
.post("/");
resp
.then()
.statusCode(200)
.body("random.object", CoreMatchers.equalTo("value"));
This would work for request.json object like :
{"random":{"object": "value"}}

Play Framework 2.4 how to use return statement in Action controller

is there a way to return a value inside Action controller.
I have a method in my User model which returns the number of friends of a given user.
def nrOfFriends(current_user: Long): Int = {
DB.withConnection{ implicit connection =>
var nr: Int = SQL("select count(*) from friend where user_id_1=" + current_user + " or user_id_2=" + current_user).as(scalar[Int].single)
nr
}
}
In my controller, I just want to return the value from the model
def freunde() = IsAuthenticated { username => _ =>
User.findByUsername(username).map { user =>
var nr: Int = Friend.nrOfFriends(user.id.get)
Ok(""+nr)
}.getOrElse(Forbidden)
}
But in the way that is written, it will print "empty string " concatenated with the number
If I replace Ok(""+nr) with Ok(nr) I receive the following error:
"Cannot write an instance of Int to HTTP response. Try to define a Writeable[Int]"
I need for my action to return a value so that I can pass the value from the action to header.views.html inside the navbar something like that
#Freund.freunde Friends
if you want your response to just be the value of nr you can simply call nr.toString:
def freunde() = IsAuthenticated { username => _ =>
User.findByUsername(username).map { user =>
var nr: Int = Friend.nrOfFriends(user.id.get)
Ok(nr.toString)
}.getOrElse(Forbidden)
}
The error you're getting makes reference to the fact that Int doesn't have an implicit Writeable[Int] in scope. So play doesn't know how display an Int in an http response.
You can add make Int writeable by putting this in scope:
implicit val intWriteable = play.api.http.Writeable[Int](_.toString.getBytes, None)
Then you would be able to just say:
Ok(nr)
without error.
However, it sounds like you just want the result of nrOfFriends inside an unrelated template. If that's the case, you should be using an Action at all. Instead just call your model function inside the template where you need the data.
#User.nrOfFriends(user.id) Friends
Of course you would need to pass in the user to the template as well.
You didn't post a full sample of all the code involved in what you are trying to accomplish so I think this is the best I can do for now. Perhaps try posting the base template that your <a> is in.
An important point is that Actions are for production an HTTP response, and not just plain data internally to the application.
An action of a controller handles a request and generates a result to be sent to the client. In other words, an action returns a play.api.mvc.Result value, representing the HTTP response to send to the web client. In your example Ok constructs a 200 OK response. The body of the response must be one of the predefined types, including text/plain, json, and html. The number of a friends is an integer and is NOT an acceptable type of the body. Therefore, a simple way to address this problem is to convert it into a text/plain using .toString().
On the other hand, you can define a writer for Int that lets Play know how to convert an integer into a json format.
For more details, please take a look at this https://www.playframework.com/documentation/2.2.x/ScalaActions.

PUT Request not happening at all in Fantom

I am having some trouble with PUT requests to the google sheets api.
I have this code
spreadsheet_inputer := WebClient(`$google_sheet_URI_cells/R3C6?access_token=$accesstoken`)
xml_test := XDoc{
XElem("entry")
{
addAttr("xmlns","http://www.w3.org/2005/Atom")
addAttr("xmlns:gs","http://schemas.google.com/spreadsheets/2006")
XElem("id") { XText("https://spreadsheets.google.com/feeds/cells/$spreadsheet_id/1/private/full/R3C6?access_token=$accesstoken"), },
XElem("link") { addAttr("rel","edit");addAttr("type","application/atom+xml");addAttr("href","https://spreadsheets.google.com/feeds/cells/$spreadsheet_id/1/private/full/R3C6?access_token=$accesstoken"); },
XElem("gs:cell") { addAttr("row","3");addAttr("col","6");addAttr("inputValue","testing 123"); },
},
}
spreadsheet_inputer.reqHeaders["If-match"] = "*"
spreadsheet_inputer.reqHeaders["Content-Type"] = "application/atom+xml"
spreadsheet_inputer.reqMethod = "PUT"
spreadsheet_inputer.writeReq
spreadsheet_inputer.reqOut.writeXml(xml_test.writeToStr).close
echo(spreadsheet_inputer.resStr)
Right now it returns
sys::IOErr: No input stream for response 0
at the echo statement.
I have all the necessary data (at least i'm pretty sure) and it works here https://developers.google.com/oauthplayground/
Just to note, it does not accurately update the calendars.
EDIT: I had it return the response code and it was a 0, any pointers on what this means from the google sheets api? Or the fantom webclient?
WebClient.resCode is a non-nullable Int so it is 0 by default hence the problem would be either the request not being sent or the response not being read.
As you are obviously writing the request, the problem should the latter. Try calling WebClient.readRes() before resStr.
This readRes()
Read the response status line and response headers. This method may be called after the request has been written via writeReq and reqOut. Once this method completes the response status and headers are available. If there is a response body, it is available for reading via resIn. Throw IOErr if there is a network or protocol error. Return this.
Try this:
echo(spreadsheet_inputer.readRes.resStr)
I suspect the following line will also cause you problems:
spreadsheet_inputer.reqOut.writeXml(xml_test.writeToStr).close
becasue writeXml() escapes the string to be XML safe, whereas you'll want to just print the string. Try this:
spreadsheet_inputer.reqOut.writeChars(xml_test.writeToStr).close

What changed in jQuery 1.9 to cause a $.ajax call to fail with syntax error

I'm making a REST DELETE call, which returns a 204. In jQuery 1.8.3 this works, and hits the request.done callback. But if I use 1.9 it goes to request.fail with a parsererror in the textStatus and a 'SyntaxError: Unexpected end of input' in the errorThrown.
remove = function (complete) {
var self = this;
var request = $.ajax({
context: self,
url: "/v1/item/" + itemId,
dataType: "json",
type: "DELETE"
});
request.done(removeCallback);
request.fail(function (xhr, textStatus, errorThrown) {
alert(errorThrown);
});
},
Anyone know what has changed in 1.9 that would cause this to fail, and what needs to change in order to fix it?
So, answering my own question it looks like this is in fact the problem:
From the jQuery upgrade guide
jQuery.ajax returning a JSON result of an empty string
Prior to 1.9, an ajax call that expected a return data type of JSON or JSONP would consider a return value of an empty string to be a success case, but return a null to the success handler or promise. As of 1.9, an empty string returned for JSON data is considered to be malformed JSON (because it is); this will now throw an error. Use the error handler to catch such cases.
So, if remove the dataType
dataType: "json",
It works in jQuery 1.8.3 and 1.9.
An HTTP 204 response is not an empty string: it means there is no data. This is a valid response for delete and update operations.
This looks like a bug introduced in JQuery 1.9.
The reason removing the dataType property fixes this is because when it's set to "json" JQuery attempts to parse the content using JSON.parse and failing as a result. From the ticket:
This won't fail with any other dataType than "json" because the
regression is due to the re-alignment of parseJSON with native
JSON.parse (throwing an exception for null/undefined values).
Don't try the workaround suggested in the ticket of adding a handler for the 204 via the statusCode property, because both that handler and the error handler will be triggered. A possible solution is the following:
$.ajax(url, {
type: "DELETE",
dataType: "json",
error: function (error) {
if (error.status === 204) {
// Success stuff
}
else {
// fail
}
}});
I was having a very similar problem, and you helped my find my answer - so thank you. My solution, however is slightly different, so I figured I would share it.
As stated in the question, on the JQuery website it says:
Prior to 1.9, an ajax call that expected a return data type of JSON or JSONP would consider a return value of an empty string to be a success case, but return a null to the success handler or promise. As of 1.9, an empty string returned for JSON data is considered to be malformed JSON (because it is); this will now throw an error. Use the error handler to catch such cases.
I was passing JSON data to a method on my server with "void" as a return type because I did not need to do anything with returned data in the success function. You can no longer return null when passing JSON in an AJAX request in JQuery 1.9 +. This was possible in previous versions of JQuery however.
To stop getting an error and get the success function to fire instead, you must simply return valid JSON in your AJAX request. It doesn't matter what you pass, as long as it's valid, because (in my case anyways) you are not using the returned data.
The problem seems to be that jQuery treats the empty body (where Content-Length is 0) of a 204 response as "". Which is one interpretation, but the downside is that "" gets treated like any other response string. So if you have called jQuery.ajax() with the dataType:json option, jQuery tries to convert "" to an object and throws an exception ("" is invalid JSON).
jQuery catches the exception and recovers, but if you prefer to avoid the exception altogether (in your development environment) you might do something like the following. Add in the "converters" option to jQuery.ajax() and use it to change "" responses to nulls (I do this when dataType is json). Something like :
var ajax_options =
{
/* ... other options here */
"converters" :
{
"text json" :
function( result )
{
if ( result === "" ) result = null;
return jQuery.parseJSON( result );
}
}
};
var dfd = jQuery.ajax( ajax_options );