dimanche 29 septembre 2013

Gatling dynamic parameters example

It is very easy to create a stress test with Gatling when you know the parameters to send within each HTTP request. But sometimes you have to handle dynamic parameters and this is more complicated to manage.

A typical case where dynamic parameters are needed is when you are testing a page with a form protected with a CSRF protection, for example :

<form action="/deleteAccount" method="POST">
  <input type="hidden" name="login" value="jsebfranck"/>
  <input type="hidden" name="verificationToken" value="wQvhCLsPHVbKd9ANoOZTpBsXtVhpG0h3"/>
</form>

For each display of this form, the verificationToken parameter expected on the server side will be different. This protection against CSRF attacks allows to be sure that the POST request is send from a form generated by the website, and not from another website.

If you use the gatling recorder to display the form page then submit the form, it will generate the following test :

val scn = scenario("delete account")
      .exec(http("get delete account page")
        .get("/Account/Delete")
        .headers(headers_1))
      .exec(http("delete account")
        .post("/Account/Delete")
        .headers(headers_5)
        .param("verificationToken", "wQvhCLsPHVbKd9ANoOZTpBsXtVhpG0h3")
        .param("login", "jsebfranck"))

The problem with this test is that it always sends the same verificationToken parameter within the form. So if you launch it, it will failed because the verificationToken will be different from the expected verificationToken.

To resolve this problem you have to parse the page with the form in order to retrieve the verificationToken parameter and to send it within the form. To do that you can use two advanced features of gatling, the "session" and the "saving data" features :

val scn = scenario("delete account")
      .exec(http("get delete account page")
        .get("/Account/Delete")
        .headers(headers_1)
        .check(
          regex("""<input name="verificationToken" type="hidden" value="([^"]*)" />""")
          .saveAs("requestVerificationToken")))
      .exec(http("delete account")
        .post("/Account/Delete")
        .headers(headers_5)
        .param("verificationToken", "${requestVerificationToken}")
        .param("login", "jsebfranck"))

The check method allows to do operations on the result of the request. Here we apply a regex to get the content of the value attribute, then we save it in the requestVerificationToken variable with the saveAs method :

    .check(
      regex("""<input name="verificationToken" type="hidden" value="([^"]*)" />""")
      .saveAs("requestVerificationToken")))

Then we can reuse the requestVerificationToken variable to send it within the form :

    .param("verificationToken", "${requestVerificationToken}")

Now you are able to use dynamic parameters in a Gatling test. I hope this example will help you to bypass most of the constraints of a website. For further information on gatling advanced usages, please visit this page.

2 commentaires:

  1. Hi Jean-Sébastien FRANCK,
    i tried with regex to capture CSRF but the request is getting failed

    .check(
    regex("""&gtinput name="verificationToken" type="hidden" value="([^"]*)" / &lt""")
    .saveAs("requestVerificationToken")))

    same thing which i used for configuring CSRF

    Thanks in advance

    any help or suggestions are appreciable

    RépondreSupprimer
  2. Merci! This worked for me on .Net Core web pages where the CSRF name was
    <input name="__RequestVerificationToken" instead of verificationToken

    RépondreSupprimer