Search code examples
scalagatling

adding attribute to session


I want to use different login methods (Bearer or JWT) for logging in. So I've created this object to reuse in simulations:

object Login {
  private val login: String = ConfigObject.config("login").asInstanceOf[String]
  private val password: String = ConfigObject.config("password").asInstanceOf[String]
  private val useBearer: Boolean = ConfigObject.config("useBearer").asInstanceOf[Boolean]
  private val bearerToken: String = ConfigObject.config("authToken").asInstanceOf[String]

  var loginAction: ChainBuilder = _

  loginAction = exec { session =>
    if (useBearer) {
      val bearerTokenString = s"Bearer $bearerToken"
      session.set("token", bearerTokenString)
    } else {
      http("Login user")
        .post("/auth/token/obtain")
        .body(StringBody(s"""{ "email": "$login", "password":"$password" }""")).asJson
        .headers(Map("Content-Type" -> "application/json"))
        .check(jsonPath("$.token").saveAs("jwtToken"))
      val jwtToken = session("jwtToken").as[String]
      session.set("token", s"JWT $jwtToken")
    }
    session
  }
}

but when I try to build headers like this I'm getting Failed to build request: No attribute named 'token' is defined

val headers: Map[String, String] = Map(
      "Content-Type" -> "application/json",
      "Authorization" -> "${token}")

I'm not very familiar with scala and gatling so please guide me how to do this properly


Solution

  • there are a couple of reasons for why your example doesn't work.

    The reason setting 'token' doesn't work is that sessions are immutable - session.set returns a new session, but you're returning the initial one on the very last line of 'loginAction'

    Your jwt flow also won't work. The gatling dsl defines builders that are created at startup - these are used to generate all the steps that a user will follow once they are injected. You can't create extra instructions via session functions during the simulation - which is what you're attempting to do here. So everything in your 'else' block will never be executed.

    you could either handle everything within gatling actions, or change loginAgction to return a ChainBuilder rather than be a session function like this...

    def loginAction: ChainBuilder =
      if (useBearer) {
        exec(session => session.set("token", s"Bearer $bearerToken")) //returns a new session
      } else {
        exec(http("Login user")
          .post("/auth/token/obtain")
          .body(StringBody(s"""{ "email": "$login", "password":"$password" }""")).asJson
          .headers(Map("Content-Type" -> "application/json"))
          .check(jsonPath("$.token").transform(token => s"JWT $token").saveAs("token"))
        )
      }