Gatling2: Get response body as byte array - scala

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.

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])
}

Gatling request body as bytearray

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}"))

I am not able to log in into the app using Gatling

I am new to Gatling facing some trouble while log in into the application.
There is an API which provides a random no and public key, I have to save these values so that I can parse them to next step.
Next step is a post request for entering User-id and password, password gets encrypted.
Also I have to save XSRF token from the cookie to maintain the session.
Then there is O.T.P authentication which I have to fetch from Rest API.
how do i need to perform all the above in sequence
object Actions {
def retrieveAuthData(session: Session, datakey: String): AuthData = {
// get response as a string
val t: String = session.get(datakey).as[String];
// retrieve parameters from json
val publicKey: String = a("PublicKey").asInstanceOf[String];
val random: String = a("Random").asInstanceOf[String];
val ds3: Boolean = a("DS3").asInstanceOf[Boolean];
val twoFA: Boolean = a("TwoFa").asInstanceOf[Boolean];
return new AuthData(publicKey, random, ds3, twoFA);
}
}

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()

HTTP CacheControl with Jersey and json implementation

I want to add the CacheControl intormation to a GET service that use the json binding.
I found that to add the cacheControl to a response the REST service sound like this:
#GET
#Path("cacheheadertest")
#Produces({"*/*"})
def testcache():javax.ws.rs.core.Response {
val rb:Response.ResponseBuilder = javax.ws.rs.core.Response.ok("chached test message")
val cc = new CacheControl()
cc.setMaxAge(60)
cc.setNoCache(false)
rb.cacheControl(cc).build()
}
but I have a REST service that produce json messages and the jersey library transform automaticcally the java object from java to xml/json.
#GET
#Path("jsontestcache")
#Produces(Array(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML))
def myjsontestservice(#HeaderParam("X-TOKENID") tokenId: String,
#QueryParam("clientId") clientId: String):com.test.MyResultClass = {
val response= new com.test.MyResultClass
[...]
response
}
How can I add the cache control to the response of myjsontestservice service? Do I need to use a filter and append the cachecontrol once the response has been created by jersey?
thanks million
Flavio
You would still need to return a Response object.
def somejson() : Response = {
val builder = Response.ok(new com.test.MyResultClass);
val cc = new CacheControl()
cc.setMaxAge(60)
cc.setNoCache(false)
builder.cacheControl(cc).build()
}
Jersey's interceptors will automatically convert your class into a JSON object.