Gatling 1.5.x: Add HMAC authorization header with EvaluatableString

Hi all,

What would be a better (more functional) way to add an authorization header to an request which URL is based on a dynamic string?

Thanks for your help in advance,
Lars

Here is how the code currently looks like …

package scenarios

import com.excilys.ebi.gatling.core.Predef._
import com.excilys.ebi.gatling.http.Predef._

import akka.util.duration._

import bootstrap._
import basic.{Configuration, Auth}
import net.jalg.hawkj.{Algorithm, HawkContext}

object Navigation {

val productIds = csv(“product_ids.csv”).random

def getAuthorizationHeader(verb: String, path: String): String = {
val ctxt = HawkContext
.request(verb, path, Configuration.HOST, 443) // Assume HTTPS all over the place
.credentials(Configuration.CLIENT_ID, Configuration.CLIENT_KEY, Algorithm.SHA_256)
.tsAndNonce(System.currentTimeMillis() / 1000, “e0bee6ad552d”)
.build()
ctxt.createAuthorizationHeader().toString
}

val scn = scenario(“Scenario Navigation”)
.repeat(2) {
feed(productIds)
.exec(session =>
session
// TODO Inject ??
.setAttribute(“product_url”, “/api/products/” + session.getTypedAttribute(“product_id”))
.setAttribute(“auth_header”, getAuthorizationHeader(“GET”, “/api/products/” + session.getTypedAttribute(“product_id”)))
)
.exec(
http(“request_product”)
.get("${product_url}")
.header(“Authorization”, “${auth_header}”)
.header(“Accept”, “application/vnd.example.product+xml”)
.check(status.is(200)))
.pause(5 milliseconds, 50 milliseconds)
}

}

PS: I found a post which seem to address a similar problem: https://groups.google.com/forum/#!searchin/gatling/hmac$20header/gatling/Xnmn1NepiTQ/VzRBWvqdZ2AJ
but am not able to see how this could work out for Gatling 1.

Session.getAttributeAsOption handles missing attribute, but not type errors, but that’s the best you can have with Gatling 1.

.exec { session =>
val updatedSession =
for {
productId ← session.getAttributeAsOptionString
authorizationHeader = getAuthorizationHeader(“GET”, “/api/products/” + productId)
} yield session
.setAttribute(“product_url”, productId)
.setAttribute(“auth_header”, authorizationHeader)

updatedSession.getOrElse(session)
}

Thanks for your answer, Stéphane.

Actually I was interested to know if there is a way to get rid of the setAttribute block by evaluating the product_id attribute inside the getAuthorizationHeader method and by which means? How to resolve with the help of ELParser?

http(“request_product”)
.get("/api/products/${product_id}") // ← works fine

.header(“Authorization”, getAuthorizationHeader(“GET”, “/api/products/${product_id}”)) // ← how to evaluate product_id ?

Thanks,
Lars

The thing is Gatling 1 Session API can’t handle missing attributes and non matching types properly, so you have to be sure that the attribute exists and it has the correct type (which is sure if it’s injected by a feeder, but not if it’s captured on a response because the request might have crashed).
If not, you’ll get an Exception. Gatling should handle it properly, but creating Exceptions is an expensive process, hence the Gatling 2 API based on Validation.

so:
.header(“Authorization”, session => getAuthorizationHeader(“GET”, “/api/products/” + session.getTypedAttributeString))