Gatling request body as bytearray - scala

val scn = scenario("gatling test").
feed(circularfeeder.circular)
.exec(http("request")
.post(endpoint)
.header("Content-Type", "application/json")
.header("Accept-Encoding", "charset=UTF-8")
.body(StringBody("""${request}"""))
.check(status.is(200))
The above code is used to send every circularfeeder data as a string to the body of the request. Suppose if i want to send as byte array instead of string in the body how do I modify the line .body(StringBody("""${request}"""))
The code .body(ByteArrayBody(getBytesData("""${request}"""))) does not work. Any advise?

Option 1
Call getBytes method on request string and pass that to ByteArrayBody
.body(ByteArrayBody { session =>
session("request")
.validate[String]
.map(s => s.getBytes(StandardCharsets.UTF_8))
})
Option 2
Convert the raw data you got from your feeder.
val circularfeeder = csv("myFile.csv").convert {
case ("request", string) => string.getBytes(StandardCharsets.UTF_8)
}
...
.body(ByteArrayBody("${request}"))

Related

Gatling session - get attribute as Long

I am a new in Scala and got some problems with casting from String to Long. I try to get Gatling session value as Long in request. Before in exec() part, I try to set the userId value
def setUserId(): ChainBuilder = {
exec(session => session
.set("userId", Random.nextLong())
)
}
Next, in request creator I want to use it like that because I need a new userId every call:
object UserRequestCreator {
def sampleUserRequest(currency: String): Request = {
Data data = new Data()
data.setUserId("${userId}".toLong)
data.setCurrency(currency)
}
}
Test scenario:
exec(setUserId())
.exec(http("postUser")
.post(endpointUser).asXml
.headers(headers)
.body(StringBody(toXmlString(sampleUserRequest("EUR"), classOf[Request])))
.check(status.is(200))
but receive error:
java.lang.NumberFormatException: For input string: "${userId}"
How to fix that in Scala?
I also try Long.valueOf, JLong.parseLong("${userId"}, 16), Try(BigDecimal(...)) and more but nothing can help. I think the problem is with $ symbol, but I don't see any different way to get this value from the session. Maybe it is possible to store Long in the Gating session?
From the documentation and based on your current code, one way to do it is like that:
// with a function payload
http("name").post("/")
.body(StringBody(session => s"""{ "foo": "${session("dynamicValueKey").as[String]}" }"""))
Thus, in your case:
StringBody(session => toXmlString(sampleUserRequest(session)("EUR"), classOf[Request])
def sampleUserRequest(session: Session)(currency: String): Request = {
//...
data.setUserId(session("userId").as[Long])
}

Modify a JSON response to send back to the api in Gatling/Scala

I am doing some Gatling and since I never do scala, I am kind of lost.
I want to modify the JSON response from a JsonPath I receive before sending it back
My code look like this
.exec(
http("Get call")
.get("getEndpoint")
.check(jsonPath("$.value").saveAs("RESPONSE_DATA"))
)
.exec(
http("Post call")
.post("postEndpoint")
.header("content-type", "application/json")
.body(StringBody("${RESPONSE_DATA}"))
.asJson
)
For example, I want to change to the first name of the user receive in Json from the Get Call. I can't manage to find an answer to Gatling documentation
Thanks to Lars comment, I manage to find a solution. I was too focus on finding the specific method for Gatling that I forgot the basic way to do programming
Here the new code
.exec(
http("Get call")
.get("getEndpoint")
.check(jsonPath("$.value").saveAs("RESPONSE_DATA"))
)
.exec(session =>
{
// put body response into variable
val response = session("RESPONSE_DATA").as[String];
// generate random string as you convenience
val randomString = Random.alphanumeric.filter(_.isLetter).take(5).mkString;
// use replace method to modify your json (which is right now a string)
newResponse = response.replace(
"""specificKey":""",
"""specificKey":""" + randomString + "",
)
session
}.set("RESPONSE_DATA", newResponse)
// ^ really important to set the new value of session outside of brackets !!
)
.exec(
http("Post call")
.post("postEndpoint")
.header("content-type", "application/json")
.body(StringBody("${RESPONSE_DATA}"))
.asJson
)
Not the cleaner code I did, but it works.

Check string in gatling simulation

Trying to check if a string exists on the body. Similar to checking status which is .check(status.is(200)). I want to check for string as well. tried .check(bodyString.is("greeting")) but got an error:
val scn = scenario("GreetingPages")
.during(testTimeSecs) {
exec(
http ("greeting")
.get("/greeting")
.check(status.is(200))
.check(bodyString.is("Greeting"))
).pause(minWaitMs,maxWaitMs)
.exec(
http("greeting1")
.get("/greeting1")
.check(status.is(200))
.check(bodyString.is("Greeting1"))
).pause(minWaitMs,maxWaitMs)
.exec(
http("Third page")
.get("/greeting2")
.check(status.is(200))
.check(bodyString.is("Greeting2"))
).pause(minWaitMs,maxWaitMs)
}
---- Errors --------------------------------------------------------------------
bodyString.find.is(Greeting), but actually found {"message":"G 9 (47.37%)
reeting"}
bodyString.find.is(Greeting1), but actually found {"message":" 5 (26.32%)
Greeting1"}
bodyString.find.is(Greeting2), but actually found {"message":" 5 (26.32%)
Greeting2"}
The reason is the bodyString return the full response body, as it described in the documentation.
You could use in matcher (you can see the implementation here - look for InMatcher[A], but it won't work because you need to switch expected.contains(actualValue) with expected.contains(expected)
I suggest you implement your own MyOwnInMatcher:
class MyOwnInMatcher[A](expected: Seq[A]) extends Matcher[A] {
def name: String = "customIn"
protected def doMatch(actual: Option[A]): Validation[Option[A]] = actual match {
case Some(actualValue) =>
if (expected.contains(actualValue))
actual.success
else
s"found $actualValue".failure
case _ => Validator.FoundNothingFailure
}
}
and use it:
.check(jsonPath("$.message").validate(customIn("Greeting")))), which checks if "Greeting" exists in the message attribute of the json response body.

Gatling2: Get response body as byte array

I want to send a request and will receive a byte[] body response. Based on this byte[] response I want to extract a value (using protobuf) and the reuse this value in another resquest.
After some hours search, I cannot find a possibility to extract the http response body as a byte array:
val httpConfig = http
.baseURL("http://www.whatever.com")
val request = exec(http("FirstRequest")
.post("/message")
.body(new ByteArrayBody((session: Session) => getFirstRequest(session)))
.check(status.is(200), ???getByteResponse???))
val response = exec(http("SecondRequest")
.post("/message")
.body(new ByteArrayBody((session: Session) => getSecondRequest(session)))
.check(status.is(200), ???getByteResponse???))
val scn = scenario("Request").exec(request,response)
setUp(scn.inject(atOnce(1 user)))
.protocols(httpConfig)
Alternatively it would also be fine if I could set a value in getFirstRequest, that I can reuse in getSecondRequest:
private def getFirstRequest(session: Session): Array[Byte] = {
... setting a session attribute ... (long)
... some protobuf stuff returning a byte array ...
}
private def getSecondRequest(session: Session): Array[Byte] = {
var value= session("value").as[Long]
... some protobuf stuff using value from session and then returning byte array...
}
I think you can try something like this :
.check(status.is(200), bodyBytes.saveAs("responseBody"))
This will save the body of the response in the virtual user's session.

How to convert request.body to a byte array in order to calculate MD5?

I'm creating a scala function in a Play! application that authenticates requests to my web-service. The authentication is basically an HMAC authentication. The method receives the type of bodyParser to be used. Since I don't know the type of the -bodyParser, how can I convert request.body to a generic Array[Byte] on which I can run my MD5 processing?
def Authenticated[T](authType : AuthenticationType, bodyParser : BodyParser[T])(f : (Request[T]) => Result) = {
Action(bodyParser) { request =>
// Authentication logic starts here
// TODO: Something like: var bodyData : Array[Byte] = request.body.toByteArray()
// The rest is easy...
var contentMD5 = calculateMD5(bodyDat)
f(request)
}
}
Any request body received by Play can be parsed to a Http.RawBuffer which can give a pure a raw byte array representation of your request body.
The line of code you're looking for is
var bodyData : Array[Byte] = request.body.asRaw.asBytes()