struggling with cookies in Gatling

Hi all,

I’m new to Gatling, but I took my first hurldles. But now I am facing challenges that neither the Gatling documentation nor my searches through the internet are helpful with. And my problem should be straightforward: I want to read cookies and use them in my scenario. (I expected that to be a piece of cake…) So I’m sure it is my ignorance as a newbee to Gatling. Here is my scenario.


private val scn = scenario("RAPtest")
.exec(
http("Home")
.get("/")
)
.pause(2)
.exec { session =>
session.set("sessID",getCookieValue(CookieKey("PHPSESSID")).toString)
}
.exec(
http("request_23")
.patch("/api/v1/resource/#{sessID}\"/1")
.headers(headers_23)
.body(StringBody(s"""{ "op":"replace",
"path":"/Login/#{sessID}/Login/#{sessID}}/Userid",
"value":"stefj"
} """)).asJson
.resources(
http("request_25")
.get(s"/api/v1/resource/#{sessID}/1/Login")
.headers(headers_2)
)
)

I hope it is clear what I want. After getting the home page, there is a cookie (named “PHPSESSID”), which contains the session id.
I want to store the value of that cookie in a variable, sessID, to be used in request-23. Nothing I tried has worked. The attempt shown above seems to come closest.

Request_23 fails with the following in the log:

11:42:36.301 [DEBUG] i.g.h.e.r.DefaultStatsProcessor - Request 'request_23' failed for user 1: status.find.in(200,201,202,203,204,205,206,207,208,209,304), found 500
11:42:36.303 [TRACE] i.g.h.e.r.DefaultStatsProcessor -
>>>>>>>>>>>>>>>>>>>>>>>>>>
Request:
request_23: KO status.find.in(200,201,202,203,204,205,206,207,208,209,304), found 500

.exec { session =>
session.set(“sessID”,getCookieValue(CookieKey(“PHPSESSID”)).toString)
}

You’re using getCookieValue wrongly. Please read the documentation: https://gatling.io/docs/gatling/reference/current/http/helpers/#getting-cookie-value

I am aware of the fact that it is wrong. I have also read the documentation: https://gatling.io/docs/gatling/reference/current/http/helpers/#getting-cookie-value. However I was not able to get it right. Do you have a suggestion? Is it my newness to scala maybe?

The doc states:

exec(getCookieValue(CookieKey("name")));
CookieKey("name")
  .withDomain("domain")
  .withPath("path")
  .withSecure(true)
  .saveAs("key");

If I do that, I get an error message: i.g.h.a.c.GetCookieBuilder$$anon$1 - ‘getCookie-4’ failed to execute: No CookieJar in session.

I get that with the following scenario:


private val scn = scenario("RAPtest")
.exec(
http("Home")
.get("/")
)
.exec(getCookieValue(CookieKey("PHPSESSID")))

Which exactly means no Cookie has been received at this point in the scenario.

I have tried to reconstruct why I did exec { session => ???}.
Since scala is a functional language, I wanted to use the cookie value directly in en EL-expression, for example in

.patch("/api/v1/resource/#{getCookieValue(CookieKey(“PHPSESSID”))}"/1")
For some reason, this doesn’t work. Probably getCookieValue is an object and perhaps I may not use an object as a function, but I could not really find out why. But apparently, the contents of #{…} requires a variable (I’m not used to that in Haskell, but Scala may be different on this point…). So I used a variable, sessID, to store the cookie value in.

Then I need a way to transport the content of the cookie to the variable sessID. I am taking the value of the cookie ( getCookieValue(CookieKey(“PHPSESSID”)) ) and assign it to “sessID” by means of session.set. That yields

session.set(“sessID”,getCookieValue(CookieKey(“PHPSESSID”)).toString). But where to put that statement? That is where the exec { session => …} construct came in.

So apparently I am making big mistakes, but I haven’t been able to find the flaws in my thinking.

I have tried your suggestion, of course, but I couldn’t use the result in request_23. Could you please give me an example of how this is done?

That has occurred to me, so I checked thoroughly what is being communicated. I saved a .har-file to prove it and trace it. And the cookie is definitely there. The “Home” event in my scenario (being exec(HTTP(“Home”).get("/") ) produces this very cookie.
This is what I see in the .har-file:

{
“name”: “cookie”,
“value”: “GUEST_LANGUAGE_ID=nl_NL; ounllang=nl_NL; _ga=GA1.2.1734014253.1610008762; _ga_R12VNJGEGL=GS1.1.1636627129.8.0.1636627150.0; PHPSESSID=4b0d070bcfe0b4ad832767e0f1fd693c”
}
and

{
“name”: “PHPSESSID”,
“value”: “4b0d070bcfe0b4ad832767e0f1fd693c”,
“path”: “/”,
“domain”: “rap.cs.ou.nl”,
“expires”: “1969-12-31T23:59:59.000Z”,
“httpOnly”: true,
“secure”: false
}
so somehow Gatling doesn’t get to that cookie.

Do you have a working example for this use-case?

What you see in the cookies in the HAR file shows the cookies that are already set (they could have as well been set prior to your recording).
You must look for the Set-Cookie header in the responses so you can figure out which request has a response that sets it.

Thank you! Your answer really triggered my thinking. It made me realize that I’m not running from a browser, as I’m used to, but from Gatling on my laptop. So there is NO session-id to communicate to the server. What I need is a different sessionID for each different virtual user and I need to make that in the Gatling scenario. I guess I could use session.userID for that purpose? My scenario would look something like this:


private val sessId = "4b0d070bcfe0b4ad832767e0f1fd693c" // TODO: use a feeder instead of this constant

private val headers_0 = Map(
"cookie" -> ("PHPSESSID="+sessId)

private val scn = scenario("RAPtest")
.exec(
http("Home")
.get("/")
.headers(headers_0)
)
.exec(
http("request_23")
.patch("/api/v1/resource/"+sessId+"/1")
.headers(headers_23)
.body(StringBody(s"""{ "op":"replace",
"path":"/Login/"""+sessId+"""/Login/"""+sessId+"""/Userid",
"value":"stefj"
} """)).asJson
.resources(
http("request_25")
.get(s"/api/v1/resource/"+sessId+"/1/Login")
.headers(headers_2)
)
)

Now I can understand your earlier comment “Why use cookies in the first place?” better.
Thanks again and happy holidays.

Cookies can originate from 2 sources:

  • set from the server with a Set-Cookie header in a response. Gatling handles this case automatically for you, just like a browser.
  • set in Javascript from the client. Here you would have to use Gatling’s addCookie

You have to figure out the origin of your cookies. If you’re recording (HAR or Recorder), make sure to record in fresh anonymous mode so you don’t have the cookies already set and end up bypassing the steps that would set them.

Note: if you’re beginning with Gatling, I really recommend you go with the new Java DSL that was introduced in Gatling 3.7 instead of the Scala one. Not that it’s better, but you won’t have the Scala psychological barrier.